diff --git a/.eslintrc b/.eslintrc
index 08b899e7..477eb3ee 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -3,7 +3,7 @@
"react": {
"pragma": "React",
"version": "16.6",
- "flowVersion": "0.78" // Flow version
+ "flowVersion": "0.109.0" // Flow version
}
},
// babel parser to support ES6/7 features
@@ -139,7 +139,7 @@
// react
"react/display-name": 0,
- "react/jsx-no-bind": 2,
+ "react/jsx-no-bind": 0,
"react/jsx-no-duplicate-props": 2,
"react/jsx-no-undef": 2,
"react/jsx-pascal-case": 2,
@@ -153,7 +153,7 @@
"react/no-string-refs": 2,
"react/no-unknown-property": 2,
"react/prefer-es6-class": 2,
- "react/prop-types": 2,
+ "react/prop-types": 0,
"react/react-in-jsx-scope": 0,
"react/self-closing-comp": 2,
"react/sort-comp": 0,
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 8f8f6074..6cedeeae 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -70,15 +70,16 @@ yarn compile
yarn compile --watch
```
-## Website and visual tests
+## Documentation and visual tests
To run the interactive storybook:
```
-yarn website
+yarn docs
```
-When you're also making changes to the 'react-native-web' source files, run this command in another process:
+When you're also making changes to the 'react-native-web' source files, run this
+command in another process:
```
yarn compile --watch
diff --git a/package.json b/package.json
index d8aefc57..38efd4a8 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"version": "0.11.7",
- "name": "react-native-web-monorepo",
+ "name": "monorepo",
"scripts": {
"clean": "del-cli ./packages/*/dist",
"compile": "npm-run-all clean -p \"compile:* -- {@}\" --",
@@ -9,10 +9,8 @@
"compile:es": "cd packages/react-native-web && babel --root-mode upward src --out-dir dist --ignore \"**/__tests__\"",
"benchmarks": "cd packages/benchmarks && yarn build",
"benchmarks:release": "cd packages/benchmarks && yarn release",
- "examples": "cd packages/examples && yarn build",
- "examples:release": "cd packages/examples && yarn release",
- "website": "cd packages/website && yarn start",
- "website:release": "cd packages/website && yarn release",
+ "docs": "cd packages/docs && yarn start",
+ "docs:release": "cd packages/docs && yarn release",
"flow": "flow",
"fmt": "prettier --write \"**/*.js\"",
"jest": "jest --config ./scripts/jest/config.js",
@@ -21,7 +19,7 @@
"precommit": "lint-staged",
"prerelease": "yarn test && yarn compile && yarn compile:commonjs",
"release": "node ./scripts/release/publish.js",
- "postrelease": "yarn benchmarks:release && yarn examples:release && yarn website:release",
+ "postrelease": "yarn benchmarks:release && yarn docs:release",
"test": "yarn flow && yarn lint:check && yarn jest --runInBand"
},
"devDependencies": {
diff --git a/packages/docs/.storybook/_webpack.config.js b/packages/docs/.storybook/_webpack.config.js
new file mode 100644
index 00000000..77de6167
--- /dev/null
+++ b/packages/docs/.storybook/_webpack.config.js
@@ -0,0 +1,20 @@
+const path = require('path');
+const webpack = require('webpack');
+
+module.exports = async ({ config, mode }) => {
+ config.module.rules.push({
+ test: /\.(gif|jpe?g|png|svg)$/,
+ use: {
+ loader: 'url-loader',
+ options: { name: '[name].[ext]' }
+ }
+ });
+
+ config.resolve.extensions = ['.web.js', '.js', '.json', '.web.jsx', '.jsx'];
+
+ config.resolve.alias = {
+ 'react-native': 'react-native-web'
+ };
+
+ return config;
+};
diff --git a/packages/docs/.storybook/addons.js b/packages/docs/.storybook/addons.js
new file mode 100644
index 00000000..0748e932
--- /dev/null
+++ b/packages/docs/.storybook/addons.js
@@ -0,0 +1 @@
+// import '@storybook/addon-options/register';
diff --git a/packages/docs/.storybook/config.js b/packages/docs/.storybook/config.js
new file mode 100644
index 00000000..0dc1c204
--- /dev/null
+++ b/packages/docs/.storybook/config.js
@@ -0,0 +1,48 @@
+import { create } from '@storybook/theming';
+
+// import centered from './decorator-centered';
+import { addParameters, configure, addDecorator } from '@storybook/react';
+
+// Option defaults:
+addParameters({
+ options: {
+ storySort: (a, b) => {
+ const sectionA = a[1].id.split('-')[0];
+ const sectionB = b[1].id.split('-')[0];
+
+ return sectionB.localeCompare(sectionA);
+ },
+ theme: create({
+ base: 'light',
+ brandTitle: 'React Native for Web',
+ brandUrl: 'https://necolas.github.io/react-native-web'
+ // To control appearance:
+ // brandImage: 'http://url.of/some.svg',
+ }),
+ /**
+ * regex for finding the hierarchy separator
+ * @example:
+ * null - turn off hierarchy
+ * /\// - split by `/`
+ * /\./ - split by `.`
+ * /\/|\./ - split by `/` or `.`
+ * @type {Regex}
+ */
+ hierarchySeparator: /\/|\./,
+ /**
+ * regex for finding the hierarchy root separator
+ * @example:
+ * null - turn off multiple hierarchy roots
+ * /\|/ - split by `|`
+ * @type {Regex}
+ */
+ hierarchyRootSeparator: /\|/,
+ panelPosition: 'bottom'
+ }
+});
+
+// addDecorator(centered);
+
+const context = require.context('../src', true, /\.stories\.(js|mdx)$/);
+
+configure(context, module);
diff --git a/packages/website/storybook/.storybook/decorator-centered.js b/packages/docs/.storybook/decorator-centered.js
similarity index 76%
rename from packages/website/storybook/.storybook/decorator-centered.js
rename to packages/docs/.storybook/decorator-centered.js
index c29c0adc..3e97d96d 100644
--- a/packages/website/storybook/.storybook/decorator-centered.js
+++ b/packages/docs/.storybook/decorator-centered.js
@@ -3,9 +3,7 @@ import { StyleSheet, View } from 'react-native';
const styles = StyleSheet.create({
root: {
- minHeight: '100vh',
- maxWidth: 680,
- marginHorizontal: 'auto'
+ maxWidth: '100%'
}
});
diff --git a/packages/docs/.storybook/presets.js b/packages/docs/.storybook/presets.js
new file mode 100644
index 00000000..353aa94d
--- /dev/null
+++ b/packages/docs/.storybook/presets.js
@@ -0,0 +1,10 @@
+module.exports = [
+ {
+ name: '@storybook/addon-docs/preset',
+ options: {
+ configureJSX: true,
+ babelOptions: {},
+ sourceLoaderOptions: null
+ }
+ }
+];
diff --git a/packages/website/storybook/.storybook/babel.config.js b/packages/docs/babel.config.js
similarity index 100%
rename from packages/website/storybook/.storybook/babel.config.js
rename to packages/docs/babel.config.js
diff --git a/packages/docs/package.json b/packages/docs/package.json
new file mode 100644
index 00000000..1af9f359
--- /dev/null
+++ b/packages/docs/package.json
@@ -0,0 +1,23 @@
+{
+ "private": true,
+ "name": "docs",
+ "version": "0.11.7",
+ "scripts": {
+ "build": "build-storybook --docs -o ./dist -c ./.storybook",
+ "start": "start-storybook --docs -p 9001 -c ./.storybook",
+ "release": "yarn build && git checkout gh-pages && rm -rf ../../docs && mv dist ../../docs && git add -A && git commit -m \"Deploy documentation\" && git push origin gh-pages && git checkout -"
+ },
+ "dependencies": {
+ "@storybook/addon-docs": "5.3.0-alpha.43",
+ "@storybook/addon-options": "5.3.0-alpha.43",
+ "@storybook/cli": "5.3.0-alpha.43",
+ "@storybook/react": "5.3.0-alpha.43",
+ "@storybook/theming": "5.3.0-alpha.43",
+ "react-native-web": "0.11.7"
+ },
+ "devDependencies": {
+ "babel-plugin-react-native-web": "0.11.7",
+ "url-loader": "^2.2.0",
+ "webpack": "^4.41.2"
+ }
+}
diff --git a/packages/docs/src/apis/AppRegistry/AppRegistry.stories.mdx b/packages/docs/src/apis/AppRegistry/AppRegistry.stories.mdx
new file mode 100644
index 00000000..c7cb7993
--- /dev/null
+++ b/packages/docs/src/apis/AppRegistry/AppRegistry.stories.mdx
@@ -0,0 +1,107 @@
+import { Meta, Props } from '@storybook/addon-docs/blocks';
+
+
+
+# AppRegistry
+
+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`.
+
+## Methods
+
+### getAppKeys()
+
+Returns an array of all registered app keys
+
+```js
+const appKeys = AppRegistry.getAppKeys();
+```
+
+### getApplication(appKey, appParams)
+
+A web-only method for server-side rendering to HTML and CSS. It returns an
+object containing the given application's element and a function to get styles
+once the element is rendered.
+
+Additional props can be passed to the `getStyleElement` function, e.g., your CSP
+policy may require a `nonce` to be set on style elements.
+
+```js
+const appKey = 'MyApp';
+const appParams = { ... };
+const { element, getStyleElement } = AppRegistry.getApplication(appKey, appParams);
+```
+
+### registerComponent(appKey, getComponent)
+
+Register a component provider under the given appKey.
+
+```js
+const appKey = 'MyApp';
+const getComponent = () => App;
+AppRegistry.registerComponent(appKey, getComponent)
+```
+
+### registerConfig(config)
+
+Register multiple applications. AppConfig type is:
+
+```js
+type AppConfig = {
+ appKey: string;
+ component: ComponentProvider;
+ run?: function
+}
+
+const config = [{
+ appKey: 'FirstApp',
+ component: () => FirstApp
+}, {
+ appKey: 'SecondApp',
+ component: () => SecondApp
+}];
+AppRegistry.registerConfig(config)
+```
+
+### registerRunnable(appKey, run)
+
+Register a custom render function for an application. The function will receive
+the `appParameters` passed to `runApplication`.
+
+```js
+AppRegistry.registerRunnable('MyApp', (appParams) => { ... });
+```
+
+### runApplication(appKey, appParams)
+
+Runs the application that was registered under `appKey`. The `appParameters` must
+include the `rootTag` into which the application is rendered, and optionally any
+`initialProps` or render callback.
+
+```js
+AppRegistry.runApplication('MyApp', {
+ initialProps: {},
+ rootTag: document.getElementById('react-root'),
+ callback: () => { console.log('React rendering has finished') }
+})
+```
+
+### setComponentProviderInstrumentationHook(componentProvider)
+
+```js
+type setComponentProviderInstrumentationHook = (componentProvider: func) => Component;
+```
+
+### setWrapperComponentProvider(appParams)
+
+```js
+type setWrapperComponentProvider = (appParameters: object) => Component;
+```
+
+### unmountApplicationComponentAtRootTag(rootTag)
+
+To "stop" an application when a view should be destroyed, call
+`AppRegistry.unmountApplicationComponentAtRootTag` with the `rootTag` that was passed
+into `runApplication`.
diff --git a/packages/docs/src/apis/AppState/AppState.stories.js b/packages/docs/src/apis/AppState/AppState.stories.js
new file mode 100644
index 00000000..8d9a9ec2
--- /dev/null
+++ b/packages/docs/src/apis/AppState/AppState.stories.js
@@ -0,0 +1,6 @@
+export default {
+ title: 'APIs|AppState',
+ includeStories: []
+};
+
+export { default as stateChanges } from './examples/StateChanges';
diff --git a/packages/docs/src/apis/AppState/AppState.stories.mdx b/packages/docs/src/apis/AppState/AppState.stories.mdx
new file mode 100644
index 00000000..7452ae61
--- /dev/null
+++ b/packages/docs/src/apis/AppState/AppState.stories.mdx
@@ -0,0 +1,44 @@
+import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
+import * as stories from './AppState.stories.js';
+
+
+
+# AppState
+
+AppState can tell you if the app is in the foreground or background, and notify
+you when the state changes. States: `active` (the app is running in the
+foreground), `background` (the app is running in the background, i.e., the user
+has not focused the app's tab).
+
+## Properties
+
+### isAvailable
+
+Determines whether the browser environment supports `AppState`.
+
+### currentState
+
+Returns the current state of the app: "active" or "background".
+
+## Methods
+
+### addEventListener(type, handler)
+
+Add a handler to AppState changes by listening to the `change` event type and
+providing the handler. The handler is called with the app state value.
+
+```js
+AppState.addEventListener('change', (currentState) => {});
+```
+
+### removeEventListener(type, handler)
+
+Remove a handler by passing the `change` event type and the handler.
+
+AppState.removeEventListener('change', handler);
+
+## Example
+
+
+ {stories.stateChanges}
+
diff --git a/packages/docs/src/apis/AppState/examples/StateChanges.js b/packages/docs/src/apis/AppState/examples/StateChanges.js
new file mode 100644
index 00000000..cd589b34
--- /dev/null
+++ b/packages/docs/src/apis/AppState/examples/StateChanges.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import { AppState, Text, View } from 'react-native';
+
+export default function StateChanges() {
+ const [state, updateState] = React.useState({
+ active: 0,
+ background: 0,
+ currentState: AppState.currentState
+ });
+
+ const handleChange = nextState => {
+ updateState(previousState => ({
+ ...previousState,
+ [nextState]: previousState[nextState] + 1
+ }));
+ };
+
+ React.useEffect(() => {
+ AppState.addEventListener('change', handleChange);
+ return () => {
+ AppState.removeEventListener('change', handleChange);
+ };
+ }, [handleChange]);
+
+ return (
+
+ Active count: {state.active}
+ Background count: {state.background}
+ Current state is: {state.currentState}
+
+ );
+}
diff --git a/packages/docs/src/apis/Clipboard/Clipboard.stories.js b/packages/docs/src/apis/Clipboard/Clipboard.stories.js
new file mode 100644
index 00000000..33b416e4
--- /dev/null
+++ b/packages/docs/src/apis/Clipboard/Clipboard.stories.js
@@ -0,0 +1,6 @@
+export default {
+ title: 'APIs|Clipboard',
+ includeStories: []
+};
+
+export { default as setString } from './examples/SetString';
diff --git a/packages/docs/src/apis/Clipboard/Clipboard.stories.mdx b/packages/docs/src/apis/Clipboard/Clipboard.stories.mdx
new file mode 100644
index 00000000..08f4dd05
--- /dev/null
+++ b/packages/docs/src/apis/Clipboard/Clipboard.stories.mdx
@@ -0,0 +1,39 @@
+import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
+import * as stories from './Clipboard.stories.js';
+
+
+
+# Clipboard
+
+Clipboard gives you an interface for setting to the clipboard. (Getting
+clipboard content is not currently supported on web.)
+
+## Methods
+
+### isAvailable()
+
+Determines whether the browser environment supports Clipboard at all.
+
+```js
+if (Clipboard.isAvailable) {
+ // you can use the Clipboard API
+}
+```
+
+### setString(string)
+
+Copies a string to the clipboard. On web, some browsers may not support copying
+to the clipboard, therefore, this function returns a boolean to indicate if the
+copy was successful.
+
+```js
+const wasSet = Clipboard.setString('add this to clipboard');
+```
+
+
+ {stories.setString}
+
+
+### getString()
+
+Not properly supported on Web. Returns a `Promise` of an empty string.
diff --git a/packages/docs/src/apis/Clipboard/examples/SetString.js b/packages/docs/src/apis/Clipboard/examples/SetString.js
new file mode 100644
index 00000000..b7221c95
--- /dev/null
+++ b/packages/docs/src/apis/Clipboard/examples/SetString.js
@@ -0,0 +1,35 @@
+import { Button, Clipboard, StyleSheet, TextInput, View } from 'react-native';
+import React from 'react';
+
+export default function SetString() {
+ const setString = () => {
+ const success = Clipboard.setString('This text was copied to the clipboard by React Native');
+ console.log(`Clipboard.setString success? ${success}`);
+ };
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ buttonBox: {
+ maxWidth: 300
+ },
+ textInput: {
+ borderColor: '#AAB8C2',
+ borderWidth: 1,
+ height: 50,
+ marginTop: 20,
+ padding: 5
+ }
+});
diff --git a/packages/docs/src/apis/Dimensions/Dimensions.stories.js b/packages/docs/src/apis/Dimensions/Dimensions.stories.js
new file mode 100644
index 00000000..7013a278
--- /dev/null
+++ b/packages/docs/src/apis/Dimensions/Dimensions.stories.js
@@ -0,0 +1,6 @@
+export default {
+ title: 'APIs|Dimensions',
+ includeStories: []
+};
+
+export { default as stateChanges } from './examples/StateChanges';
diff --git a/packages/docs/src/apis/Dimensions/Dimensions.stories.mdx b/packages/docs/src/apis/Dimensions/Dimensions.stories.mdx
new file mode 100644
index 00000000..3a4081f3
--- /dev/null
+++ b/packages/docs/src/apis/Dimensions/Dimensions.stories.mdx
@@ -0,0 +1,50 @@
+import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
+import * as stories from './Dimensions.stories.js';
+
+
+
+# Dimensions
+
+Note: dimensions may change (e.g., due to device rotation) so any rendering
+logic or styles that depend on these constants should try to call this function
+on every render, rather than caching the value.
+
+## Methods
+
+### get(dimension)
+
+Get a dimension (e.g., `window` or `screen`).
+
+```js
+const { height, width } = Dimensions.get('window')
+```
+
+### set(dimensions)
+
+This should only be called server-side with an estimate for initial dimensions
+to be used when pre-rendering pages on the server.
+
+```js
+Dimensions.set({
+ window: {
+ height: estimatedHeight,
+ width: estimatedWidth
+ }
+})
+```
+
+### addEventListener(type, handler)
+
+Add an event handler. Supported events:
+
+* `change`: Fires when a property within the `Dimensions` object changes. The argument to the event handler is an object with `window` and `screen` properties whose values are the same as the return values of `Dimensions.get('window')` and `Dimensions.get('screen')`, respectively.
+
+### removeEventListener(type, handler)
+
+Remove an event handler.
+
+## Example
+
+
+ {stories.stateChanges}
+
diff --git a/packages/website/storybook/2-apis/Dimensions/examples/DimensionsChange.js b/packages/docs/src/apis/Dimensions/examples/StateChanges.js
similarity index 92%
rename from packages/website/storybook/2-apis/Dimensions/examples/DimensionsChange.js
rename to packages/docs/src/apis/Dimensions/examples/StateChanges.js
index 93eb89bb..a0a6ae4c 100644
--- a/packages/website/storybook/2-apis/Dimensions/examples/DimensionsChange.js
+++ b/packages/docs/src/apis/Dimensions/examples/StateChanges.js
@@ -1,7 +1,7 @@
import { Button, Dimensions, ScrollView, StyleSheet, Text, View } from 'react-native';
import React, { Component } from 'react';
-export default class ChangeEventExample extends Component {
+class StateChangeExample extends Component {
state = {
listened: false,
logs: []
@@ -53,6 +53,10 @@ export default class ChangeEventExample extends Component {
};
}
+export default function StateChange() {
+ return ;
+}
+
const styles = StyleSheet.create({
logs: {
maxHeight: 256
diff --git a/packages/docs/src/apis/I18nManager/I18nManager.stories.js b/packages/docs/src/apis/I18nManager/I18nManager.stories.js
new file mode 100644
index 00000000..423e183b
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/I18nManager.stories.js
@@ -0,0 +1,6 @@
+export default {
+ title: 'APIs|I18nManager',
+ includeStories: []
+};
+
+export { default as layoutRTL } from './examples/LayoutRTL';
diff --git a/packages/docs/src/apis/I18nManager/I18nManager.stories.mdx b/packages/docs/src/apis/I18nManager/I18nManager.stories.mdx
new file mode 100644
index 00000000..24067942
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/I18nManager.stories.mdx
@@ -0,0 +1,48 @@
+import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
+import * as stories from './I18nManager.stories.js';
+
+
+
+# I18nManager
+
+Control and query the layout and writing direction of the application.
+
+## Properties
+
+### isRTL
+
+Whether the application is currently in RTL mode.
+
+### doLeftAndRightSwapInRTL
+
+Whether the application swaps left/right styles in RTL mode. (Default is `true`
+but will eventually be changed to `false`).
+
+## Methods
+
+### allowRTL(bool)
+
+Allow the application to display in RTL mode.
+
+### forceRTL(bool)
+
+Force the application to display in RTL mode.
+
+### swapLeftAndRightInRTL(bool)
+
+Control whether the application swaps `left`/`right` styles in RTL mode. It is
+recommended that applications rely on `start`/`end` styles and disable automatic
+BiDi-flipping of `left`/`right` styles, as this will eventually become the
+default.
+
+### setPreferredLanguageRTL(bool)
+
+Set the application's preferred writing direction to RTL. You may need to infer
+the user's preferred locale on the server (from HTTP headers) and decide whether
+it's an RTL language. (Web-only)
+
+## Example
+
+
+ {stories.layoutRTL}
+
diff --git a/packages/docs/src/apis/I18nManager/examples/Block.js b/packages/docs/src/apis/I18nManager/examples/Block.js
new file mode 100644
index 00000000..90f9a13b
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/examples/Block.js
@@ -0,0 +1,67 @@
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+
+export default class Block extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = { description: null };
+ }
+
+ render() {
+ let description;
+ if (this.props.description) {
+ description = {this.props.description};
+ }
+
+ return (
+
+
+ {this.props.title}
+ {description}
+
+ {this.props.children}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ borderRadius: 3,
+ borderWidth: 0.5,
+ borderColor: '#d6d7da',
+ backgroundColor: '#ffffff',
+ margin: 10,
+ marginVertical: 5,
+ overflow: 'hidden'
+ },
+ titleContainer: {
+ borderBottomWidth: 0.5,
+ borderTopLeftRadius: 3,
+ borderTopRightRadius: 2.5,
+ borderBottomColor: '#d6d7da',
+ backgroundColor: '#f6f7f8',
+ paddingHorizontal: 10,
+ paddingVertical: 10
+ },
+ titleText: {
+ fontSize: 16,
+ fontWeight: '500'
+ },
+ descriptionText: {
+ fontSize: 14
+ },
+ disclosure: {
+ position: 'absolute',
+ top: 0,
+ right: 0,
+ padding: 10
+ },
+ disclosureIcon: {
+ width: 12,
+ height: 8
+ },
+ children: {
+ margin: 10
+ }
+});
diff --git a/packages/docs/src/apis/I18nManager/examples/LayoutRTL.js b/packages/docs/src/apis/I18nManager/examples/LayoutRTL.js
new file mode 100644
index 00000000..acf7b455
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/examples/LayoutRTL.js
@@ -0,0 +1,627 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @noflow
+ */
+
+/* eslint-disable no-use-before-define */
+
+import React from 'react';
+import Page from './Page';
+import Block from './Block';
+import {
+ Animated,
+ Button,
+ I18nManager,
+ Image,
+ PanResponder,
+ PixelRatio,
+ Platform,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableWithoutFeedback,
+ Switch,
+ View
+} from 'react-native';
+
+const SCALE = PixelRatio.get();
+const IMAGE_DIMENSION = 100 * SCALE;
+const IMAGE_SIZE = [IMAGE_DIMENSION, IMAGE_DIMENSION];
+const iconSource =
+ 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0nMjAwJyBoZWlnaHQ9JzIwMCcgZmlsbD0iIzAwMDAwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDEwMCAxMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwYXRoIGQ9Ik0yNS44NjcsNDguODUzQzMyLjgwNiw1MC4xNzYsNDYuNDYsNTIuNSw2MS4yMTUsNTIuNWgwLjAwNWM5LjcxLDAsMTguNDAxLTEuMDU3LDI1LjkzOC0yLjkxMyAgIGMwLjE1OS0wLjA0NiwwLjM1LTAuMTM1LDAuNTY1LTAuMTg3YzAuMjgyLTAuMDcyLDAuNTY1LTAuMTY0LDAuODQ0LTAuMjM4YzMuMTg0LTAuOTY0LDIuNTc3LTMuMDUxLDIuMTk5LTMuODUyICAgYy00LjE2Ni03LjcxOS0xNS4wODYtMjMuNDE1LTM1LjAyOC0yMy40MTVjLTIyLjE2OSwwLTMwLjI2MiwxMC42MzUtMzMuMTQsMTkuNTg5QzIyLjU0NSw0Mi4zMzMsMjIuNDA3LDQ3LjEzNSwyNS44NjcsNDguODUzeiAgICBNMjguNjc2LDM4LjAzMmMwLjAxMy0wLjAzNiwwLjYxNC0xLjYyNiwxLjkyMy0xLjAwOGMxLjEzMywwLjUzNSwwLjk2MSwxLjU2MywwLjg4NywxLjg1Yy0wLjAwNywwLjAyNC0wLjAxNCwwLjA0OC0wLjAyMSwwLjA3MyAgIGMwLDAuMDAxLTAuMDAxLDAuMDA0LTAuMDAxLDAuMDA0bDAsMGMtMC4yNDksMC45MjktMC40MDQsMi4wODYtMC4wMTcsMi44NmMwLjE2LDAuMzE5LDAuNDkyLDAuNzY4LDEuNTQyLDAuOTg3bDAuMzY2LDAuMDc3ICAgYzIwLjgxNiw0LjM2LDM2LDIuOTMzLDQ1LjY3OCwwLjYyNmwtMC4wMDQsMC4wMDJjMCwwLDAuMDA1LTAuMDAyLDAuMDA3LTAuMDAzYzAuMjEyLTAuMDUsMC40MjEtMC4xMDEsMC42MjgtMC4xNTIgICBjMC41MDktMC4wNSwxLjE3MywwLjA3OCwxLjM5OSwxYzAuMzUxLDEuNDI0LTAuOTczLDEuODk1LTEuMjE3LDEuOTY5Yy01LjMyNSwxLjI3OS0xMi4yNjYsMi4zMDYtMjAuODM1LDIuMzA3ICAgYy03LjUwNSwwLTE2LjI1NS0wLjc4Ny0yNi4yNTctMi44ODJsLTAuMzY0LTAuMDc3Yy0yLjEyLTAuNDQyLTMuMTExLTEuNjMzLTMuNTY5LTIuNTU1QzI3Ljk4NSw0MS40MjEsMjguMjgxLDM5LjQxNiwyOC42NzYsMzguMDMyICAgeiI+PC9wYXRoPjxjaXJjbGUgY3g9IjEwLjQ5MyIgY3k9IjIzLjQ1NSIgcj0iMC42MTkiPjwvY2lyY2xlPjxwYXRoIGQ9Ik0yLjA4LDI4LjMwOGMwLjY3Ni0wLjE3OCwwLjk4My0wLjM1MiwxLjE3NC0wLjVDNC42OSwyNi42OSw2LjUsMjcuNDgzLDcuNSwyOC4zNTd2MC4wMDJjMCwwLDEuNzExLDEuMjM1LDAuNzM3LDIuMjAyICAgYy0wLjk3NCwwLjk2NS0yLjMxOSwwLjAwNi0yLjMxOSwwLjAwNmwwLjAzNSwwLjAxNmMtMC4zMjctMC4yMDMtMC42LTAuNTYxLTAuNzgtMC41ODRjLTAuMzcsMC4yNi0wLjg3NiwwLjUtMS40NzYsMC41SDMuNyAgIGMwLDAtMS4zNDUsMC43MDksMC4xNzgsMS42NTJjMC4wMDEsMC4wMDEsMC4wMDIsMC4wNzIsMC4wMDQsMC4wNzNjMy45MzksMi4zNDIsOC4yNzEsNS43MDEsOC4yNzEsOC44OCAgIGMwLDAuNjkxLDAuMiwxNy4wNDIsMTcuNjI2LDI0LjczOWwwLjk2NywwLjQ0MmwtMC4xLDEuMDU5Yy0wLjQyMSw0LjM5LDEuMTQ1LDEwLjE5MSwxMC45OTMsMTIuODg4bDAuMTEzLDAuMDM4ICAgYzAuMDY3LDAuMDIzLDYuNzMyLDIuNDI5LDEwLjkwNywyLjQyOWMxLjU4NCwwLDIuMTU1LTAuMzUyLDIuMjQzLTAuNTYxYzAuMDg1LTAuMjAyLDAuNjEyLTIuMTY0LTYuMzMyLTkuMzg3bDAuMDAyLTAuMTgzICAgYzAsMC0yLjQ3Ny0zLjA3LDEuNTMzLTMuMDdjMC4wMSwwLDAuMDE5LDAsMC4wMjksMGMxLjI4NSwwLDIuNjA4LDAuMjE1LDMuOTgsMC4xODRjNC43NzEtMC4xMTcsOS4zMTYtMC40MjUsMTMuNTA2LTEuMDk2ICAgbDAuNDc0LTAuMDI4bDAuNjY4LDAuMTU4YzkuNjUxLDQuOTQ4LDE2LjczOCw3LjcxNiwxOS43MzgsNy43MTZ2MC4wMDZjMCwwLDAuMTY0LDAuMDExLDAuMjMsMC4wMDQgICBjLTAuMTg5LTAuNzIzLTIuMjMtMi44LTcuMjMtOS4wNzl2MC4wMjFjMCwwLTEuNTEyLTEuNjU4LDAuNzk3LTIuNjUzYzAuMDYzLTAuMDI2LDAuMDA4LDAuMDIzLDAuMDYtMC4wMDEgICBjOC42MzktMy41MDksMTMuNTAxLTguMjA0LDE1LjQxMS0xMS43NzVjMS4xNDUtMi4xMjksMC4yMDYtMi43ODQtMC42NTktMi45NzZjLTAuMzE3LTAuMDM4LTAuNjM0LTAuMDYyLTAuOTEyLTAuMDYyICAgYy0wLjIwNSwwLTAuMzc5LDAuMDEtMC41MjgsMC4wMjdsLTMuMTQzLDEuMjE0QzgzLjczMiw1My45MjYsNzMuMjE4LDU1LjUsNjEuMjIsNTUuNWMtMC4wMDIsMC0wLjAwNSwwLTAuMDA1LDAgICBjLTE1LjEyOCwwLTI5LjEwMS0yLjQzMi0zNi4wODMtMy43NzFsLTAuMTczLTAuMTExbC0wLjE2LTAuMTI2Yy01Ljg1OC0yLjY4MS01LjEzNy0xMC4yMDItNS4xMDMtMTAuNTE5bDAuMDYtMC4zICAgYzAuODk1LTIuODM4LDIuNDY3LTYuMzUyLDUuMjEzLTkuNzE5Yy0xLjgwOC0xLjM2OS00LjU5LTQuMTg4LTQuNDMtOC40OTRjMC4wNDYtMS4yNDQtMC40ODYtMi41MDgtMS40OTgtMy41NTkgICBjLTEuNDk4LTEuNTU1LTMuNzg1LTIuNDQ2LTYuMjc0LTIuNDQ2Yy0xLjc3LDAtMy41NTMsMC40NDItNS4yOTMsMS4zMTRjLTQuMDYxLDIuMDM1LTQuODU1LDQuNzM2LTUuNjkyLDcuNTk2ICAgYy0wLjEzNiwwLjQ2OC0wLjI4NCwwLjkzOS0wLjQzOCwxLjQxYy0wLjAwNiwwLjAxOS0wLjAyMiwwLjAzNS0wLjAyOCwwLjA1NkMwLjgzMywyOC40MjMsMS42OTEsMjguMzksMi4wOCwyOC4zMDh6IE0xMC40OTMsMTkuOTA4ICAgYzEuOTU2LDAsMy41NDgsMS41OTEsMy41NDgsMy41NDdjMCwxLjk1Ny0xLjU5MiwzLjU0OC0zLjU0OCwzLjU0OGMtMS45NTcsMC0zLjU0OC0xLjU5Mi0zLjU0OC0zLjU0OCAgIEM2Ljk0NCwyMS40OTksOC41MzYsMTkuOTA4LDEwLjQ5MywxOS45MDh6Ij48L3BhdGg+PC9nPjwvc3ZnPg==';
+
+function ListItem(props) {
+ return (
+
+
+
+
+
+
+ Text Text Text
+
+
+
+
+
+ );
+}
+
+function TextAlignmentExample(props) {
+ return (
+
+
+ Left-to-Right language text alignment.
+
+ {'\u0645\u0646 \u0627\u0644\u064A\u0645\u064A\u0646 ' +
+ '\u0625\u0644\u0649 \u0627\u0644\u064A\u0633\u0627\u0631 ' +
+ '\u0627\u0644\u0644\u063A\u0629 \u062F\u0648\u0646 ' +
+ '\u0645\u062D\u0627\u0630\u0627\u0629 \u0627\u0644\u0646\u0635'}
+
+
+ {'\u05DE\u05D9\u05DE\u05D9\u05DF \u05DC\u05E9\u05DE\u05D0\u05DC ' +
+ '\u05D4\u05E9\u05E4\u05D4 \u05D1\u05DC\u05D9 ' +
+ '\u05D9\u05D9\u05E9\u05D5\u05E8 \u05D8\u05E7\u05E1\u05D8'}
+
+
+
+ );
+}
+
+function AnimationBlock(props) {
+ return (
+
+
+
+
+
+ );
+}
+
+function withRTLState(Component) {
+ return class extends React.Component {
+ constructor(...args) {
+ super(...args);
+ this.state = {
+ isRTL: false
+ };
+ }
+
+ render() {
+ const isRTL = Platform === 'ios' ? this.state.isRTL : I18nManager.isRTL;
+ const setRTL = isRTL => this.setState({ isRTL: isRTL });
+ return ;
+ }
+ };
+}
+
+const RTLToggler = ({ isRTL, setRTL }) => {
+ if (Platform.OS !== 'ios') {
+ return {isRTL ? 'RTL' : 'LTR'};
+ }
+
+ const toggleRTL = () => setRTL(!isRTL);
+ return (
+
+ );
+};
+
+const PaddingExample = withRTLState(({ isRTL, setRTL }) => {
+ const color = 'teal';
+
+ return (
+
+ Styles
+ paddingStart: 50,
+ paddingEnd: 10
+
+ Demo:
+ The {color} is padding.
+
+
+
+
+
+
+ );
+});
+
+const MarginExample = withRTLState(({ isRTL, setRTL }) => {
+ return (
+
+ Styles
+ marginStart: 50,
+ marginEnd: 10
+
+ Demo:
+ The green is margin.
+
+
+
+
+
+
+ );
+});
+
+const PositionExample = withRTLState(({ isRTL, setRTL }) => {
+ return (
+
+ Styles
+ start: 50
+
+ Demo:
+ The orange is position.
+
+
+
+
+
+
+ Styles
+ end: 50
+
+ Demo:
+ The orange is position.
+
+
+
+
+
+
+ );
+});
+
+const BorderWidthExample = withRTLState(({ isRTL, setRTL }) => {
+ return (
+
+ Styles
+ borderStartWidth: 10,
+ borderEndWidth: 50
+
+ Demo:
+
+
+
+
+
+
+
+
+ );
+});
+
+const BorderColorExample = withRTLState(({ isRTL, setRTL }) => {
+ return (
+
+ Styles
+ borderStartColor: 'red',
+ borderEndColor: 'green',
+
+ Demo:
+
+
+
+
+
+
+
+
+ );
+});
+
+const BorderRadiiExample = withRTLState(({ isRTL, setRTL }) => {
+ return (
+
+ Styles
+ borderTopStartRadius: 10,
+ borderTopEndRadius: 20,
+ borderBottomStartRadius: 30,
+ borderBottomEndRadius: 40
+
+ Demo:
+
+
+
+
+
+
+
+
+ );
+});
+
+class LayoutRTLExample extends React.Component {
+ constructor(props) {
+ super(props);
+ const pan = new Animated.ValueXY();
+
+ this._panResponder = PanResponder.create({
+ onStartShouldSetPanResponder: () => true,
+ onPanResponderGrant: this._onPanResponderGrant,
+ onPanResponderMove: Animated.event([null, { dx: pan.x, dy: pan.y }]),
+ onPanResponderRelease: this._onPanResponderEnd,
+ onPanResponderTerminate: this._onPanResponderEnd
+ });
+
+ const { doLeftAndRightSwapInRTL, isRTL } = I18nManager;
+
+ this.state = {
+ toggleStatus: {},
+ pan,
+ linear: new Animated.Value(0),
+ isRTL,
+ doLeftAndRightSwapInRTL,
+ containerWidth: 0
+ };
+
+ this._linearTap = this._linearTap.bind(this);
+ this._onContainerLayout = this._onContainerLayout.bind(this);
+ this._onDirectionChange = this._onDirectionChange.bind(this);
+ this._onPanResponderGrant = this._onPanResponderGrant.bind(this);
+ this._onPanResponderEnd = this._onPanResponderEnd.bind(this);
+ this._onSwapChange = this._onSwapChange.bind(this);
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ {this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'}
+
+
+
+
+
+ forceRTL
+
+
+
+
+
+ swapLeftAndRightInRTL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No RTL flip
+
+
+
+ RTL flip
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ _onContainerLayout(e) {
+ this.setState(() => ({ containerWidth: e.nativeEvent.layout.width }));
+ }
+
+ _onDirectionChange() {
+ I18nManager.forceRTL(!this.state.isRTL);
+ this.setState({ isRTL: !this.state.isRTL });
+ }
+
+ _onSwapChange() {
+ I18nManager.swapLeftAndRightInRTL(!this.state.doLeftAndRightSwapInRTL);
+ this.setState({
+ doLeftAndRightSwapInRTL: !this.state.doLeftAndRightSwapInRTL
+ });
+ }
+
+ _linearTap(refName, e) {
+ this.setState({
+ toggleStatus: {
+ ...this.state.toggleStatus,
+ [refName]: !this.state.toggleStatus[refName]
+ }
+ });
+ const offset = IMAGE_SIZE[0] / SCALE / 2 + 10;
+ const toMaxDistance = (this.state.isRTL ? -1 : 1) * (this.state.containerWidth / 2 - offset);
+ Animated.timing(this.state.linear, {
+ toValue: this.state.toggleStatus[refName] ? toMaxDistance : 0,
+ duration: 2000,
+ useNativeDriver: false
+ }).start();
+ }
+
+ _onPanResponderGrant(e, gestureState) {
+ this.state.pan.stopAnimation(value => {
+ this.state.pan.setOffset(value);
+ });
+ }
+
+ _onPanResponderEnd(e, gestureState) {
+ this.state.pan.flattenOffset();
+ Animated.sequence([
+ Animated.decay(this.state.pan, {
+ velocity: { x: gestureState.vx, y: gestureState.vy },
+ deceleration: 0.995
+ }),
+ Animated.spring(this.state.pan, { toValue: { x: 0, y: 0 } })
+ ]).start();
+ }
+}
+
+export default function LayoutRTL() {
+ return ;
+}
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: '#e9eaed'
+ },
+ directionBox: {
+ flex: 1,
+ backgroundColor: '#f8f8f8',
+ borderWidth: 0.5,
+ borderColor: 'black'
+ },
+ directionText: {
+ padding: 10,
+ fontSize: 16,
+ textAlign: 'center',
+ fontWeight: 'bold'
+ },
+ switchRow: {
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingVertical: 5
+ },
+ list: {
+ height: 120,
+ marginBottom: 5,
+ borderTopWidth: 0.5,
+ borderLeftWidth: 0.5,
+ borderRightWidth: 0.5,
+ borderColor: '#e5e5e5'
+ },
+ row: {
+ height: 60,
+ flexDirection: 'row',
+ borderBottomWidth: 0.5,
+ borderColor: '#e5e5e5'
+ },
+ column1: {
+ width: 60,
+ padding: 6
+ },
+ column2: {
+ flex: 1,
+ padding: 6
+ },
+ column3: {
+ justifyContent: 'center',
+ padding: 6
+ },
+ icon: {
+ width: 48,
+ height: 48,
+ borderWidth: 0.5,
+ borderColor: '#e5e5e5'
+ },
+ image: {
+ width: 48,
+ height: 48
+ },
+ img: {
+ width: IMAGE_SIZE[0] / SCALE,
+ height: IMAGE_SIZE[1] / SCALE
+ },
+ view: {
+ flex: 1
+ },
+ block: {
+ padding: 10,
+ alignItems: 'center'
+ },
+ smallButton: {
+ height: 24,
+ width: 64
+ },
+ fontSizeSmall: {
+ fontSize: 14
+ },
+ fontSizeExtraSmall: {
+ fontSize: 12
+ },
+ textAlignLeft: {
+ textAlign: 'left'
+ },
+ textAlignRight: {
+ textAlign: 'right'
+ },
+ textAlignStart: {
+ textAlign: 'start'
+ },
+ textAlignEnd: {
+ textAlign: 'end'
+ },
+ flexDirectionRow: {
+ flexDirection: 'row'
+ },
+ bold: {
+ fontWeight: 'bold'
+ },
+ rtlToggler: {
+ color: 'gray',
+ padding: 8,
+ textAlign: 'center',
+ fontWeight: '500'
+ }
+});
diff --git a/packages/docs/src/apis/I18nManager/examples/Page.js b/packages/docs/src/apis/I18nManager/examples/Page.js
new file mode 100644
index 00000000..e882099b
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/examples/Page.js
@@ -0,0 +1,47 @@
+import React from 'react';
+import { ScrollView, StyleSheet, View } from 'react-native';
+import Title from './Title';
+
+export default class Page extends React.Component {
+ render() {
+ let ContentWrapper;
+ const wrapperProps = {};
+ if (this.props.noScroll) {
+ ContentWrapper = View;
+ } else {
+ ContentWrapper = ScrollView;
+ // $FlowFixMe found when converting React.createClass to ES6
+ wrapperProps.automaticallyAdjustContentInsets = !this.props.title;
+ wrapperProps.keyboardShouldPersistTaps = 'handled';
+ wrapperProps.keyboardDismissMode = 'interactive';
+ }
+ const title = this.props.title ?
: null;
+ const spacer = this.props.noSpacer ? null : ;
+ return (
+
+ {title}
+
+ {this.props.children}
+ {spacer}
+
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: '#e9eaed',
+ flex: 1,
+ maxWidth: 600,
+ margin: 'auto',
+ width: '100%'
+ },
+ spacer: {
+ height: 270
+ },
+ wrapper: {
+ flex: 1,
+ paddingTop: 10
+ }
+});
diff --git a/packages/docs/src/apis/I18nManager/examples/Title.js b/packages/docs/src/apis/I18nManager/examples/Title.js
new file mode 100644
index 00000000..02169c8b
--- /dev/null
+++ b/packages/docs/src/apis/I18nManager/examples/Title.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+
+export default class Title extends React.Component {
+ render() {
+ return (
+
+ {this.props.title}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ borderRadius: 4,
+ borderWidth: 0.5,
+ borderColor: '#d6d7da',
+ margin: 10,
+ marginBottom: 0,
+ height: 45,
+ padding: 10,
+ backgroundColor: 'white'
+ },
+ text: {
+ fontSize: 20,
+ fontWeight: '500'
+ }
+});
diff --git a/packages/docs/src/apis/Linking/Linking.stories.js b/packages/docs/src/apis/Linking/Linking.stories.js
new file mode 100644
index 00000000..754f12fa
--- /dev/null
+++ b/packages/docs/src/apis/Linking/Linking.stories.js
@@ -0,0 +1,6 @@
+export default {
+ title: 'APIs|Linking',
+ includeStories: []
+};
+
+export { default as openURL } from './examples/OpenURL';
diff --git a/packages/docs/src/apis/Linking/Linking.stories.mdx b/packages/docs/src/apis/Linking/Linking.stories.mdx
new file mode 100644
index 00000000..8b5a1199
--- /dev/null
+++ b/packages/docs/src/apis/Linking/Linking.stories.mdx
@@ -0,0 +1,30 @@
+import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
+import * as stories from './Linking.stories.js';
+
+
+
+# Linking
+
+Linking gives you a general interface for securely opening external URLs from JavaScript.
+
+## Methods
+
+### canOpenURL(url)
+
+Returns a `Promise` that resolves to a boolean indicating whether the app can open the URL.
+
+### getInitialURL()
+
+Returns a `Promise` that resolves to the string of the URL that initially loaded the app.
+
+### openURL(url)
+
+Try to open the given url in a secure fashion. The method returns a `Promise`
+object. If the url opens, the promise is resolved. If not, the promise is
+rejected.
+
+## Example
+
+
+ {stories.openURL}
+
diff --git a/packages/website/storybook/2-apis/Linking/examples/OpenURL.js b/packages/docs/src/apis/Linking/examples/OpenURL.js
similarity index 88%
rename from packages/website/storybook/2-apis/Linking/examples/OpenURL.js
rename to packages/docs/src/apis/Linking/examples/OpenURL.js
index b6e99ffd..49d1f117 100644
--- a/packages/website/storybook/2-apis/Linking/examples/OpenURL.js
+++ b/packages/docs/src/apis/Linking/examples/OpenURL.js
@@ -1,13 +1,9 @@
-/**
- * @flow
- */
-
import { Linking, StyleSheet, Text, View } from 'react-native';
import React, { PureComponent } from 'react';
const url = 'https://mathiasbynens.github.io/rel-noopener/malicious.html';
-export default class OpenURL extends PureComponent {
+class OpenURLExample extends PureComponent {
handlePress() {
Linking.canOpenURL(url).then(supported => {
return Linking.openURL(url);
@@ -33,6 +29,10 @@ export default class OpenURL extends PureComponent {
}
}
+export default function OpenURL() {
+ return ;
+}
+
const styles = StyleSheet.create({
text: {
borderRadius: 5,
diff --git a/packages/docs/src/apis/PixelRatio/PixelRatio.stories.mdx b/packages/docs/src/apis/PixelRatio/PixelRatio.stories.mdx
new file mode 100644
index 00000000..36f58688
--- /dev/null
+++ b/packages/docs/src/apis/PixelRatio/PixelRatio.stories.mdx
@@ -0,0 +1,37 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+
+
+
+# PixelRatio
+
+PixelRatio class gives access to the device pixel density.
+
+## Methods
+
+### get()
+
+Returns the device pixel density as a number.
+
+### getFontScale()
+
+On web this returns the device pixel ratio as a number.
+
+### getPixelSizeForLayoutSize(number)
+
+Converts a layout size (dp) to pixel size (px). Guaranteed to return an integer number.
+
+```js
+const image = getImage({
+ width: PixelRatio.getPixelSizeForLayoutSize(200),
+ height: PixelRatio.getPixelSizeForLayoutSize(100),
+});
+
+
+```
+
+### roundToNearestPixel(number)
+
+Rounds a layout size (dp) to the nearest layout size that corresponds to an
+integer number of pixels. For example, on a device with a PixelRatio of 3,
+`PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to exactly
+`(8.33 * 3) = 25` pixels.
diff --git a/packages/docs/src/apis/Platform/Platform.stories.mdx b/packages/docs/src/apis/Platform/Platform.stories.mdx
new file mode 100644
index 00000000..e0bf5330
--- /dev/null
+++ b/packages/docs/src/apis/Platform/Platform.stories.mdx
@@ -0,0 +1,49 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+
+
+
+# Platform
+
+Detect what is the platform in which the app is running. This piece of
+functionality can be useful when only small parts of a component are platform
+specific.
+
+## Properties
+
+### OS
+
+`Platform.OS` will be `web` when running in a Web browser.
+
+```js
+import { Platform } from 'react-native';
+
+const styles = StyleSheet.create({
+ height: (Platform.OS === 'web') ? 200 : 100,
+});
+```
+
+## Methods
+
+### select(config)
+
+`Platform.select` takes an object containing `Platform.OS` as keys and returns
+the value for the platform you are currently running on.
+
+```js
+import { Platform } from 'react-native';
+
+const containerStyles = {
+ flex: 1,
+ ...Platform.select({
+ android: {
+ backgroundColor: 'blue'
+ },
+ ios: {
+ backgroundColor: 'red'
+ },
+ web: {
+ backgroundColor: 'green'
+ }
+ })
+});
+```
diff --git a/packages/docs/src/apis/StyleSheet/StyleSheet.stories.mdx b/packages/docs/src/apis/StyleSheet/StyleSheet.stories.mdx
new file mode 100644
index 00000000..bcd933f3
--- /dev/null
+++ b/packages/docs/src/apis/StyleSheet/StyleSheet.stories.mdx
@@ -0,0 +1,83 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+
+
+
+# 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.
+
+## Methods
+
+### compose(style1, style2)
+
+Combines two styles such that the last style overrides properties of the first
+style. If either style is falsy, the other one is returned without allocating an
+array, saving allocations and maintaining reference equality.
+
+```js
+StyleSheet.compose(style1, style2);
+```
+
+### create(styles)
+
+Each key of the object passed to `create` must define a style object. The
+returned object replaces style objects with IDs.
+
+```js
+const styles = StyleSheet.create({
+ container: {
+ borderRadius: 4,
+ borderWidth: 0.5,
+ borderColor: '#d6d7da',
+ },
+ title: {
+ fontSize: 19,
+ fontWeight: 'bold',
+ }
+})
+```
+
+### flatten(style)
+
+Lookup a style object by ID or flatten an array of styles into a single style
+object.
+
+```js
+StyleSheet.flatten(styles.listItem);
+StyleSheet.flatten([styles.listItem, styles.selectedListItem]);
+```
+
+## Properties
+
+### absoluteFill
+
+A very common pattern is to create overlays with position absolute and zero
+positioning, so `absoluteFill` can be used for convenience and to reduce
+duplication of these repeated styles.
+
+```js
+
+```
+
+### absoluteFillObject
+
+Sometimes you may want `absoluteFill` but with a couple tweaks -
+`absoluteFillObject` can be used to create a customized entry in a `StyleSheet`
+
+```js
+const styles = StyleSheet.create({
+ container: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: 'transparent',
+ top: 10
+ }
+});
+```
+
+### hairlineWidth
+
+Enables borders of just one physical pixel on retina screens, otherwise it is
+equal to a CSS value of 1px.
diff --git a/packages/docs/src/apis/Vibration/Vibration.stories.mdx b/packages/docs/src/apis/Vibration/Vibration.stories.mdx
new file mode 100644
index 00000000..9547097a
--- /dev/null
+++ b/packages/docs/src/apis/Vibration/Vibration.stories.mdx
@@ -0,0 +1,33 @@
+import { Meta } from '@storybook/addon-docs/blocks';
+
+
+
+# Vibration
+
+Vibration is described as a pattern of on-off pulses, which may be of varying
+lengths. The pattern may consist of either a single integer, describing the
+number of milliseconds to vibrate, or an array of integers describing a pattern
+of vibrations and pauses. Vibration is controlled with a single method:
+`Vibration.vibrate()`.
+
+The vibration is asynchronous so this method will return immediately. There will
+be no effect on devices that do not support vibration.
+
+## Methods
+
+### cancel()
+
+Stop the vibration
+
+### vibrate(pattern)
+
+Start the vibration pattern
+
+```js
+// Vibrate once for 200ms
+Vibration.vibrate(200);
+Vibration.vibrate([200]);
+
+// Vibrate for 200ms, pause for 100ms, vibrate for 200ms:
+Vibration.vibrate([200, 100, 200]);
+```
diff --git a/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.js b/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.js
new file mode 100644
index 00000000..6bd40c4e
--- /dev/null
+++ b/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.js
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ViewPropTypes': PropTypes.any,
+ animating: PropTypes.bool,
+ color: PropTypes.string,
+ hidesWhenStopped: PropTypes.bool,
+ size: PropTypes.oneOfType([PropTypes.oneOf(['small', 'large']), PropTypes.number])
+};
+
+ofProps.defaultProps = {
+ animating: true,
+ color: '#1976D2',
+ hidesWhenStopped: true,
+ size: 'small'
+};
+
+export default {
+ title: 'Components|ActivityIndicator',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as animating } from './examples/Animating';
+export { default as color } from './examples/Color';
+export { default as hidesWhenStopped } from './examples/HidesWhenStopped';
+export { default as size } from './examples/Size';
diff --git a/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.mdx b/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.mdx
new file mode 100644
index 00000000..bf244ff0
--- /dev/null
+++ b/packages/docs/src/components/ActivityIndicator/ActivityIndicator.stories.mdx
@@ -0,0 +1,45 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './ActivityIndicator.stories.js';
+
+
+
+# ActivityIndicator
+
+Displays a customizable activity indicator.
+
+## Props
+
+
+
+### animating
+
+Controls whether to show the indicator or hide it.
+
+
+ {stories.animating}
+
+
+### color
+
+Customize the foreground color of the indicator.
+
+
+ {stories.color}
+
+
+### hidesWhenStopped
+
+Control whether to show the indicator when it is not animating.
+
+
+ {stories.hidesWhenStopped}
+
+
+### size
+
+Customize the size of the indicator. `small` has a height of `20px`, large has a
+height of `36px`. Scale transforms can also be used.
+
+
+ {stories.size}
+
diff --git a/packages/docs/src/components/ActivityIndicator/examples/Animating.js b/packages/docs/src/components/ActivityIndicator/examples/Animating.js
new file mode 100644
index 00000000..b97237d3
--- /dev/null
+++ b/packages/docs/src/components/ActivityIndicator/examples/Animating.js
@@ -0,0 +1,18 @@
+import { ActivityIndicator, StyleSheet, View } from 'react-native';
+import React from 'react';
+
+export default function Animating() {
+ return (
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ horizontal: {
+ alignItems: 'center',
+ flexDirection: 'row'
+ }
+});
diff --git a/packages/docs/src/components/ActivityIndicator/examples/Color.js b/packages/docs/src/components/ActivityIndicator/examples/Color.js
new file mode 100644
index 00000000..c37b7440
--- /dev/null
+++ b/packages/docs/src/components/ActivityIndicator/examples/Color.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { ActivityIndicator, StyleSheet, View } from 'react-native';
+
+export default function Color() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ horizontal: {
+ alignItems: 'center',
+ flexDirection: 'row'
+ },
+ item: {
+ paddingRight: 10
+ }
+});
diff --git a/packages/website/storybook/1-components/ActivityIndicator/examples/PropHidesWhenStopped.js b/packages/docs/src/components/ActivityIndicator/examples/HidesWhenStopped.js
similarity index 69%
rename from packages/website/storybook/1-components/ActivityIndicator/examples/PropHidesWhenStopped.js
rename to packages/docs/src/components/ActivityIndicator/examples/HidesWhenStopped.js
index b50eadc4..528a24ca 100644
--- a/packages/website/storybook/1-components/ActivityIndicator/examples/PropHidesWhenStopped.js
+++ b/packages/docs/src/components/ActivityIndicator/examples/HidesWhenStopped.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { bool } from 'prop-types';
import React, { PureComponent } from 'react';
@@ -43,26 +39,21 @@ class ToggleAnimatingActivityIndicator extends PureComponent {
}
}
-const ActivityIndicatorHidesWhenStoppedExample = () => (
-
-
-
-
-);
+export default function HidesWhenStoppedExample() {
+ return (
+
+
+
+
+ );
+}
const styles = StyleSheet.create({
horizontal: {
alignItems: 'center',
flexDirection: 'row'
},
- rightPadding: {
+ item: {
paddingRight: 10
}
});
-
-ActivityIndicatorHidesWhenStoppedExample.metadata = {
- id: 'ActivityIndicator.props.hidesWhenStopped',
- description: ''
-};
-
-export default ActivityIndicatorHidesWhenStoppedExample;
diff --git a/packages/docs/src/components/ActivityIndicator/examples/Size.js b/packages/docs/src/components/ActivityIndicator/examples/Size.js
new file mode 100644
index 00000000..e7c2d34f
--- /dev/null
+++ b/packages/docs/src/components/ActivityIndicator/examples/Size.js
@@ -0,0 +1,29 @@
+import React from 'react';
+import { ActivityIndicator, StyleSheet, View } from 'react-native';
+
+const sizes = [20, 'small', 36, 'large', 60];
+
+export default function Size() {
+ return (
+
+ {sizes.map((size, i) => (
+
+ ))}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ horizontal: {
+ alignItems: 'center',
+ flexDirection: 'row'
+ },
+ item: {
+ paddingRight: 10
+ },
+ large: {
+ marginLeft: 20,
+ transform: [{ scale: 1.75 }]
+ }
+});
diff --git a/packages/docs/src/components/Button/Button.stories.js b/packages/docs/src/components/Button/Button.stories.js
new file mode 100644
index 00000000..8e6f0cb8
--- /dev/null
+++ b/packages/docs/src/components/Button/Button.stories.js
@@ -0,0 +1,27 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ accessibilityLabel: PropTypes.string,
+ color: PropTypes.string,
+ disabled: PropTypes.bool,
+ onPress: PropTypes.func,
+ testID: PropTypes.string,
+ title: PropTypes.string
+};
+
+ofProps.defaultProps = {
+ color: '#2196F3',
+ disabled: false
+};
+
+export default {
+ title: 'Components|Button',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as color } from './examples/Color';
+export { default as disabled } from './examples/Disabled';
+export { default as onPress } from './examples/OnPress';
diff --git a/packages/docs/src/components/Button/Button.stories.mdx b/packages/docs/src/components/Button/Button.stories.mdx
new file mode 100644
index 00000000..f84172ce
--- /dev/null
+++ b/packages/docs/src/components/Button/Button.stories.mdx
@@ -0,0 +1,45 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './Button.stories.js';
+
+
+
+# Button
+
+A basic button component. Supports a minimal level of customization. You can
+build your own custom button using `TouchableOpacity` or `TouchableHighlight`.
+
+## Props
+
+
+
+### color
+
+Customize the background color of the button.
+
+
+ {stories.color}
+
+
+### disabled
+
+Prevent all interactions with the button.
+
+
+ {stories.disabled}
+
+
+### onPress
+
+Called when the button is pressed by a pointer or keyboard.
+
+
+ {stories.onPress}
+
+
+### title
+
+Text to display inside the button.
+
+```js
+
+```
diff --git a/packages/docs/src/components/Button/examples/Color.js b/packages/docs/src/components/Button/examples/Color.js
new file mode 100644
index 00000000..cf0993ed
--- /dev/null
+++ b/packages/docs/src/components/Button/examples/Color.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import { DividerVertical } from '../helpers';
+import { Button, View } from 'react-native';
+
+const emptyFunction = () => {};
+
+export default function Color() {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/docs/src/components/Button/examples/Disabled.js b/packages/docs/src/components/Button/examples/Disabled.js
new file mode 100644
index 00000000..673758fa
--- /dev/null
+++ b/packages/docs/src/components/Button/examples/Disabled.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import { Button } from 'react-native';
+
+export default function Disabled() {
+ const onPress = () => {
+ console.error('Disabled button should not trigger onPress!');
+ };
+
+ return ;
+}
diff --git a/packages/docs/src/components/Button/examples/OnPress.js b/packages/docs/src/components/Button/examples/OnPress.js
new file mode 100644
index 00000000..76c0be72
--- /dev/null
+++ b/packages/docs/src/components/Button/examples/OnPress.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import { DividerHorizontal } from '../helpers';
+import { Button, StyleSheet, View } from 'react-native';
+
+const emptyFunction = () => {};
+
+export default function OnPress() {
+ return (
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ horizontal: {
+ flexDirection: 'row'
+ }
+});
diff --git a/packages/website/storybook/1-components/Button/helpers.js b/packages/docs/src/components/Button/helpers.js
similarity index 95%
rename from packages/website/storybook/1-components/Button/helpers.js
rename to packages/docs/src/components/Button/helpers.js
index 67f13126..eba3efac 100644
--- a/packages/website/storybook/1-components/Button/helpers.js
+++ b/packages/docs/src/components/Button/helpers.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { StyleSheet, View } from 'react-native';
diff --git a/packages/docs/src/components/CheckBox/CheckBox.stories.js b/packages/docs/src/components/CheckBox/CheckBox.stories.js
new file mode 100644
index 00000000..de60f514
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/CheckBox.stories.js
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ViewPropTypes': PropTypes.any,
+ color: PropTypes.string,
+ disabled: PropTypes.bool,
+ onChange: PropTypes.func,
+ onValueChange: PropTypes.func,
+ value: PropTypes.bool
+};
+
+ofProps.defaultProps = {
+ disabled: false,
+ value: false
+};
+
+export default {
+ title: 'Components|CheckBox',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as color } from './examples/Color';
+export { default as disabled } from './examples/Disabled';
+export { default as onValueChange } from './examples/OnValueChange';
+export { default as value } from './examples/Value';
+export { default as customSize } from './examples/CustomSize';
diff --git a/packages/docs/src/components/CheckBox/CheckBox.stories.mdx b/packages/docs/src/components/CheckBox/CheckBox.stories.mdx
new file mode 100644
index 00000000..3ab01e7c
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/CheckBox.stories.mdx
@@ -0,0 +1,56 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './CheckBox.stories.js';
+
+
+
+# CheckBox
+
+This is a controlled component that requires an `onValueChange` callback that
+updates the value prop in order for the component to reflect user actions. If
+the `value` prop is not updated, the component will continue to render the
+supplied `value` prop instead of the expected result of any user actions.
+
+## Props
+
+
+
+### color
+
+Customize the color of the active checkbox.
+
+
+ {stories.color}
+
+
+### disabled
+
+Prevent interaction with the checkbox.
+
+
+ {stories.disabled}
+
+
+### onValueChange
+
+Called with the event when the value changes.
+
+
+ {stories.onValueChange}
+
+
+### value
+
+Controls whether the checkbox is active or not.
+
+
+ {stories.value}
+
+
+## Notes
+
+The checkbox size can be controlled by changing the `height` and `width` style
+properties.
+
+
+ {stories.customSize}
+
diff --git a/packages/docs/src/components/CheckBox/examples/Color.js b/packages/docs/src/components/CheckBox/examples/Color.js
new file mode 100644
index 00000000..7e926b9d
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/examples/Color.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import styles from './styles';
+import { CheckBox, View } from 'react-native';
+
+export default function Color() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/docs/src/components/CheckBox/examples/CustomSize.js b/packages/docs/src/components/CheckBox/examples/CustomSize.js
new file mode 100644
index 00000000..32420a64
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/examples/CustomSize.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import styles from './styles';
+import { CheckBox, View } from 'react-native';
+
+export default function CustomSize() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/docs/src/components/CheckBox/examples/Disabled.js b/packages/docs/src/components/CheckBox/examples/Disabled.js
new file mode 100755
index 00000000..5103840a
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/examples/Disabled.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import styles from './styles';
+import { CheckBox, View } from 'react-native';
+
+export default function Disabled() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/website/storybook/1-components/CheckBox/examples/PropOnValueChange.js b/packages/docs/src/components/CheckBox/examples/OnValueChange.js
similarity index 92%
rename from packages/website/storybook/1-components/CheckBox/examples/PropOnValueChange.js
rename to packages/docs/src/components/CheckBox/examples/OnValueChange.js
index aeb10620..b1cb8bcb 100755
--- a/packages/website/storybook/1-components/CheckBox/examples/PropOnValueChange.js
+++ b/packages/docs/src/components/CheckBox/examples/OnValueChange.js
@@ -1,12 +1,8 @@
-/**
- * @flow
- */
-
import styles from './styles';
import React, { PureComponent } from 'react';
import { CheckBox, Text, View } from 'react-native';
-class CheckBoxOnValueChangeExample extends PureComponent {
+class OnValueChangeExample extends PureComponent {
state = {
eventSwitchIsOn: false,
eventSwitchRegressionIsOn: true
@@ -56,4 +52,6 @@ class CheckBoxOnValueChangeExample extends PureComponent {
};
}
-export default CheckBoxOnValueChangeExample;
+export default function OnValueChange() {
+ return ;
+}
diff --git a/packages/docs/src/components/CheckBox/examples/Value.js b/packages/docs/src/components/CheckBox/examples/Value.js
new file mode 100755
index 00000000..5f706f52
--- /dev/null
+++ b/packages/docs/src/components/CheckBox/examples/Value.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import styles from './styles';
+import { CheckBox, View } from 'react-native';
+
+export default function Value() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/website/storybook/1-components/CheckBox/examples/styles.js b/packages/docs/src/components/CheckBox/examples/styles.js
similarity index 94%
rename from packages/website/storybook/1-components/CheckBox/examples/styles.js
rename to packages/docs/src/components/CheckBox/examples/styles.js
index e0a2f08f..b19b301c 100755
--- a/packages/website/storybook/1-components/CheckBox/examples/styles.js
+++ b/packages/docs/src/components/CheckBox/examples/styles.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
diff --git a/packages/website/storybook/1-components/CheckBox/helpers.js b/packages/docs/src/components/CheckBox/helpers.js
similarity index 97%
rename from packages/website/storybook/1-components/CheckBox/helpers.js
rename to packages/docs/src/components/CheckBox/helpers.js
index 7b87cf0e..ff54b950 100644
--- a/packages/website/storybook/1-components/CheckBox/helpers.js
+++ b/packages/docs/src/components/CheckBox/helpers.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { StyleSheet, View } from 'react-native';
diff --git a/packages/docs/src/components/FlatList/FlatList.stories.js b/packages/docs/src/components/FlatList/FlatList.stories.js
new file mode 100644
index 00000000..35e4ca5f
--- /dev/null
+++ b/packages/docs/src/components/FlatList/FlatList.stories.js
@@ -0,0 +1,7 @@
+export default {
+ title: 'Components|FlatList',
+ includeStories: []
+};
+
+export { default as singleColumn } from './examples/SingleColumn';
+export { default as multiColumn } from './examples/MultiColumn';
diff --git a/packages/docs/src/components/FlatList/FlatList.stories.mdx b/packages/docs/src/components/FlatList/FlatList.stories.mdx
new file mode 100644
index 00000000..ffccd263
--- /dev/null
+++ b/packages/docs/src/components/FlatList/FlatList.stories.mdx
@@ -0,0 +1,26 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './FlatList.stories.js';
+
+
+
+# FlatList
+
+An interface for rendering basic, flat lists. Please refer to the React Native
+[documentation for FlatList](https://facebook.github.io/react-native/docs/flatlist).
+
+Note that `FlatList` is not optimized for the web. You may wish to consider
+alternatives such as
+[recyclerlistview](https://github.com/Flipkart/recyclerlistview) and
+[FastList](https://gist.github.com/vishnevskiy/f4ba74adf5cf1d269b860fab86e8feef).
+
+### Single column
+
+
+ {stories.singleColumn}
+
+
+### Multiple columns
+
+
+ {stories.multiColumn}
+
diff --git a/packages/examples/src/RNTester/MultiColumnExample.js b/packages/docs/src/components/FlatList/examples/MultiColumn.js
similarity index 63%
rename from packages/examples/src/RNTester/MultiColumnExample.js
rename to packages/docs/src/components/FlatList/examples/MultiColumn.js
index cc323cfc..3caeb9f2 100644
--- a/packages/examples/src/RNTester/MultiColumnExample.js
+++ b/packages/docs/src/components/FlatList/examples/MultiColumn.js
@@ -4,25 +4,14 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @flow
* @providesModule MultiColumnExample
*/
'use strict';
-const React = require('react');
-const ReactNative = require('react-native');
-const {
- FlatList,
- StyleSheet,
- Text,
- View,
-} = ReactNative;
+import React from 'react';
+import { FlatList, StyleSheet, Text, View } from 'react-native';
-const RNTesterPage = require('./RNTesterPage');
-
-const infoLog = require('infoLog');
-
-const {
+import {
FooterComponent,
HeaderComponent,
ItemComponent,
@@ -31,10 +20,10 @@ const {
genItemData,
getItemLayout,
pressItem,
- renderSmallSwitchOption,
-} = require('./ListExampleShared');
+ renderSmallSwitchOption
+} from './shared';
-class MultiColumnExample extends React.PureComponent<$FlowFixMeProps, $FlowFixMeState> {
+class MultiColumnExample extends React.PureComponent {
static title = ' - MultiColumn';
static description = 'Performant, scrollable grid of data.';
@@ -44,23 +33,20 @@ class MultiColumnExample extends React.PureComponent<$FlowFixMeProps, $FlowFixMe
fixedHeight: true,
logViewable: false,
numColumns: 2,
- virtualized: true,
+ virtualized: true
};
- _onChangeFilterText = (filterText) => {
- this.setState(() => ({filterText}));
+ _onChangeFilterText = filterText => {
+ this.setState(() => ({ filterText }));
};
- _onChangeNumColumns = (numColumns) => {
- this.setState(() => ({numColumns: Number(numColumns)}));
+ _onChangeNumColumns = numColumns => {
+ this.setState(() => ({ numColumns: Number(numColumns) }));
};
render() {
const filterRegex = new RegExp(String(this.state.filterText), 'i');
- const filter = (item) => (filterRegex.test(item.text) || filterRegex.test(item.title));
+ const filter = item => filterRegex.test(item.text) || filterRegex.test(item.title);
const filteredData = this.state.data.filter(filter);
return (
- - MultiColumn'}
- noSpacer={true}
- noScroll={true}>
+
- numColumns:
+ numColumns:
alert('onRefresh: nothing to refresh :P')}
+ onRefresh={() => console.log('onRefresh: nothing to refresh :P')}
+ onViewableItemsChanged={this._onViewableItemsChanged}
refreshing={false}
renderItem={this._renderItemComponent}
- disableVirtualization={!this.state.virtualized}
- onViewableItemsChanged={this._onViewableItemsChanged}
- legacyImplementation={false}
/>
-
+
);
}
- _getItemLayout(data: any, index: number): {length: number, offset: number, index: number} {
+ _getItemLayout(data: any, index: number): { length: number, offset: number, index: number } {
const length = getItemLayout(data, index).length + 2 * (CARD_MARGIN + BORDER_WIDTH);
- return {length, offset: length * index, index};
+ return { length, offset: length * index, index };
}
- _renderItemComponent = ({item}) => {
+ _renderItemComponent = ({ item }) => {
return (
-
+
);
};
// This is called when items change viewability by scrolling into or out of the viewable area.
_onViewableItemsChanged = (info: {
changed: Array<{
- key: string, isViewable: boolean, item: {columns: Array<*>}, index: ?number, section?: any
- }>},
- ) => {
+ key: string,
+ isViewable: boolean,
+ item: { columns: Array<*> },
+ index: ?number,
+ section?: any
+ }>
+ }) => {
// Impressions can be logged here
if (this.state.logViewable) {
- infoLog('onViewableItemsChanged: ', info.changed.map((v) => ({...v, item: '...'})));
+ console.log('onViewableItemsChanged: ', info.changed.map(v => ({ ...v, item: '...' })));
}
};
_pressItem = (key: string) => {
@@ -134,21 +119,31 @@ const CARD_MARGIN = 4;
const BORDER_WIDTH = 1;
const styles = StyleSheet.create({
+ container: {
+ backgroundColor: 'rgb(239, 239, 244)',
+ flex: 1
+ },
card: {
margin: CARD_MARGIN,
borderRadius: 10,
flex: 1,
overflow: 'hidden',
borderColor: 'lightgray',
- borderWidth: BORDER_WIDTH,
+ borderWidth: BORDER_WIDTH
},
row: {
flexDirection: 'row',
- alignItems: 'center',
+ alignItems: 'center'
},
searchRow: {
- padding: 10,
- },
+ padding: 10
+ }
});
-module.exports = MultiColumnExample;
+export default function() {
+ return (
+
+
+
+ );
+}
diff --git a/packages/docs/src/components/FlatList/examples/SingleColumn.js b/packages/docs/src/components/FlatList/examples/SingleColumn.js
new file mode 100644
index 00000000..73c45239
--- /dev/null
+++ b/packages/docs/src/components/FlatList/examples/SingleColumn.js
@@ -0,0 +1,197 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';
+
+import React from 'react';
+import { Animated, FlatList, StyleSheet, View } from 'react-native';
+
+import {
+ FooterComponent,
+ HeaderComponent,
+ ItemComponent,
+ ItemSeparatorComponent,
+ PlainInput,
+ SeparatorComponent,
+ Spindicator,
+ genItemData,
+ getItemLayout,
+ pressItem,
+ renderSmallSwitchOption
+} from './shared';
+
+const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
+
+const VIEWABILITY_CONFIG = {
+ minimumViewTime: 3000,
+ viewAreaCoveragePercentThreshold: 100,
+ waitForInteraction: true
+};
+
+class SingleColumnExample extends React.PureComponent {
+ static title = '';
+ static description = 'Performant, scrollable list of data.';
+
+ state = {
+ data: genItemData(100),
+ debug: false,
+ horizontal: false,
+ inverted: false,
+ filterText: '',
+ fixedHeight: true,
+ logViewable: false,
+ virtualized: true
+ };
+
+ _onChangeFilterText = filterText => {
+ this.setState({ filterText });
+ };
+
+ _onChangeScrollToIndex = text => {
+ this._listRef.getNode().scrollToIndex({ viewPosition: 0.5, index: Number(text) });
+ };
+
+ _scrollPos = new Animated.Value(0);
+ _scrollSinkX = Animated.event([{ nativeEvent: { contentOffset: { x: this._scrollPos } } }], {
+ useNativeDriver: true
+ });
+ _scrollSinkY = Animated.event([{ nativeEvent: { contentOffset: { y: this._scrollPos } } }], {
+ useNativeDriver: true
+ });
+
+ componentDidUpdate() {
+ this._listRef.getNode().recordInteraction(); // e.g. flipping logViewable switch
+ }
+
+ render() {
+ const filterRegex = new RegExp(String(this.state.filterText), 'i');
+ const filter = item => filterRegex.test(item.text) || filterRegex.test(item.title);
+ const filteredData = this.state.data.filter(filter);
+ return (
+
+
+
+
+
+
+
+ {renderSmallSwitchOption(this, 'virtualized')}
+ {renderSmallSwitchOption(this, 'horizontal')}
+ {renderSmallSwitchOption(this, 'fixedHeight')}
+ {renderSmallSwitchOption(this, 'logViewable')}
+ {renderSmallSwitchOption(this, 'inverted')}
+ {renderSmallSwitchOption(this, 'debug')}
+
+
+
+
+ }
+ numColumns={1}
+ onEndReached={this._onEndReached}
+ onRefresh={this._onRefresh}
+ onScroll={this.state.horizontal ? this._scrollSinkX : this._scrollSinkY}
+ onViewableItemsChanged={this._onViewableItemsChanged}
+ ref={this._captureRef}
+ refreshing={false}
+ renderItem={this._renderItemComponent}
+ viewabilityConfig={VIEWABILITY_CONFIG}
+ />
+
+ );
+ }
+ _captureRef = ref => {
+ this._listRef = ref;
+ };
+ _getItemLayout = (data: any, index: number) => {
+ return getItemLayout(data, index, this.state.horizontal);
+ };
+ _onEndReached = () => {
+ if (this.state.data.length >= 1000) {
+ return;
+ }
+ this.setState(state => ({
+ data: state.data.concat(genItemData(100, state.data.length))
+ }));
+ };
+ _onRefresh = () => console.log('onRefresh: nothing to refresh :P');
+ _renderItemComponent = ({ item, separators }) => {
+ return (
+
+ );
+ };
+ // This is called when items change viewability by scrolling into or out of
+ // the viewable area.
+ _onViewableItemsChanged = (info: {
+ changed: Array<{
+ key: string,
+ isViewable: boolean,
+ item: any,
+ index: ?number,
+ section?: any
+ }>
+ }) => {
+ // Impressions can be logged here
+ if (this.state.logViewable) {
+ console.log('onViewableItemsChanged: ', info.changed.map(v => ({ ...v, item: '...' })));
+ }
+ };
+ _pressItem = (key: string) => {
+ this._listRef.getNode().recordInteraction();
+ pressItem(this, key);
+ };
+ _listRef: AnimatedFlatList;
+}
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: 'rgb(239, 239, 244)',
+ flex: 1
+ },
+ list: {
+ backgroundColor: 'white'
+ },
+ options: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ alignItems: 'center'
+ },
+ searchRow: {
+ paddingHorizontal: 10
+ }
+});
+
+export default function() {
+ return (
+
+
+
+ );
+}
diff --git a/packages/examples/src/RNTester/Thumbnails/bandaged.png b/packages/docs/src/components/FlatList/examples/Thumbnails/bandaged.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/bandaged.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/bandaged.png
diff --git a/packages/examples/src/RNTester/Thumbnails/call.png b/packages/docs/src/components/FlatList/examples/Thumbnails/call.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/call.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/call.png
diff --git a/packages/examples/src/RNTester/Thumbnails/dislike.png b/packages/docs/src/components/FlatList/examples/Thumbnails/dislike.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/dislike.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/dislike.png
diff --git a/packages/examples/src/RNTester/Thumbnails/fist.png b/packages/docs/src/components/FlatList/examples/Thumbnails/fist.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/fist.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/fist.png
diff --git a/packages/examples/src/RNTester/Thumbnails/flowers.png b/packages/docs/src/components/FlatList/examples/Thumbnails/flowers.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/flowers.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/flowers.png
diff --git a/packages/examples/src/RNTester/Thumbnails/heart.png b/packages/docs/src/components/FlatList/examples/Thumbnails/heart.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/heart.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/heart.png
diff --git a/packages/examples/src/RNTester/Thumbnails/like.png b/packages/docs/src/components/FlatList/examples/Thumbnails/like.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/like.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/like.png
diff --git a/packages/examples/src/RNTester/Thumbnails/liking.png b/packages/docs/src/components/FlatList/examples/Thumbnails/liking.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/liking.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/liking.png
diff --git a/packages/examples/src/RNTester/Thumbnails/party.png b/packages/docs/src/components/FlatList/examples/Thumbnails/party.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/party.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/party.png
diff --git a/packages/examples/src/RNTester/Thumbnails/poke.png b/packages/docs/src/components/FlatList/examples/Thumbnails/poke.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/poke.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/poke.png
diff --git a/packages/examples/src/RNTester/Thumbnails/superlike.png b/packages/docs/src/components/FlatList/examples/Thumbnails/superlike.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/superlike.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/superlike.png
diff --git a/packages/examples/src/RNTester/Thumbnails/victory.png b/packages/docs/src/components/FlatList/examples/Thumbnails/victory.png
similarity index 100%
rename from packages/examples/src/RNTester/Thumbnails/victory.png
rename to packages/docs/src/components/FlatList/examples/Thumbnails/victory.png
diff --git a/packages/examples/src/RNTester/ListExampleShared.js b/packages/docs/src/components/FlatList/examples/shared.js
similarity index 63%
rename from packages/examples/src/RNTester/ListExampleShared.js
rename to packages/docs/src/components/FlatList/examples/shared.js
index c5eef14d..5b8c142d 100644
--- a/packages/examples/src/RNTester/ListExampleShared.js
+++ b/packages/docs/src/components/FlatList/examples/shared.js
@@ -3,15 +3,11 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @providesModule ListExampleShared
*/
'use strict';
-const React = require('react');
-const ReactNative = require('react-native');
-const {
+import * as React from 'react';
+import {
Animated,
Image,
Platform,
@@ -20,10 +16,10 @@ const {
Switch,
Text,
TextInput,
- View,
-} = ReactNative;
+ View
+} from 'react-native';
-type Item = {title: string, text: string, key: string, pressed: boolean, noImage?: ?boolean};
+type Item = { title: string, text: string, key: string, pressed: boolean, noImage?: ?boolean };
function genItemData(count: number, start: number = 0): Array- {
const dataBlob = [];
@@ -31,9 +27,9 @@ function genItemData(count: number, start: number = 0): Array
- {
const itemHash = Math.abs(hashCode('Item ' + ii));
dataBlob.push({
title: 'Item ' + ii,
- text: LOREM_IPSUM.substr(0, itemHash % 301 + 20),
+ text: LOREM_IPSUM.substr(0, (itemHash % 301) + 20),
key: String(ii),
- pressed: false,
+ pressed: false
});
}
return dataBlob;
@@ -48,30 +44,34 @@ class ItemComponent extends React.PureComponent<{
item: Item,
onPress: (key: string) => void,
onShowUnderlay?: () => void,
- onHideUnderlay?: () => void,
+ onHideUnderlay?: () => void
}> {
_onPress = () => {
this.props.onPress(this.props.item.key);
};
render() {
- const {fixedHeight, horizontal, item} = this.props;
+ const { fixedHeight, horizontal, item } = this.props;
const itemHash = Math.abs(hashCode(item.title));
const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length];
return (
-
- {!item.noImage && }
-
+ >
+
+ {!item.noImage && }
+
{item.title} - {item.text}
@@ -80,13 +80,15 @@ class ItemComponent extends React.PureComponent<{
}
}
-const renderStackedItem = ({item}: {item: Item}) => {
+const renderStackedItem = ({ item }: { item: Item }) => {
const itemHash = Math.abs(hashCode(item.title));
const imgSource = THUMB_URLS[itemHash % THUMB_URLS.length];
return (
- {item.title} - {item.text}
-
+
+ {item.title} - {item.text}
+
+
);
};
@@ -123,27 +125,34 @@ class SeparatorComponent extends React.PureComponent<{}> {
}
}
-class ItemSeparatorComponent extends React.PureComponent<$FlowFixMeProps> {
+class ItemSeparatorComponent extends React.PureComponent<{}> {
render() {
const style = this.props.highlighted
- ? [styles.itemSeparator, {marginLeft: 0, backgroundColor: 'rgb(217, 217, 217)'}]
+ ? [styles.itemSeparator, { marginLeft: 0, backgroundColor: 'rgb(217, 217, 217)' }]
: styles.itemSeparator;
return ;
}
}
-class Spindicator extends React.PureComponent<$FlowFixMeProps> {
+class Spindicator extends React.PureComponent<{}> {
render() {
return (
-
+
);
}
}
@@ -160,44 +169,46 @@ const THUMB_URLS = [
require('./Thumbnails/party.png'),
require('./Thumbnails/poke.png'),
require('./Thumbnails/superlike.png'),
- require('./Thumbnails/victory.png'),
+ require('./Thumbnails/victory.png')
];
-const LOREM_IPSUM = 'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix \
-civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id \
-integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem \
-vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud \
-modus, putant invidunt reprehendunt ne qui.';
+const LOREM_IPSUM =
+ 'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix ' +
+ 'civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id ' +
+ 'integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem ' +
+ 'vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud ' +
+ 'modus, putant invidunt reprehendunt ne qui.';
/* eslint no-bitwise: 0 */
function hashCode(str: string): number {
let hash = 15;
for (let ii = str.length - 1; ii >= 0; ii--) {
- hash = ((hash << 5) - hash) + str.charCodeAt(ii);
+ hash = (hash << 5) - hash + str.charCodeAt(ii);
}
return hash;
}
-const HEADER = {height: 30, width: 100};
+const HEADER = { height: 30, width: 100 };
const SEPARATOR_HEIGHT = StyleSheet.hairlineWidth;
function getItemLayout(data: any, index: number, horizontal?: boolean) {
- const [length, separator, header] = horizontal ?
- [HORIZ_WIDTH, 0, HEADER.width] : [ITEM_HEIGHT, SEPARATOR_HEIGHT, HEADER.height];
- return {length, offset: (length + separator) * index + header, index};
+ const [length, separator, header] = horizontal
+ ? [HORIZ_WIDTH, 0, HEADER.width]
+ : [ITEM_HEIGHT, SEPARATOR_HEIGHT, HEADER.height];
+ return { length, offset: (length + separator) * index + header, index };
}
function pressItem(context: Object, key: string) {
const index = Number(key);
const pressed = !context.state.data[index].pressed;
- context.setState((state) => {
+ context.setState(state => {
const newData = [...state.data];
newData[index] = {
...state.data[index],
pressed,
- title: 'Item ' + key + (pressed ? ' (pressed)' : ''),
+ title: 'Item ' + key + (pressed ? ' (pressed)' : '')
};
- return {data: newData};
+ return { data: newData };
});
}
@@ -209,9 +220,9 @@ function renderSmallSwitchOption(context: Object, key: string) {
{key}:
context.setState({ [key]: value })}
style={styles.smallSwitch}
value={context.state[key]}
- onValueChange={(value) => context.setState({[key]: value})}
/>
);
@@ -223,8 +234,8 @@ function PlainInput(props: Object) {
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
- underlineColorAndroid="transparent"
style={styles.searchTextInput}
+ underlineColorAndroid="transparent"
{...props}
/>
);
@@ -235,31 +246,31 @@ const styles = StyleSheet.create({
...HEADER,
alignSelf: 'center',
alignItems: 'center',
- justifyContent: 'center',
+ justifyContent: 'center'
},
headerFooterContainer: {
- backgroundColor: 'rgb(239, 239, 244)',
+ backgroundColor: 'rgb(239, 239, 244)'
},
horizItem: {
- alignSelf: 'flex-start', // Necessary for touch highlight
+ alignSelf: 'flex-start' // Necessary for touch highlight
},
item: {
- flex: 1,
+ flex: 1
},
itemSeparator: {
height: SEPARATOR_HEIGHT,
backgroundColor: 'rgb(200, 199, 204)',
- marginLeft: 60,
+ marginLeft: 60
},
option: {
flexDirection: 'row',
padding: 8,
- paddingRight: 0,
+ paddingRight: 0
},
row: {
flexDirection: 'row',
padding: 10,
- backgroundColor: 'white',
+ backgroundColor: 'white'
},
searchTextInput: {
backgroundColor: 'white',
@@ -270,51 +281,51 @@ const styles = StyleSheet.create({
paddingVertical: 0,
height: 26,
fontSize: 14,
- flexGrow: 1,
+ flexGrow: 1
},
separator: {
height: SEPARATOR_HEIGHT,
- backgroundColor: 'rgb(200, 199, 204)',
+ backgroundColor: 'rgb(200, 199, 204)'
},
smallSwitch: Platform.select({
android: {
top: 1,
margin: -6,
- transform: [{scale: 0.7}],
+ transform: [{ scale: 0.7 }]
},
ios: {
top: 4,
margin: -10,
- transform: [{scale: 0.5}],
- },
+ transform: [{ scale: 0.5 }]
+ }
}),
stacked: {
alignItems: 'center',
backgroundColor: 'white',
- padding: 10,
+ padding: 10
},
thumb: {
width: 50,
height: 50,
- left: -5,
+ left: -5
},
spindicator: {
marginLeft: 'auto',
marginTop: 8,
width: 2,
height: 16,
- backgroundColor: 'darkgray',
+ backgroundColor: 'darkgray'
},
stackedText: {
padding: 4,
- fontSize: 18,
+ fontSize: 18
},
text: {
- flex: 1,
- },
+ flex: 1
+ }
});
-module.exports = {
+export {
FooterComponent,
HeaderComponent,
ItemComponent,
@@ -326,5 +337,5 @@ module.exports = {
getItemLayout,
pressItem,
renderSmallSwitchOption,
- renderStackedItem,
+ renderStackedItem
};
diff --git a/packages/docs/src/components/Image/Image.stories.js b/packages/docs/src/components/Image/Image.stories.js
new file mode 100644
index 00000000..362ecb1c
--- /dev/null
+++ b/packages/docs/src/components/Image/Image.stories.js
@@ -0,0 +1,48 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ViewPropTypes': PropTypes.any,
+ blurRadius: PropTypes.number,
+ defaultSource: PropTypes.object, // ImageSourcePropType,
+ draggable: PropTypes.bool,
+ onError: PropTypes.func,
+ onLoad: PropTypes.func,
+ onLoadEnd: PropTypes.func,
+ onLoadStart: PropTypes.func,
+ resizeMode: PropTypes.oneOf(['contain', 'cover']),
+ source: PropTypes.object, ///ImageSourcePropType,
+ style: PropTypes.any
+};
+
+ofProps.defaultProps = {};
+
+const ofStatics = () => {};
+
+// hack to display instance methods
+ofStatics.propTypes = {
+ getSize: PropTypes.func,
+ prefetch: PropTypes.func,
+ queryCache: PropTypes.func
+};
+
+export default {
+ title: 'Components|Image',
+ includeStories: []
+};
+
+export { ofProps, ofStatics };
+export { default as defaultSource } from './examples/DefaultSource';
+export { default as draggable } from './examples/Draggable';
+export { default as onError } from './examples/OnError';
+export { default as onLoad } from './examples/OnLoad';
+export { default as onLoadEnd } from './examples/OnLoadEnd';
+export { default as onLoadStart } from './examples/OnLoadStart';
+export { default as resizeMode } from './examples/ResizeMode';
+export { default as source } from './examples/Source';
+export { default as styleBoxShadow } from './examples/StyleBoxShadow';
+export { default as styleTintColor } from './examples/StyleTintColor';
+
+export { default as getSize } from './examples/StaticGetSize';
+export { default as prefetch } from './examples/StaticPrefetch';
diff --git a/packages/docs/src/components/Image/Image.stories.mdx b/packages/docs/src/components/Image/Image.stories.mdx
new file mode 100644
index 00000000..af092968
--- /dev/null
+++ b/packages/docs/src/components/Image/Image.stories.mdx
@@ -0,0 +1,173 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './Image.stories.js';
+
+
+
+# Image
+
+An accessible and responsive image component.
+
+## Props
+
+
+
+### blurRadius
+
+The blur radius of the blur filter added to the image.
+
+### defaultSource
+
+The source `uri` is a string representing a placeholder to display while the main image is being loaded.
+
+```js
+type Source = { uri: string, width: number, height: number }
+```
+
+
+ {stories.defaultSource}
+
+
+### draggable
+
+This is a web-only prop that indicates whether the image can be dragged with
+native browser behavior. The default is `false`.
+
+
+ {stories.draggable}
+
+
+### onError
+
+Called on load error with ``{nativeEvent: {error}}``.
+
+
+ {stories.onError}
+
+
+### onLoad
+
+Called when load completes successfully.
+
+
+ {stories.onLoad}
+
+
+### resizeMode
+
+Determines how to resize the image when the frame doesn't match the raw image dimensions.
+
+```js
+type ResizeMode = 'center' | 'contain' | 'cover' | 'none' | 'repeat' | 'stretch';
+```
+
+
+ {stories.resizeMode}
+
+
+### source
+
+The source `uri` is a string representing the resource identifier for the image, which could be an http address or a base64 encoded image.
+
+```js
+type Source = { uri: string, width: number, height: number }
+```
+
+
+ {stories.source}
+
+
+### style
+
+```js
+{
+ ...ViewProps.style
+ resizeMode: ResizeMode
+ tintColor: Color
+}
+```
+
+#### shadows
+
+Image shadows are derived exactly from the pixels.
+
+
+ {stories.styleBoxShadow}
+
+
+#### tintColor
+
+Tint color is applied to all opaque pixels.
+
+
+ {stories.styleTintColor}
+
+
+## Static methods
+
+
+
+### getSize(url, callback)
+
+```js
+type GetSize = (url: string, success: (width, height) => {}, failure: function) => void
+```
+
+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.
+
+(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.)
+
+```js
+const uri = 'https://www.domain.com/img-1.jpg';
+Image.getSize(uri, ((width, height) => {
+ // image size is available
+});
+```
+
+
+ {stories.getSize}
+
+
+### prefetch(url)
+
+```js
+type Prefetch = (url: string) => Promise
+```
+
+Prefetches a remote image for later use by downloading it. Once an image has been
+prefetched it is assumed to be in native browser caches and available for immediate
+rendering.
+
+```js
+const uri = 'https://www.domain.com/img-1.jpg';
+Image.prefetch(uri).then(() => {
+ // image is now prefetched
+});
+```
+
+
+ {stories.prefetch}
+
+
+### queryCache(list)
+
+Performs cache interrogation. Returns a mapping from URL to cache status:
+"disk", "memory", "disk/memory". If a requested URL is not in the mapping, it
+means it's not in the cache.
+
+```js
+Image.queryCache([
+ 'https://www.domain.com/img-1.jpg',
+ 'https://www.domain.com/img-2.missing',
+ 'https://www.domain.com/img-3.jpg'
+]).then(res => {
+ expect(res).toEqual({
+ 'https://www.domain.com/img-1.jpg': 'disk/memory',
+ 'https://www.domain.com/img-3.jpg': 'disk/memory'
+ });
+});
+```
diff --git a/packages/docs/src/components/Image/examples/DefaultSource.js b/packages/docs/src/components/Image/examples/DefaultSource.js
new file mode 100644
index 00000000..bffde1b8
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/DefaultSource.js
@@ -0,0 +1,8 @@
+import * as helpers from '../helpers';
+import sources from '../sources';
+import React from 'react';
+import { Image } from 'react-native';
+
+export default function Source() {
+ return ;
+}
diff --git a/packages/website/storybook/1-components/Image/examples/PropDraggable.js b/packages/docs/src/components/Image/examples/Draggable.js
similarity index 58%
rename from packages/website/storybook/1-components/Image/examples/PropDraggable.js
rename to packages/docs/src/components/Image/examples/Draggable.js
index 9ddb3c3d..c80a39ce 100644
--- a/packages/website/storybook/1-components/Image/examples/PropDraggable.js
+++ b/packages/docs/src/components/Image/examples/Draggable.js
@@ -1,16 +1,14 @@
-/**
- * @flow
- */
-
import sources from '../sources';
import React from 'react';
import { Image, StyleSheet, View } from 'react-native';
-const ImageDraggableExample = () => (
-
-
-
-);
+export default function Draggable() {
+ return (
+
+
+
+ );
+}
const styles = StyleSheet.create({
container: {
@@ -23,5 +21,3 @@ const styles = StyleSheet.create({
marginRight: 10
}
});
-
-export default ImageDraggableExample;
diff --git a/packages/website/storybook/1-components/Image/examples/MultipleSources.js b/packages/docs/src/components/Image/examples/MultipleSources.js
similarity index 99%
rename from packages/website/storybook/1-components/Image/examples/MultipleSources.js
rename to packages/docs/src/components/Image/examples/MultipleSources.js
index 7b33f631..233eb381 100644
--- a/packages/website/storybook/1-components/Image/examples/MultipleSources.js
+++ b/packages/docs/src/components/Image/examples/MultipleSources.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React, { PureComponent } from 'react';
import { Image, StyleSheet, Text, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/Image/examples/NetworkImage.js b/packages/docs/src/components/Image/examples/NetworkImage.js
similarity index 99%
rename from packages/website/storybook/1-components/Image/examples/NetworkImage.js
rename to packages/docs/src/components/Image/examples/NetworkImage.js
index f882e6e6..a92250fd 100644
--- a/packages/website/storybook/1-components/Image/examples/NetworkImage.js
+++ b/packages/docs/src/components/Image/examples/NetworkImage.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import * as helpers from '../helpers';
import { oneOf } from 'prop-types';
import sources from '../sources';
diff --git a/packages/docs/src/components/Image/examples/OnError.js b/packages/docs/src/components/Image/examples/OnError.js
new file mode 100644
index 00000000..fdbeca71
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/OnError.js
@@ -0,0 +1,7 @@
+import NetworkImage from './NetworkImage';
+import React from 'react';
+import sources from '../sources';
+
+export default function OnError() {
+ return ;
+}
diff --git a/packages/docs/src/components/Image/examples/OnLoad.js b/packages/docs/src/components/Image/examples/OnLoad.js
new file mode 100644
index 00000000..072b5ae9
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/OnLoad.js
@@ -0,0 +1,8 @@
+import { createUncachedURI } from '../helpers';
+import NetworkImage from './NetworkImage';
+import React from 'react';
+import sources from '../sources';
+
+export default function OnLoad() {
+ return ;
+}
diff --git a/packages/docs/src/components/Image/examples/OnLoadEnd.js b/packages/docs/src/components/Image/examples/OnLoadEnd.js
new file mode 100644
index 00000000..7aece0bf
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/OnLoadEnd.js
@@ -0,0 +1,8 @@
+import { createUncachedURI } from '../helpers';
+import NetworkImage from './NetworkImage';
+import React from 'react';
+import sources from '../sources';
+
+export default function OnLoadEnd() {
+ return ;
+}
diff --git a/packages/docs/src/components/Image/examples/OnLoadStart.js b/packages/docs/src/components/Image/examples/OnLoadStart.js
new file mode 100644
index 00000000..b954d91b
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/OnLoadStart.js
@@ -0,0 +1,8 @@
+import { createUncachedURI } from '../helpers';
+import NetworkImage from './NetworkImage';
+import React from 'react';
+import sources from '../sources';
+
+export default function OnLoadStart() {
+ return ;
+}
diff --git a/packages/docs/src/components/Image/examples/ResizeMode.js b/packages/docs/src/components/Image/examples/ResizeMode.js
new file mode 100644
index 00000000..cace40f3
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/ResizeMode.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import sources from '../sources';
+import { Image, StyleSheet, Text, View } from 'react-native';
+
+export default function ResizeMode() {
+ return (
+
+ {[sources.small].map((source, i) => {
+ return (
+
+
+
+ Center
+
+
+
+ Contain
+
+
+
+ Cover
+
+
+
+ Repeat
+
+
+
+ Stretch
+
+
+
+
+ );
+ })}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ horizontal: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ justifyContent: 'space-between'
+ },
+ resizeMode: {
+ borderColor: 'black',
+ borderWidth: 0.5,
+ height: 120,
+ width: 120
+ },
+ resizeModeText: {
+ marginBottom: '0.5rem'
+ },
+ leftMargin: {
+ marginLeft: 10
+ }
+});
diff --git a/packages/docs/src/components/Image/examples/Source.js b/packages/docs/src/components/Image/examples/Source.js
new file mode 100644
index 00000000..e2aafcdd
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/Source.js
@@ -0,0 +1,60 @@
+import sources from '../sources';
+import React from 'react';
+import { Image, StyleSheet, Text, View } from 'react-native';
+
+export default function Source() {
+ return (
+
+
+
+ Static image
+
+
+
+ Progressive JPEG
+
+
+
+ Animated GIF
+
+
+
+
+
+ PNG (base64)
+
+
+
+ SVG (base64)
+
+
+
+ SVG (inline data)
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ justifyContent: 'space-between'
+ },
+ column: {
+ alignItems: 'flex-start',
+ marginBottom: '1rem'
+ },
+ text: {
+ marginBottom: '0.5rem'
+ },
+ image: {
+ borderColor: 'black',
+ borderWidth: 0.5,
+ height: 120,
+ width: 120,
+ resizeMode: 'cover'
+ }
+});
diff --git a/packages/website/storybook/1-components/Image/examples/StaticGetSize.js b/packages/docs/src/components/Image/examples/StaticGetSize.js
similarity index 98%
rename from packages/website/storybook/1-components/Image/examples/StaticGetSize.js
rename to packages/docs/src/components/Image/examples/StaticGetSize.js
index 1e346a05..546b5458 100644
--- a/packages/website/storybook/1-components/Image/examples/StaticGetSize.js
+++ b/packages/docs/src/components/Image/examples/StaticGetSize.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { createUncachedURI } from '../helpers';
import sources from '../sources';
import React, { PureComponent } from 'react';
diff --git a/packages/website/storybook/1-components/Image/examples/StaticPrefetch.js b/packages/docs/src/components/Image/examples/StaticPrefetch.js
similarity index 99%
rename from packages/website/storybook/1-components/Image/examples/StaticPrefetch.js
rename to packages/docs/src/components/Image/examples/StaticPrefetch.js
index 9d831d85..fb4a62bd 100644
--- a/packages/website/storybook/1-components/Image/examples/StaticPrefetch.js
+++ b/packages/docs/src/components/Image/examples/StaticPrefetch.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { createUncachedURI } from '../helpers';
import sources from '../sources';
import React, { PureComponent } from 'react';
diff --git a/packages/docs/src/components/Image/examples/StyleBoxShadow.js b/packages/docs/src/components/Image/examples/StyleBoxShadow.js
new file mode 100644
index 00000000..e4bba66e
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/StyleBoxShadow.js
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';
+
+import React from 'react';
+import { Image, StyleSheet } from 'react-native';
+import source from '../sources/hawk.png';
+
+export default function StyleBoxShadow() {
+ return ;
+}
+
+const styles = StyleSheet.create({
+ box: {
+ width: 100,
+ height: 100,
+ overflow: 'visible',
+ shadowOpacity: 0.5,
+ shadowRadius: 3,
+ shadowOffset: { width: 2, height: 2 }
+ }
+});
diff --git a/packages/docs/src/components/Image/examples/StyleTintColor.js b/packages/docs/src/components/Image/examples/StyleTintColor.js
new file mode 100644
index 00000000..af489126
--- /dev/null
+++ b/packages/docs/src/components/Image/examples/StyleTintColor.js
@@ -0,0 +1,24 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';
+
+import React from 'react';
+import { Image, StyleSheet } from 'react-native';
+import source from '../sources/hawk.png';
+
+export default function StyleBoxShadow() {
+ return ;
+}
+
+const styles = StyleSheet.create({
+ box: {
+ width: 100,
+ height: 100,
+ borderWidth: 2,
+ tintColor: 'red'
+ }
+});
diff --git a/packages/website/storybook/1-components/Image/helpers.js b/packages/docs/src/components/Image/helpers.js
similarity index 91%
rename from packages/website/storybook/1-components/Image/helpers.js
rename to packages/docs/src/components/Image/helpers.js
index 664847d2..1eaf0800 100644
--- a/packages/website/storybook/1-components/Image/helpers.js
+++ b/packages/docs/src/components/Image/helpers.js
@@ -1,8 +1,3 @@
-/**
- * @flow
- */
-
-// import React from 'react';
import { StyleSheet } from 'react-native';
const createUncachedURI = source => {
diff --git a/packages/examples/src/RNTester/hawk.png b/packages/docs/src/components/Image/sources/hawk.png
similarity index 100%
rename from packages/examples/src/RNTester/hawk.png
rename to packages/docs/src/components/Image/sources/hawk.png
diff --git a/packages/website/storybook/1-components/Image/sources/index.js b/packages/docs/src/components/Image/sources/index.js
similarity index 98%
rename from packages/website/storybook/1-components/Image/sources/index.js
rename to packages/docs/src/components/Image/sources/index.js
index 254edc8e..189575e2 100644
--- a/packages/website/storybook/1-components/Image/sources/index.js
+++ b/packages/docs/src/components/Image/sources/index.js
@@ -1,4 +1,5 @@
import placeholder from './placeholder.jpg';
+import smallflower from './smallflower.jpg';
import staticImage from './ladybug.jpg';
const dataBase64Png =
@@ -14,10 +15,7 @@ const sources = {
'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'
},
broken: { uri: 'http://TYPO_ERROR.github.io/image.png' },
- small: {
- uri:
- 'https://images.unsplash.com/photo-1488584585634-35fc98ccb808?dpr=1&auto=format&fit=crop&w=100&h=66&q=60&cs=tinysrgb'
- },
+ small: smallflower,
smallAlt: {
uri:
'https://images.unsplash.com/photo-1481595357459-84468f6eeaac?dpr=1&auto=format&fit=crop&w=100&h=66&q=60&cs=tinysrgb'
diff --git a/packages/website/storybook/1-components/Image/sources/ladybug.jpg b/packages/docs/src/components/Image/sources/ladybug.jpg
similarity index 100%
rename from packages/website/storybook/1-components/Image/sources/ladybug.jpg
rename to packages/docs/src/components/Image/sources/ladybug.jpg
diff --git a/packages/website/storybook/1-components/Image/sources/placeholder.jpg b/packages/docs/src/components/Image/sources/placeholder.jpg
similarity index 100%
rename from packages/website/storybook/1-components/Image/sources/placeholder.jpg
rename to packages/docs/src/components/Image/sources/placeholder.jpg
diff --git a/packages/docs/src/components/Image/sources/smallflower.jpg b/packages/docs/src/components/Image/sources/smallflower.jpg
new file mode 100644
index 00000000..7ac39110
Binary files /dev/null and b/packages/docs/src/components/Image/sources/smallflower.jpg differ
diff --git a/packages/docs/src/components/ImageBackground/ImageBackground.stories.js b/packages/docs/src/components/ImageBackground/ImageBackground.stories.js
new file mode 100644
index 00000000..05c0db9d
--- /dev/null
+++ b/packages/docs/src/components/ImageBackground/ImageBackground.stories.js
@@ -0,0 +1,19 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ImagePropTypes': PropTypes.any,
+ children: PropTypes.number,
+ imageStyle: PropTypes.any
+};
+
+ofProps.defaultProps = {};
+
+export default {
+ title: 'Components|ImageBackground',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as children } from './examples/Children';
diff --git a/packages/docs/src/components/ImageBackground/ImageBackground.stories.mdx b/packages/docs/src/components/ImageBackground/ImageBackground.stories.mdx
new file mode 100644
index 00000000..8b61bd57
--- /dev/null
+++ b/packages/docs/src/components/ImageBackground/ImageBackground.stories.mdx
@@ -0,0 +1,20 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './ImageBackground.stories.js';
+
+
+
+# ImageBackground
+
+A image component with support for child content.
+
+## Props
+
+
+
+### children
+
+Content to display over the image.
+
+
+ {stories.children}
+
diff --git a/packages/website/storybook/1-components/ImageBackground/examples/PropChildren.js b/packages/docs/src/components/ImageBackground/examples/Children.js
similarity index 66%
rename from packages/website/storybook/1-components/ImageBackground/examples/PropChildren.js
rename to packages/docs/src/components/ImageBackground/examples/Children.js
index 4960d498..ef52b95b 100644
--- a/packages/website/storybook/1-components/ImageBackground/examples/PropChildren.js
+++ b/packages/docs/src/components/ImageBackground/examples/Children.js
@@ -1,16 +1,14 @@
-/**
- * @flow
- */
-
import sources from '../../Image/sources';
import React from 'react';
import { ImageBackground, StyleSheet, Text } from 'react-native';
-const ImageChildrenExample = () => (
-
- Child content
-
-);
+export default function Children() {
+ return (
+
+ Child content
+
+ );
+}
const styles = StyleSheet.create({
image: {
@@ -29,5 +27,3 @@ const styles = StyleSheet.create({
top: 50
}
});
-
-export default ImageChildrenExample;
diff --git a/packages/docs/src/components/Picker/Picker.stories.js b/packages/docs/src/components/Picker/Picker.stories.js
new file mode 100644
index 00000000..ea73f6cb
--- /dev/null
+++ b/packages/docs/src/components/Picker/Picker.stories.js
@@ -0,0 +1,42 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ViewPropTypes': PropTypes.any,
+ children: PropTypes.any,
+ enabled: PropTypes.bool,
+ onValueChange: PropTypes.func,
+ selectedValue: PropTypes.string,
+ style: PropTypes.any
+};
+
+ofProps.defaultProps = {};
+
+const ofPropsItem = () => {};
+
+ofPropsItem.propTypes = {
+ color: PropTypes.any,
+ label: PropTypes.string,
+ testID: PropTypes.string,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
+};
+
+export default {
+ title: 'Components|ImageBackground',
+ includeStories: []
+};
+
+export { ofProps, ofPropsItem };
+
+/*
+
+
+ {
+ window.alert(`itemValue: ${itemValue}, itemPosition: ${itemPosition}`);
+ }}
+/>
+
+
+*/
diff --git a/packages/docs/src/components/Picker/Picker.stories.mdx b/packages/docs/src/components/Picker/Picker.stories.mdx
new file mode 100644
index 00000000..9587848d
--- /dev/null
+++ b/packages/docs/src/components/Picker/Picker.stories.mdx
@@ -0,0 +1,71 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './Picker.stories.js';
+
+
+
+# Picker
+
+Renders the native `
);
-export default TextInputOnSelectionChangeExample;
+export default function OnSelectionChange() {
+ return ;
+}
diff --git a/packages/docs/src/components/TextInput/examples/Placeholder.js b/packages/docs/src/components/TextInput/examples/Placeholder.js
new file mode 100644
index 00000000..8d26f340
--- /dev/null
+++ b/packages/docs/src/components/TextInput/examples/Placeholder.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { styles } from '../helpers';
+import { TextInput, View } from 'react-native';
+
+export default function Placeholder() {
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/docs/src/components/TextInput/examples/PlaceholderTextColor.js b/packages/docs/src/components/TextInput/examples/PlaceholderTextColor.js
new file mode 100644
index 00000000..13d61593
--- /dev/null
+++ b/packages/docs/src/components/TextInput/examples/PlaceholderTextColor.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import { styles } from '../helpers';
+import { TextInput, View } from 'react-native';
+
+export default function PlaceholderTextColor() {
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropOnChange.js b/packages/docs/src/components/TextInput/examples/PropOnChange.js
similarity index 90%
rename from packages/website/storybook/1-components/TextInput/examples/PropOnChange.js
rename to packages/docs/src/components/TextInput/examples/PropOnChange.js
index f5b6ae38..f2ec71f7 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropOnChange.js
+++ b/packages/docs/src/components/TextInput/examples/PropOnChange.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropOnChangeText.js b/packages/docs/src/components/TextInput/examples/PropOnChangeText.js
similarity index 90%
rename from packages/website/storybook/1-components/TextInput/examples/PropOnChangeText.js
rename to packages/docs/src/components/TextInput/examples/PropOnChangeText.js
index 88deb052..e5694316 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropOnChangeText.js
+++ b/packages/docs/src/components/TextInput/examples/PropOnChangeText.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropOnKeyPress.js b/packages/docs/src/components/TextInput/examples/PropOnKeyPress.js
similarity index 90%
rename from packages/website/storybook/1-components/TextInput/examples/PropOnKeyPress.js
rename to packages/docs/src/components/TextInput/examples/PropOnKeyPress.js
index d6bc5c4f..4e634539 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropOnKeyPress.js
+++ b/packages/docs/src/components/TextInput/examples/PropOnKeyPress.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropOnSubmitEditing.js b/packages/docs/src/components/TextInput/examples/PropOnSubmitEditing.js
similarity index 91%
rename from packages/website/storybook/1-components/TextInput/examples/PropOnSubmitEditing.js
rename to packages/docs/src/components/TextInput/examples/PropOnSubmitEditing.js
index 4c1b6994..bcf7aff8 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropOnSubmitEditing.js
+++ b/packages/docs/src/components/TextInput/examples/PropOnSubmitEditing.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropSelection.js b/packages/docs/src/components/TextInput/examples/PropSelection.js
similarity index 90%
rename from packages/website/storybook/1-components/TextInput/examples/PropSelection.js
rename to packages/docs/src/components/TextInput/examples/PropSelection.js
index 85d31647..6ef56851 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropSelection.js
+++ b/packages/docs/src/components/TextInput/examples/PropSelection.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/PropStyle.js b/packages/docs/src/components/TextInput/examples/PropStyle.js
similarity index 90%
rename from packages/website/storybook/1-components/TextInput/examples/PropStyle.js
rename to packages/docs/src/components/TextInput/examples/PropStyle.js
index 00d5ed3e..94529e19 100644
--- a/packages/website/storybook/1-components/TextInput/examples/PropStyle.js
+++ b/packages/docs/src/components/TextInput/examples/PropStyle.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
/*
import React from 'react';
import { TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/Rewrite.js b/packages/docs/src/components/TextInput/examples/Rewrite.js
similarity index 98%
rename from packages/website/storybook/1-components/TextInput/examples/Rewrite.js
rename to packages/docs/src/components/TextInput/examples/Rewrite.js
index 62f51bda..305f54a7 100644
--- a/packages/website/storybook/1-components/TextInput/examples/Rewrite.js
+++ b/packages/docs/src/components/TextInput/examples/Rewrite.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { styles as helperStyles } from '../helpers';
import { StyleSheet, Text, TextInput, View } from 'react-native';
diff --git a/packages/docs/src/components/TextInput/examples/SecureTextEntry.js b/packages/docs/src/components/TextInput/examples/SecureTextEntry.js
new file mode 100644
index 00000000..1a51962f
--- /dev/null
+++ b/packages/docs/src/components/TextInput/examples/SecureTextEntry.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import { styles } from '../helpers';
+import { TextInput } from 'react-native';
+
+export default function SecureTextEntry() {
+ return (
+
+ );
+}
diff --git a/packages/docs/src/components/TextInput/examples/SelectTextOnFocus.js b/packages/docs/src/components/TextInput/examples/SelectTextOnFocus.js
new file mode 100644
index 00000000..2c4eb7e6
--- /dev/null
+++ b/packages/docs/src/components/TextInput/examples/SelectTextOnFocus.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { styles } from '../helpers';
+import { TextInput, View } from 'react-native';
+
+export default function SelectTextOnFocus() {
+ return (
+
+
+
+
+ );
+}
diff --git a/packages/website/storybook/1-components/TextInput/examples/TextInputEvents.js b/packages/docs/src/components/TextInput/examples/TextInputEvents.js
similarity index 99%
rename from packages/website/storybook/1-components/TextInput/examples/TextInputEvents.js
rename to packages/docs/src/components/TextInput/examples/TextInputEvents.js
index b78a3367..0ad5782b 100644
--- a/packages/website/storybook/1-components/TextInput/examples/TextInputEvents.js
+++ b/packages/docs/src/components/TextInput/examples/TextInputEvents.js
@@ -1,9 +1,4 @@
/* eslint-disable react/jsx-no-bind */
-
-/**
- * @flow
- */
-
import React from 'react';
import { styles as helperStyles } from '../helpers';
import { StyleSheet, Text, TextInput, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/examples/TouchableWrapper.js b/packages/docs/src/components/TextInput/examples/TouchableWrapper.js
similarity index 97%
rename from packages/website/storybook/1-components/TextInput/examples/TouchableWrapper.js
rename to packages/docs/src/components/TextInput/examples/TouchableWrapper.js
index d5bb7060..e3406bb4 100644
--- a/packages/website/storybook/1-components/TextInput/examples/TouchableWrapper.js
+++ b/packages/docs/src/components/TextInput/examples/TouchableWrapper.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { styles as helperStyles } from '../helpers';
import { StyleSheet, TextInput, TouchableWithoutFeedback, View } from 'react-native';
diff --git a/packages/website/storybook/1-components/TextInput/helpers.js b/packages/docs/src/components/TextInput/helpers.js
similarity index 98%
rename from packages/website/storybook/1-components/TextInput/helpers.js
rename to packages/docs/src/components/TextInput/helpers.js
index b2e2e9a8..85daa99f 100644
--- a/packages/website/storybook/1-components/TextInput/helpers.js
+++ b/packages/docs/src/components/TextInput/helpers.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { any, string } from 'prop-types';
import { StyleSheet, Text, View } from 'react-native';
diff --git a/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.js b/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.js
new file mode 100644
index 00000000..53f67394
--- /dev/null
+++ b/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.js
@@ -0,0 +1,27 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...TouchableWithoutFeedbackPropTypes': PropTypes.any,
+ activeOpacity: PropTypes.number,
+ onHideUnderlay: PropTypes.func,
+ onShowUnderlay: PropTypes.func,
+ underlayColor: PropTypes.string
+};
+
+ofProps.defaultProps = {
+ activeOpacity: '0.85',
+ underlayColor: 'black'
+};
+
+export default {
+ title: 'Components|TouchableHighlight',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as delayEvents } from './examples/DelayEvents';
+export { default as disabled } from './examples/Disabled';
+export { default as feedbackEvents } from './examples/FeedbackEvents';
+export { default as styleOverrides } from './examples/StyleOverrides';
diff --git a/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.mdx b/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.mdx
new file mode 100644
index 00000000..f2b7b11c
--- /dev/null
+++ b/packages/docs/src/components/TouchableHighlight/TouchableHighlight.stories.mdx
@@ -0,0 +1,38 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './TouchableHighlight.stories.js';
+
+
+
+# TouchableHighlight
+
+A wrapper for making views respond properly to touches. On press down, the
+opacity of the wrapped view is decreased, which allows the underlay color to
+show through, darkening or tinting the view.
+
+The underlay comes from wrapping the child in a new View, which can affect
+layout, and sometimes cause unwanted visual artifacts if not used correctly, for
+example if the backgroundColor of the wrapped view isn't explicitly set to an
+opaque color.
+
+TouchableHighlight must have one child (not zero or more than one). If you wish
+to have several child components, wrap them in a View.
+
+## Props
+
+
+
+### activeOpacity
+
+Determines what the opacity of the wrapped view should be when active.
+
+### onHideUnderlay
+
+Called immediately after the underlay is hidden.
+
+### onShowUnderlay
+
+Called immediately after the underlay is shown
+
+### underlayColor
+
+The color of the underlay that will show through when the touch is active.
diff --git a/packages/website/storybook/1-components/Touchable/examples/DelayEvents.js b/packages/docs/src/components/TouchableHighlight/examples/DelayEvents.js
similarity index 99%
rename from packages/website/storybook/1-components/Touchable/examples/DelayEvents.js
rename to packages/docs/src/components/TouchableHighlight/examples/DelayEvents.js
index fd3615c4..871d2de0 100644
--- a/packages/website/storybook/1-components/Touchable/examples/DelayEvents.js
+++ b/packages/docs/src/components/TouchableHighlight/examples/DelayEvents.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { oneOf } from 'prop-types';
import React, { PureComponent } from 'react';
import {
diff --git a/packages/website/storybook/1-components/Touchable/examples/PropDisabled.js b/packages/docs/src/components/TouchableHighlight/examples/Disabled.js
similarity index 99%
rename from packages/website/storybook/1-components/Touchable/examples/PropDisabled.js
rename to packages/docs/src/components/TouchableHighlight/examples/Disabled.js
index 08e917ac..81e953e9 100644
--- a/packages/website/storybook/1-components/Touchable/examples/PropDisabled.js
+++ b/packages/docs/src/components/TouchableHighlight/examples/Disabled.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import {
StyleSheet,
diff --git a/packages/website/storybook/1-components/Touchable/examples/FeedbackEvents.js b/packages/docs/src/components/TouchableHighlight/examples/FeedbackEvents.js
similarity index 99%
rename from packages/website/storybook/1-components/Touchable/examples/FeedbackEvents.js
rename to packages/docs/src/components/TouchableHighlight/examples/FeedbackEvents.js
index a0e067d4..451d9a62 100644
--- a/packages/website/storybook/1-components/Touchable/examples/FeedbackEvents.js
+++ b/packages/docs/src/components/TouchableHighlight/examples/FeedbackEvents.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import { oneOf } from 'prop-types';
import React, { PureComponent } from 'react';
import {
diff --git a/packages/website/storybook/1-components/Touchable/examples/CustomStyleOverrides.js b/packages/docs/src/components/TouchableHighlight/examples/StyleOverrides.js
similarity index 98%
rename from packages/website/storybook/1-components/Touchable/examples/CustomStyleOverrides.js
rename to packages/docs/src/components/TouchableHighlight/examples/StyleOverrides.js
index bb43e088..064e4675 100644
--- a/packages/website/storybook/1-components/Touchable/examples/CustomStyleOverrides.js
+++ b/packages/docs/src/components/TouchableHighlight/examples/StyleOverrides.js
@@ -1,7 +1,3 @@
-/**
- * @flow
- */
-
import React from 'react';
import { StyleSheet, View, Text, TouchableHighlight } from 'react-native';
diff --git a/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.js b/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.js
new file mode 100644
index 00000000..e85d11c6
--- /dev/null
+++ b/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.js
@@ -0,0 +1,32 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...TouchableWithoutFeedbackPropTypes': PropTypes.any,
+ activeOpacity: PropTypes.number,
+ focusedOpacity: PropTypes.func,
+ onShowUnderlay: PropTypes.func,
+ underlayColor: PropTypes.string
+};
+
+ofProps.defaultProps = {
+ activeOpacity: '0.2',
+ focusedOpacity: '0.7'
+};
+
+const ofMethods = () => {};
+
+ofMethods.propTypes = {
+ setOpacityTo: PropTypes.func
+};
+
+export default {
+ title: 'Components|TouchableOpacity',
+ includeStories: []
+};
+
+export { ofMethods, ofProps };
+//export { default as color } from './examples/Color';
+export { default as disabled } from './examples/Disabled';
+//export { default as onPress } from './examples/OnPress';
diff --git a/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.mdx b/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.mdx
new file mode 100644
index 00000000..f38555da
--- /dev/null
+++ b/packages/docs/src/components/TouchableOpacity/TouchableOpacity.stories.mdx
@@ -0,0 +1,28 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './TouchableOpacity.stories.js';
+
+
+
+# TouchableOpacity
+
+A wrapper for making views respond properly to touches. On press down, the
+opacity of the wrapped view is decreased, dimming it.
+
+Opacity is controlled by wrapping the children in an Animated.View, which is
+added to the view hierarchy. Be aware that this can affect layout.
+
+## Props
+
+
+
+### activeOpacity
+
+Determines what the opacity of the wrapped view should be when active.
+
+### focusedOpacity
+
+Determines what the opacity of the wrapped view should be when it is focused.
+
+## Instance methods
+
+
diff --git a/packages/docs/src/components/TouchableOpacity/examples/DelayEvents.js b/packages/docs/src/components/TouchableOpacity/examples/DelayEvents.js
new file mode 100644
index 00000000..871d2de0
--- /dev/null
+++ b/packages/docs/src/components/TouchableOpacity/examples/DelayEvents.js
@@ -0,0 +1,88 @@
+import { oneOf } from 'prop-types';
+import React, { PureComponent } from 'react';
+import {
+ StyleSheet,
+ Text,
+ TouchableHighlight,
+ TouchableOpacity,
+ TouchableWithoutFeedback,
+ View
+} from 'react-native';
+
+const Touchables = {
+ highlight: TouchableHighlight,
+ opacity: TouchableOpacity,
+ withoutFeedback: TouchableWithoutFeedback
+};
+
+export default class TouchableDelayEvents extends PureComponent {
+ static propTypes = {
+ touchable: oneOf(['highlight', 'opacity', 'withoutFeedback'])
+ };
+
+ static defaultProps = {
+ touchable: 'highlight'
+ };
+
+ state = { eventLog: [] };
+
+ render() {
+ const Touchable = Touchables[this.props.touchable];
+ const { displayName } = Touchable;
+ return (
+
+
+
+
+ {displayName}
+
+
+
+
+ {this.state.eventLog.map((e, ii) => (
+ {e}
+ ))}
+
+
+ );
+ }
+
+ _createPressHandler = eventName => {
+ return () => {
+ const limit = 6;
+ this.setState(state => {
+ const eventLog = state.eventLog.slice(0, limit - 1);
+ eventLog.unshift(eventName);
+ return { eventLog };
+ });
+ };
+ };
+}
+
+const styles = StyleSheet.create({
+ touchableText: {
+ borderRadius: 8,
+ padding: 5,
+ borderWidth: 1,
+ borderColor: 'black',
+ color: '#007AFF',
+ borderStyle: 'solid',
+ textAlign: 'center'
+ },
+ eventLogBox: {
+ padding: 10,
+ marginTop: 10,
+ height: 120,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: '#f0f0f0',
+ backgroundColor: '#f9f9f9'
+ }
+});
diff --git a/packages/docs/src/components/TouchableOpacity/examples/Disabled.js b/packages/docs/src/components/TouchableOpacity/examples/Disabled.js
new file mode 100644
index 00000000..81e953e9
--- /dev/null
+++ b/packages/docs/src/components/TouchableOpacity/examples/Disabled.js
@@ -0,0 +1,96 @@
+import React from 'react';
+import {
+ StyleSheet,
+ View,
+ Text,
+ TouchableHighlight,
+ TouchableOpacity,
+ TouchableWithoutFeedback
+} from 'react-native';
+
+const action = msg => () => {
+ console.log(msg);
+};
+
+class TouchableHighlightDisabled extends React.Component {
+ render() {
+ return (
+
+
+ Disabled TouchableHighlight
+
+
+
+ Enabled TouchableHighlight
+
+
+ );
+ }
+}
+
+class TouchableOpacityDisabled extends React.Component {
+ render() {
+ return (
+
+
+ Disabled TouchableOpacity
+
+
+
+ Enabled TouchableOpacity
+
+
+ );
+ }
+}
+
+class TouchableWithoutFeedbackDisabled extends React.Component {
+ render() {
+ return (
+
+
+
+ Disabled TouchableWithoutFeedback
+
+
+
+
+
+ Enabled TouchableWithoutFeedback
+
+
+
+ );
+ }
+}
+
+export { TouchableHighlightDisabled, TouchableOpacityDisabled, TouchableWithoutFeedbackDisabled };
+
+const styles = StyleSheet.create({
+ row: {
+ justifyContent: 'center',
+ flexDirection: 'row'
+ },
+ block: {
+ padding: 10
+ }
+});
diff --git a/packages/docs/src/components/TouchableOpacity/examples/FeedbackEvents.js b/packages/docs/src/components/TouchableOpacity/examples/FeedbackEvents.js
new file mode 100644
index 00000000..451d9a62
--- /dev/null
+++ b/packages/docs/src/components/TouchableOpacity/examples/FeedbackEvents.js
@@ -0,0 +1,84 @@
+import { oneOf } from 'prop-types';
+import React, { PureComponent } from 'react';
+import {
+ StyleSheet,
+ Text,
+ TouchableHighlight,
+ TouchableOpacity,
+ TouchableWithoutFeedback,
+ View
+} from 'react-native';
+
+const Touchables = {
+ highlight: TouchableHighlight,
+ opacity: TouchableOpacity,
+ withoutFeedback: TouchableWithoutFeedback
+};
+
+export default class TouchableFeedbackEvents extends PureComponent {
+ static propTypes = {
+ touchable: oneOf(['highlight', 'opacity', 'withoutFeedback'])
+ };
+
+ static defaultProps = {
+ touchable: 'highlight'
+ };
+
+ state = { eventLog: [] };
+
+ render() {
+ const Touchable = Touchables[this.props.touchable];
+ return (
+
+
+
+
+ Press Me
+
+
+
+
+ {this.state.eventLog.map((e, ii) => (
+ {e}
+ ))}
+
+
+ );
+ }
+
+ _createPressHandler = eventName => {
+ return () => {
+ const limit = 6;
+ this.setState(state => {
+ const eventLog = state.eventLog.slice(0, limit - 1);
+ eventLog.unshift(eventName);
+ return { eventLog };
+ });
+ };
+ };
+}
+
+const styles = StyleSheet.create({
+ touchableText: {
+ borderRadius: 8,
+ padding: 5,
+ borderWidth: 1,
+ borderColor: 'black',
+ color: '#007AFF',
+ borderStyle: 'solid',
+ textAlign: 'center'
+ },
+ eventLogBox: {
+ padding: 10,
+ marginTop: 10,
+ height: 120,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: '#f0f0f0',
+ backgroundColor: '#f9f9f9'
+ }
+});
diff --git a/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.js b/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.js
new file mode 100644
index 00000000..6eb8ba10
--- /dev/null
+++ b/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.js
@@ -0,0 +1,26 @@
+import PropTypes from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ '...ViewPropsTypes': PropTypes.any,
+ delayLongPress: PropTypes.number,
+ delayPressIn: PropTypes.number,
+ delayPressOut: PropTypes.number,
+ disabled: PropTypes.bool,
+ onLongPress: PropTypes.func,
+ onPress: PropTypes.func,
+ onPressIn: PropTypes.func,
+ onPressOut: PropTypes.func,
+ pressRetentionOffset: PropTypes.object
+};
+
+export default {
+ title: 'Components|TouchableWithoutFeedback',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as delayEvents } from './examples/DelayEvents';
+export { default as disabled } from './examples/Disabled';
+export { default as feedbackEvents } from './examples/FeedbackEvents';
diff --git a/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.mdx b/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.mdx
new file mode 100644
index 00000000..ea8766da
--- /dev/null
+++ b/packages/docs/src/components/TouchableWithoutFeedback/TouchableWithoutFeedback.stories.mdx
@@ -0,0 +1,63 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './TouchableWithoutFeedback.stories.js';
+
+
+
+# TouchableWithoutFeedback
+
+Do not use unless you have a very good reason. All the elements that respond to
+press should have a visual feedback when touched. This is one of the primary
+reason a "web" app doesn't feel "native".
+
+NOTE: `TouchableWithoutFeedback` supports only one child. If you wish to have
+several child components, wrap them in a `View`.
+
+## Props
+
+
+
+### delayLongPress
+
+Delay in ms, from `onPressIn` to before `onLongPress` is called. The default is `500`.
+
+### delayPressIn
+
+Delay in ms, from pointer down to before `onPressIn` is called.
+
+### delayPressOut
+
+Delay in ms, from pointer up to before `onPressOut` is called.
+
+### disabled
+
+Disables all pointer interactions with the element.
+
+
+ {stories.disabled}
+
+
+### onLongPress
+
+Called when the pointer is held down for as long as the value of `delayLongPress`.
+
+### onPress
+
+Called when the pointer is released, but not if cancelled (e.g. by a scroll that steals the responder lock).
+
+### pressRetentionOffset
+
+When the scroll view is disabled, this defines how far the pointer may move off
+of the element before it becomes deactivated. Once deactivated, try moving the pointer
+back over the element and you'll see that the element is once again reactivated!
+Move it back and forth several times while the scroll view is disabled. Ensure
+you pass in a constant to reduce memory allocations.
+
+## Examples
+
+
+ {stories.delayEvents}
+
+
+
+ {stories.feedbackEvents}
+
diff --git a/packages/docs/src/components/TouchableWithoutFeedback/examples/DelayEvents.js b/packages/docs/src/components/TouchableWithoutFeedback/examples/DelayEvents.js
new file mode 100644
index 00000000..9b3075bd
--- /dev/null
+++ b/packages/docs/src/components/TouchableWithoutFeedback/examples/DelayEvents.js
@@ -0,0 +1,62 @@
+import React from 'react';
+import { StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native';
+
+export default function DelayEvents() {
+ const [eventLog, updateEventLog] = React.useState([]);
+
+ const handlePress = eventName => {
+ return () => {
+ const limit = 6;
+ updateEventLog(state => {
+ const nextState = state.slice(0, limit - 1);
+ nextState.unshift(eventName);
+ return nextState;
+ });
+ };
+ };
+
+ return (
+
+
+
+
+ TouchableWithoutFeedback
+
+
+
+
+ {eventLog.map((e, ii) => (
+ {e}
+ ))}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ touchableText: {
+ borderRadius: 8,
+ padding: 5,
+ borderWidth: 1,
+ borderColor: 'black',
+ color: '#007AFF',
+ borderStyle: 'solid',
+ textAlign: 'center'
+ },
+ eventLogBox: {
+ padding: 10,
+ marginTop: 10,
+ height: 120,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: '#f0f0f0',
+ backgroundColor: '#f9f9f9'
+ }
+});
diff --git a/packages/docs/src/components/TouchableWithoutFeedback/examples/Disabled.js b/packages/docs/src/components/TouchableWithoutFeedback/examples/Disabled.js
new file mode 100644
index 00000000..5aed2e46
--- /dev/null
+++ b/packages/docs/src/components/TouchableWithoutFeedback/examples/Disabled.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import { StyleSheet, View, Text, TouchableWithoutFeedback } from 'react-native';
+
+const action = msg => () => {
+ console.log(msg);
+};
+
+export default function Disabled() {
+ return (
+
+
+
+ Disabled TouchableWithoutFeedback
+
+
+
+
+
+ Enabled TouchableWithoutFeedback
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ row: {
+ justifyContent: 'center',
+ flexDirection: 'row'
+ },
+ block: {
+ padding: 10
+ }
+});
diff --git a/packages/docs/src/components/TouchableWithoutFeedback/examples/FeedbackEvents.js b/packages/docs/src/components/TouchableWithoutFeedback/examples/FeedbackEvents.js
new file mode 100644
index 00000000..fa4e67bc
--- /dev/null
+++ b/packages/docs/src/components/TouchableWithoutFeedback/examples/FeedbackEvents.js
@@ -0,0 +1,59 @@
+import React from 'react';
+import { StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native';
+
+export default function FeedbackEvents() {
+ const [eventLog, updateEventLog] = React.useState([]);
+
+ const handlePress = eventName => {
+ return () => {
+ const limit = 6;
+ updateEventLog(state => {
+ const nextState = state.slice(0, limit - 1);
+ nextState.unshift(eventName);
+ return nextState;
+ });
+ };
+ };
+
+ return (
+
+
+
+
+ Press Me
+
+
+
+
+ {eventLog.map((e, ii) => (
+ {e}
+ ))}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ touchableText: {
+ borderRadius: 8,
+ padding: 5,
+ borderWidth: 1,
+ borderColor: 'black',
+ color: '#007AFF',
+ borderStyle: 'solid',
+ textAlign: 'center'
+ },
+ eventLogBox: {
+ padding: 10,
+ marginTop: 10,
+ height: 120,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: '#f0f0f0',
+ backgroundColor: '#f9f9f9'
+ }
+});
diff --git a/packages/docs/src/components/View/View.stories.js b/packages/docs/src/components/View/View.stories.js
new file mode 100644
index 00000000..a4958f6b
--- /dev/null
+++ b/packages/docs/src/components/View/View.stories.js
@@ -0,0 +1,56 @@
+import PropTypes, { any, bool, func, object, oneOf, string } from 'prop-types';
+
+const ofProps = () => {};
+
+ofProps.propTypes = {
+ /* test */
+ accessibilityLabel: PropTypes.string,
+ accessibilityLiveRegion: oneOf(['assertive', 'none', 'polite']),
+ accessibilityRelationship: object,
+ accessibilityRole: string,
+ accessibilityState: object,
+ accessible: bool,
+ children: any,
+ forwardedRef: any,
+ hitSlop: object,
+ importantForAccessibility: oneOf(['auto', 'no', 'no-hide-descendants', 'yes']),
+ itemID: string,
+ itemProp: string,
+ itemRef: string,
+ itemScope: string,
+ itemType: string,
+ nativeID: string,
+ onBlur: func,
+ onContextMenu: func,
+ onFocus: func,
+ onKeyDown: func,
+ onKeyUp: func,
+ onLayout: func,
+ onMoveShouldSetResponder: func,
+ onMoveShouldSetResponderCapture: func,
+ onResponderGrant: func,
+ onResponderMove: func,
+ onResponderReject: func,
+ onResponderRelease: func,
+ onResponderTerminate: func,
+ onResponderTerminationRequest: func,
+ onStartShouldSetResponder: func,
+ onStartShouldSetResponderCapture: func,
+ onWheel: func,
+ pointerEvents: oneOf(['auto', 'box-none', 'box-only', 'none']),
+ style: object,
+ testID: string
+};
+
+export default {
+ title: 'Components|View',
+ includeStories: []
+};
+
+export { ofProps };
+export { default as onLayout } from './examples/OnLayout';
+export { default as pointerEvents } from './examples/PointerEvents';
+export { default as styleBorder } from './examples/StyleBorder';
+export { default as styleBoxShadow } from './examples/StyleBoxShadow';
+export { default as styleFlexbox } from './examples/StyleFlexbox';
+export { default as styleZIndex } from './examples/StyleZIndex';
diff --git a/packages/docs/src/components/View/View.stories.mdx b/packages/docs/src/components/View/View.stories.mdx
new file mode 100644
index 00000000..362ac1e1
--- /dev/null
+++ b/packages/docs/src/components/View/View.stories.mdx
@@ -0,0 +1,299 @@
+import { Meta, Props, Story, Preview } from '@storybook/addon-docs/blocks';
+import * as stories from './View.stories.js';
+
+
+
+# View
+
+View is the fundamental UI building block. It is a component that supports
+style, layout with flexbox, and accessibility controls. It can be nested inside
+another View and has zero-to-many children of any type.
+
+## Props
+
+Please also refer to the in-depth "Accessibility" and "Style" guides.
+
+
+
+### hitSlop
+
+This defines how far a touch event can start away from the view (in pixels).
+Typical interface guidelines recommend touch targets that are at least 30 - 40
+points/density-independent pixels.
+
+For example, if a touchable view has a height of 20 the touchable height can be
+extended to 40 with hitSlop.
+
+```js
+
+```
+
+### onLayout
+
+This is invoked when a component is mounted and when its layout changes. `x` and
+`y` are the offsets from the parent node.
+
+```
+const onLayout = ({
+ nativeEvent: {
+ layout: { x, y, width, height }
+ }
+}) => {}
+
+
+```
+
+
+ {stories.onLayout}
+
+
+### onMoveShouldSetResponder
+
+Does this view want to "claim" touch responsiveness? This is called for every
+touch move on the View when it is not the responder.
+
+### onMoveShouldSetResponderCapture
+
+If a parent View wants to prevent a child View from becoming responder on a
+move, it should have this handler return `true`.
+
+### onResponderGrant
+
+The View is now responding to touch events. This is the time to highlight and
+show the user what is happening. For most touch interactions, you'll simply want
+to wrap your component in `TouchableHighlight` or `TouchableOpacity`.
+
+### onResponderMove
+
+The user is moving their finger.
+
+### onResponderReject
+
+Another responder is already active and will not release it to the View asking
+to be the responder.
+
+### onResponderRelease
+
+Fired at the end of the touch.
+
+### onResponderTerminate
+
+The responder has been taken from the view.
+
+### onResponderTerminationRequest
+
+Some other view wants to become responder and is asking this view to release its
+responder. Returning `true` allows its release.
+
+### onStartShouldSetResponder
+
+Does this view want to become responder on the start of a touch?
+
+### onStartShouldSetResponderCapture
+
+If a parent view wants to prevent a child view from becoming the responder on a
+touch start, it should have this handler return true.
+
+### pointerEvents
+
+Controls whether the View can be the target of touch events. Allowed values are
+`auto`, `box-only`, `box-none`, and `none`. A value of `box-none` preserves
+pointer events on the element's children; `box-only` disables pointer events on
+the element's children.
+
+
+ {stories.pointerEvents}
+
+
+### testID
+
+Used to locate this view in end-to-end tests. The test ID is rendered to a
+`data-testid` DOM attribute.
+
+### style
+
+...
+
+```js
+{
+ ...CSSCustomProperties,
+ alignContent: string,
+ alignItems: string,
+ alignSelf: string,
+ animationDelay: string,
+ animationDirection: string,
+ animationFillMode: string,
+ animationKeyframes: Array