diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/example/demo1/.babelrc b/example/demo1/.babelrc new file mode 100644 index 0000000..2bcd546 --- /dev/null +++ b/example/demo1/.babelrc @@ -0,0 +1,8 @@ +{ + "presets": ["babel-preset-expo"], + "env": { + "development": { + "plugins": ["transform-react-jsx-source"] + } + } +} diff --git a/example/demo1/.gitignore b/example/demo1/.gitignore new file mode 100644 index 0000000..9f9e17e --- /dev/null +++ b/example/demo1/.gitignore @@ -0,0 +1,3 @@ +node_modules/**/* +.expo/* +npm-debug.* diff --git a/example/demo1/.watchmanconfig b/example/demo1/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/example/demo1/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/example/demo1/App.js b/example/demo1/App.js new file mode 100644 index 0000000..4435fe7 --- /dev/null +++ b/example/demo1/App.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react'; + +import { View, TextInput, StyleSheet, KeyboardAvoidingView } from 'react-native'; +import { Constants } from 'expo'; + +import Form from './form'; + +export default class App extends Component { + state = { + inputValue1: 'You can change me!', + inputValue2: 'You can change me!', + inputValue3: 'You can change me!', + }; + + _handleTextChange = i => inputValue => { + const x = {}; + x[`inputValue${i}`] = inputValue; + this.setState(x); + }; + + render() { + return ( + +
+ + + + + { console.log('poooopie'); } } + /> + +
+ ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingTop: Constants.statusBarHeight, + backgroundColor: 'red', + }, + form: { + flex: 1, + alignItems: 'center', + justifyContent: 'space-between' + } +}); \ No newline at end of file diff --git a/example/demo1/app.json b/example/demo1/app.json new file mode 100644 index 0000000..4ab6547 --- /dev/null +++ b/example/demo1/app.json @@ -0,0 +1,21 @@ +{ + "expo": { + "name": "demo1", + "description": "This project is really great.", + "slug": "demo1", + "privacy": "public", + "sdkVersion": "25.0.0", + "platforms": ["ios", "android"], + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/icon.png", + "splash": { + "image": "./assets/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "ios": { + "supportsTablet": true + } + } +} diff --git a/example/demo1/assets/icon.png b/example/demo1/assets/icon.png new file mode 100644 index 0000000..3f5bbc0 Binary files /dev/null and b/example/demo1/assets/icon.png differ diff --git a/example/demo1/assets/splash.png b/example/demo1/assets/splash.png new file mode 100644 index 0000000..4f9ade6 Binary files /dev/null and b/example/demo1/assets/splash.png differ diff --git a/example/demo1/form.js b/example/demo1/form.js new file mode 100644 index 0000000..25bc30d --- /dev/null +++ b/example/demo1/form.js @@ -0,0 +1,94 @@ +import React from 'react'; +import { View } from 'react-native'; + +export default class Form extends React.Component { + constructor(props) { + super(props); + this.inputs = []; + } + + checkIfInput = element => { + const elemName = element.type.name || element.type.displayName; + const inputElements = this.props.inputElements || + [ + { + names: ['TextInput'], // names: 'TextInput' or name: 'TextInput' is also okay + submitFunctionNames: ['onSubmitEditing'], // submitFunctionNames: 'onSubmitEditing' or submitFunctionName: 'onSubmitEditing' is also okay + focus: 'focus', + }, + ]; + for (let input of inputElements) { + let names = []; + if (input.names) { + names = names.concat(input.names); + } + if (input.name) { + names.push(input.name); + } + console.log('z', names, elemName); + if (names.includes(elemName)) { + return input; + } + } + return false; + }; + + cloneElement = (element, index, inputInfo) => { + console.log('cloning'); + let functionNames = []; + if (inputInfo.submitFunctionNames) { + functionNames = functionNames.concat(inputInfo.submitFunctionNames); + } + if (inputInfo.submitFunctionName) { + functionNames = functionNames.concat(inputInfo.submitFunctionName); + } + const handleEnterBuilder = (oldEnter) => (...arg) => + this.inputs[index + 1] + ? this.inputs[index + 1][inputInfo['focus']]() + : oldEnter(...arg); + const submitFunctions = {}; + for (let func of functionNames) { + let oldFunc = element.props[func]; + submitFunctions[func] = handleEnterBuilder(oldFunc); + } + const oldRef = element.props.ref; + const handleRef = (ref, ...rest) => { + this.inputs[index] = ref; + if (oldRef) { + oldRef(ref, ...rest); + } + }; + return React.cloneElement(element, { + ...submitFunctions, + ref: handleRef, + }); + }; + + renderChildren(children, recursiveIndex = 0) { + console.log('renderChildren', children.length); + return React.Children.map(children, (child, index) => { + //return children.map((child, index) => { + if (child.props.children) + return React.cloneElement(child, { + ...child.props, + children: this.renderChildren(child.props.children, index) + }); + const childType = this.checkIfInput(child); + console.log(childType); + if (childType === false) return child; + console.log('action'); + const realIndex = index + recursiveIndex; + return this.cloneElement(child, realIndex, childType); + }); + } + + render() { + let { children, ...props } = this.props; + return ( + + {this.renderChildren(children)} + + ); + } +} + diff --git a/example/demo1/package.json b/example/demo1/package.json new file mode 100644 index 0000000..cc2c527 --- /dev/null +++ b/example/demo1/package.json @@ -0,0 +1,9 @@ +{ + "main": "node_modules/expo/AppEntry.js", + "private": true, + "dependencies": { + "expo": "^25.0.0", + "react": "16.2.0", + "react-native": "https://github.com/expo/react-native/archive/sdk-25.0.0.tar.gz" + } +} diff --git a/form.js b/form.js index 271d713..221b7be 100644 --- a/form.js +++ b/form.js @@ -2,26 +2,83 @@ import React from 'react'; import { View } from 'react-native'; export default class Form extends React.Component { - constructor() { - super(); + constructor(props) { + super(props); this.inputs = []; } + checkIfInput = element => { + const elemName = element.type.name || element.type.displayName; + const inputElements = this.props.inputElements || + [ + { + names: ['TextInput'], // names: 'TextInput' or name: 'TextInput' is also okay + submitFunctionNames: ['onSubmitEditing'], // submitFunctionNames: 'onSubmitEditing' or submitFunctionName: 'onSubmitEditing' is also okay + focus: 'focus', + }, + ]; + for (let input of inputElements) { + let names = []; + if (input.names) { + names = names.concat(input.names); + } + if (input.name) { + names.push(input.name); + } + console.log('z', names, elemName); + if (names.includes(elemName)) { + return input; + } + } + return false; + }; + + cloneElement = (element, index, inputInfo) => { + console.log('cloning'); + let functionNames = []; + if (inputInfo.submitFunctionNames) { + functionNames = functionNames.concat(inputInfo.submitFunctionNames); + } + if (inputInfo.submitFunctionName) { + functionNames = functionNames.concat(inputInfo.submitFunctionName); + } + const handleEnterBuilder = (oldEnter) => (...arg) => + this.inputs[index + 1] + ? this.inputs[index + 1][inputInfo['focus']]() + : oldEnter(...arg); + const submitFunctions = {}; + for (let func of functionNames) { + let oldFunc = element.props[func]; + submitFunctions[func] = handleEnterBuilder(oldFunc); + } + const oldRef = element.props.ref; + const handleRef = (ref, ...rest) => { + this.inputs[index] = ref; + if (oldRef) { + oldRef(ref, ...rest); + } + }; + return React.cloneElement(element, { + ...submitFunctions, + ref: handleRef, + }); + }; + renderChildren(children, recursiveIndex = 0) { + console.log('renderChildren', children.length); return React.Children.map(children, (child, index) => { + //return children.map((child, index) => { if (child.props.children) return React.cloneElement(child, { - ...child.props, + ...child.props, children: this.renderChildren(child.props.children, index) }); - if (child.type.name !== 'TextInput') return child; - - let realIndex = index + recursiveIndex - return React.cloneElement(child, { - onEnter: () => - this.inputs[realIndex + 1] ? this.inputs[realIndex + 1].focus() : null, - inputRef: ref => (this.inputs[realIndex] = ref), - }); + const childType = this.checkIfInput(child); + console.log(childType); + if (childType === false) return child; + console.log('action'); + const realIndex = index + recursiveIndex; + return this.cloneElement(child, realIndex, childType); }); } @@ -34,3 +91,4 @@ export default class Form extends React.Component { ); } } + diff --git a/index.js b/index.js index e4bd23d..e990a4f 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,2 @@ export { default as Form } from './form'; -export { default as TextInput } from './text-input'; +//export { default as TextInput } from './text-input'; diff --git a/package.json b/package.json index 9020ddf..daa939e 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,9 @@ "bugs": { "url": "https://github.com/zackify/react-native-autofocus/issues" }, - "homepage": "https://github.com/zackify/react-native-autofocus#readme" + "homepage": "https://github.com/zackify/react-native-autofocus#readme", + "dependencies": { + "react": "^16.2.0", + "react-native": "^0.54.0" + } } diff --git a/text-input.js b/text-input.js index 0b60e06..7a4ea0c 100644 --- a/text-input.js +++ b/text-input.js @@ -1,6 +1,25 @@ +/* import React from 'react'; import { TextInput as Input } from 'react-native'; +export const InputBuilder = (Element, submitFunctionNames) => ({ onEnter, inputRef, ...props }) => { + const enterProp = {}; + const functionNamesArray = [].concat(submitFunctionNames); + for (let functionName of functionNamesArray) { + enterProp[functionName] = onEnter; + } + return ( + inputRef(ref) } + { ...enterProp, ...props } + /> + ); +} + + +const TextInput = InputBuilder(Input); + + const TextInput = ({ onSubmitEditing, onEnter, inputRef, ...props }) => ( inputRef(ref)} @@ -13,3 +32,4 @@ const TextInput = ({ onSubmitEditing, onEnter, inputRef, ...props }) => ( ); export default TextInput; +*/