diff --git a/examples/components/TextInput/TextInputExample.js b/examples/components/TextInput/TextInputExample.js
index 3f1e62c1..df7f813f 100644
--- a/examples/components/TextInput/TextInputExample.js
+++ b/examples/components/TextInput/TextInputExample.js
@@ -1,41 +1,884 @@
import React from 'react';
import { storiesOf, action } from '@kadira/storybook';
-import { StyleSheet, TextInput, View } from 'react-native'
+import { StyleSheet, Text, TextInput, View } from 'react-native'
-storiesOf('component: TextInput', module)
- .add('tbd', () => (
-
- { console.log('TextInput.onBlur', e) }}
- onChange={(e) => { console.log('TextInput.onChange', e) }}
- onChangeText={(e) => { console.log('TextInput.onChangeText', e) }}
- onFocus={(e) => { console.log('TextInput.onFocus', e) }}
- onSelectionChange={(e) => { console.log('TextInput.onSelectionChange', e) }}
- />
-
-
-
-
-
-
-
-
-
- ))
+/**
+ * Copyright (c) 2013-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.
+ *
+ * The examples provided by Facebook are for non-commercial testing and
+ * evaluation purposes only.
+ *
+ * Facebook reserves all rights not expressly granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
+ * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * @flow
+ */
-const styles = StyleSheet.create({
- textInput: {
- borderWidth: 1
+class WithLabel extends React.Component {
+ render() {
+ return (
+
+
+ {this.props.label}
+
+ {this.props.children}
+
+ );
}
-})
+}
+
+class TextEventsExample extends React.Component {
+ state = {
+ curText: '',
+ prevText: '',
+ prev2Text: '',
+ prev3Text: '',
+ };
+
+ updateText = (text) => {
+ this.setState((state) => {
+ return {
+ curText: text,
+ prevText: state.curText,
+ prev2Text: state.prevText,
+ prev3Text: state.prev2Text,
+ };
+ });
+ };
+
+ render() {
+ return (
+
+ this.updateText('onFocus')}
+ onBlur={() => this.updateText('onBlur')}
+ onChange={(event) => this.updateText(
+ 'onChange text: ' + event.nativeEvent.text
+ )}
+ onEndEditing={(event) => this.updateText(
+ 'onEndEditing text: ' + event.nativeEvent.text
+ )}
+ onSubmitEditing={(event) => this.updateText(
+ 'onSubmitEditing text: ' + event.nativeEvent.text
+ )}
+ onSelectionChange={(event) => this.updateText(
+ 'onSelectionChange range: ' +
+ event.nativeEvent.selection.start + ',' +
+ event.nativeEvent.selection.end
+ )}
+ onKeyPress={(event) => {
+ this.updateText('onKeyPress key: ' + event.nativeEvent.key);
+ }}
+ style={styles.default}
+ />
+
+ {this.state.curText}{'\n'}
+ (prev: {this.state.prevText}){'\n'}
+ (prev2: {this.state.prev2Text}){'\n'}
+ (prev3: {this.state.prev3Text})
+
+
+ );
+ }
+}
+
+class AutoExpandingTextInput extends React.Component {
+ state: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ text: 'React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React. The focus of React Native is on developer efficiency across all the platforms you care about — learn once, write anywhere. Facebook uses React Native in multiple production apps and will continue investing in React Native.',
+ height: 0,
+ };
+ }
+ render() {
+ return (
+ {
+ this.setState({text});
+ }}
+ onContentSizeChange={(event) => {
+ this.setState({height: event.nativeEvent.contentSize.height});
+ }}
+ style={[styles.default, {height: Math.max(35, this.state.height)}]}
+ value={this.state.text}
+ />
+ );
+ }
+}
+
+class RewriteExample extends React.Component {
+ state: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {text: ''};
+ }
+ render() {
+ var limit = 20;
+ var remainder = limit - this.state.text.length;
+ var remainderColor = remainder > 5 ? 'blue' : 'red';
+ return (
+
+ {
+ text = text.replace(/ /g, '_');
+ this.setState({text});
+ }}
+ style={styles.default}
+ value={this.state.text}
+ />
+
+ {remainder}
+
+
+ );
+ }
+}
+
+class RewriteExampleInvalidCharacters extends React.Component {
+ state: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {text: ''};
+ }
+ render() {
+ return (
+
+ {
+ this.setState({text: text.replace(/\s/g, '')});
+ }}
+ style={styles.default}
+ value={this.state.text}
+ />
+
+ );
+ }
+}
+
+class TokenizedTextExample extends React.Component {
+ state: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {text: 'Hello #World'};
+ }
+ render() {
+
+ //define delimiter
+ let delimiter = /\s+/;
+
+ //split string
+ let _text = this.state.text;
+ let token, index, parts = [];
+ while (_text) {
+ delimiter.lastIndex = 0;
+ token = delimiter.exec(_text);
+ if (token === null) {
+ break;
+ }
+ index = token.index;
+ if (token[0].length === 0) {
+ index = 1;
+ }
+ parts.push(_text.substr(0, index));
+ parts.push(token[0]);
+ index = index + token[0].length;
+ _text = _text.slice(index);
+ }
+ parts.push(_text);
+
+ //highlight hashtags
+ parts = parts.map((text) => {
+ if (/^#/.test(text)) {
+ return {text};
+ } else {
+ return text;
+ }
+ });
+
+ return (
+
+ {
+ this.setState({text});
+ }}>
+ {parts}
+
+
+ );
+ }
+}
+
+class BlurOnSubmitExample extends React.Component {
+ focusNextField = (nextField) => {
+ this.refs[nextField].focus();
+ };
+
+ render() {
+ return (
+
+ this.focusNextField('2')}
+ />
+ this.focusNextField('3')}
+ />
+ this.focusNextField('4')}
+ />
+ this.focusNextField('5')}
+ />
+
+
+ );
+ }
+}
+
+type SelectionExampleState = {
+ selection: {
+ start: number;
+ end?: number;
+ };
+ value: string;
+};
+
+class SelectionExample extends React.Component {
+ state: SelectionExampleState;
+
+ _textInput: any;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ selection: {start: 0, end: 0},
+ value: props.value
+ };
+ }
+
+ onSelectionChange({nativeEvent: {selection}}) {
+ this.setState({selection});
+ }
+
+ getRandomPosition() {
+ var length = this.state.value.length;
+ return Math.round(Math.random() * length);
+ }
+
+ select(start, end) {
+ this._textInput.focus();
+ this.setState({selection: {start, end}});
+ }
+
+ selectRandom() {
+ var positions = [this.getRandomPosition(), this.getRandomPosition()].sort();
+ this.select(...positions);
+ }
+
+ placeAt(position) {
+ this.select(position, position);
+ }
+
+ placeAtRandom() {
+ this.placeAt(this.getRandomPosition());
+ }
+
+ render() {
+ var length = this.state.value.length;
+
+ return (
+
+ this.setState({value})}
+ onSelectionChange={this.onSelectionChange.bind(this)}
+ ref={textInput => (this._textInput = textInput)}
+ selection={this.state.selection}
+ style={this.props.style}
+ value={this.state.value}
+ />
+
+
+ selection = {JSON.stringify(this.state.selection)}
+
+
+ Place at Start (0, 0)
+
+
+ Place at End ({length}, {length})
+
+
+ Place at Random
+
+
+ Select All
+
+
+ Select Random
+
+
+
+ );
+ }
+}
+
+var styles = StyleSheet.create({
+ page: {
+ paddingBottom: 300,
+ },
+ default: {
+ height: 26,
+ borderWidth: 0.5,
+ borderColor: '#0f0f0f',
+ flex: 1,
+ fontSize: 13,
+ padding: 4,
+ },
+ multiline: {
+ borderWidth: 0.5,
+ borderColor: '#0f0f0f',
+ flex: 1,
+ fontSize: 13,
+ height: 50,
+ padding: 4,
+ marginBottom: 4,
+ },
+ multilineWithFontStyles: {
+ color: 'blue',
+ fontWeight: 'bold',
+ fontSize: 18,
+ fontFamily: 'Cochin',
+ height: 60,
+ },
+ multilineChild: {
+ width: 50,
+ height: 40,
+ position: 'absolute',
+ right: 5,
+ backgroundColor: 'red',
+ },
+ eventLabel: {
+ margin: 3,
+ fontSize: 12,
+ },
+ labelContainer: {
+ flexDirection: 'row',
+ marginVertical: 2,
+ flex: 1,
+ },
+ label: {
+ width: 115,
+ alignItems: 'flex-end',
+ marginRight: 10,
+ paddingTop: 2,
+ },
+ rewriteContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ remainder: {
+ textAlign: 'right',
+ width: 24,
+ },
+ hashtag: {
+ color: 'blue',
+ fontWeight: 'bold',
+ },
+});
+
+const examples = [
+ {
+ title: 'Auto-focus',
+ render: function() {
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ title: "Live Re-Write ( -> '_') + maxLength",
+ render: function() {
+ return ;
+ }
+ },
+ {
+ title: 'Live Re-Write (no spaces allowed)',
+ render: function() {
+ return ;
+ }
+ },
+ {
+ title: 'Auto-capitalize',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Auto-correct',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Keyboard types',
+ render: function() {
+ var keyboardTypes = [
+ 'default',
+ 'ascii-capable',
+ 'numbers-and-punctuation',
+ 'url',
+ 'number-pad',
+ 'phone-pad',
+ 'name-phone-pad',
+ 'email-address',
+ 'decimal-pad',
+ 'twitter',
+ 'web-search',
+ 'numeric',
+ ];
+ var examples = keyboardTypes.map((type) => {
+ return (
+
+
+
+ );
+ });
+ return {examples};
+ }
+ },
+ {
+ title: 'Keyboard appearance',
+ render: function() {
+ var keyboardAppearance = [
+ 'default',
+ 'light',
+ 'dark',
+ ];
+ var examples = keyboardAppearance.map((type) => {
+ return (
+
+
+
+ );
+ });
+ return {examples};
+ }
+ },
+ {
+ title: 'Return key types',
+ render: function() {
+ var returnKeyTypes = [
+ 'default',
+ 'go',
+ 'google',
+ 'join',
+ 'next',
+ 'route',
+ 'search',
+ 'send',
+ 'yahoo',
+ 'done',
+ 'emergency-call',
+ ];
+ var examples = returnKeyTypes.map((type) => {
+ return (
+
+
+
+ );
+ });
+ return {examples};
+ }
+ },
+ {
+ title: 'Enable return key automatically',
+ render: function() {
+ return (
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Secure text entry',
+ render: function() {
+ return (
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Event handling',
+ render: function(): React.Element { return ; },
+ },
+ {
+ title: 'Colored input text',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Colored highlight/cursor for text input',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Clear button mode',
+ render: function () {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Clear and select',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Blur on submit',
+ render: function(): React.Element { return ; },
+ },
+ {
+ title: 'Multiline blur on submit',
+ render: function() {
+ return (
+
+ alert(event.nativeEvent.text)}
+ />
+
+ );
+ }
+ },
+ {
+ title: 'Multiline',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Number of lines',
+ render: function() {
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Auto-expanding',
+ render: function() {
+ return (
+
+
+
+ );
+ }
+ },
+ {
+ title: 'Attributed text',
+ render: function() {
+ return ;
+ }
+ },
+ {
+ title: 'Text selection & cursor placement',
+ render: function() {
+ return (
+
+
+
+
+ );
+ }
+ },
+ {
+ title: 'TextInput maxLength',
+ render: function() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+ }
+];
+
+examples.forEach((example) => {
+ storiesOf('component: TextInput', module)
+ .add(example.title, () => example.render())
+});