react-native-web icon indicating copy to clipboard operation
react-native-web copied to clipboard

TextInput: multiline rich content support

Open necolas opened this issue 7 years ago • 11 comments

Multiline TextInput in React Native supports components as children. Along with #795 and #793, this may require switching to contentEditable for the multiline implementation, if not the single-line input.

necolas avatar Jul 07 '18 02:07 necolas

Slate doesn't play so nice with mobile unfortunately. Same with DraftJS.

The easiest solution is just wrap each one in it's own native renderer function that spits out the following:

SubComponent

<Text>
     <Text style={{ fontWeight: 'bold' }}>Starts </Text>bold.
</Text>

Web

<p contentEditable={true} onKeyDown={(e) => this.onChange(e)}>
    <SubComponent />
</p>

Mobile

<TextInput 
    multiline={true} 
    onChange={(e) => this.onChange(e)}
>
    <SubComponent />
</TextInput>

PS Really awesome library I'm using this to create cross platform apps (Web, Electron, React-Native) and it's going epic. Wish I could donate!

ollyde avatar Dec 06 '18 18:12 ollyde

@voidstarfire Thanks! How does React manage when a user edits the contentEditable content that is produced by components React renders? I heard that was one of the difficulties with contentEditable but haven't made time to experiment myself yet. Any more feedback you can include would be really helpful

necolas avatar Dec 06 '18 20:12 necolas

I'm playing with that just now.

It seems to work really well so far. The <Text/> components just wrap around the text. As long as you stick with <Text> only components. No views.

Seems we have to create some sort of generator to filter out empty text components and fill in styled ones. Should work well with React-native-web.

I will get back probably mid next week with my results :-)

Here's some examples if you're interested. @necolas

I'm actually creating a cross-platform native Markdown editor (Not just viewer) from scratch in React.

Sub component.

export default class Editor extends React.Component<Props, State> {
    render () {
        return (
            <Text>
                <Text>{'This is a sentence' + '\n'}</Text>
                <Text style={{fontWeight: "bold"}}> with</Text>
                <Text>one word in bold</Text>
            </Text>
        )
    }
}

Mobile

export default class MobileRender extends React.Component<Props, State> {
    render() {
        return (
            <TextInput 
                 multiline={true} 
                 style={{ flex: 1, alignSelf: 'stretch' }}
                 onChange={(e) => this.onChange(e)}
             >
                 <Editor
                     markdown={testMarkdown}
                 />
            </TextInput>
        )
    }
    onChange = (event: NativeSyntheticEvent<any>) => {
        const {name, type, value} = event.nativeEvent;
        debugger
    }
}

Desktop / Web

export default class WebRender extends React.Component<Props, State> {
    constructor(props: Props) {
        super(props)
    }
    render() {
        return (
            <p contentEditable={true} onKeyDown={(e) => this.onChange(e)}>
                <Editor
                    markdown={testMarkdown}
                />
            </p>
        )
    }

    onChange = (event: React.SyntheticEvent<KeyboardEvent>) => {
        
    }
}

ollyde avatar Dec 06 '18 21:12 ollyde

Seems we have to create some sort of generator to filter out empty text components and fill in styled ones.

What does that mean?

necolas avatar Dec 06 '18 21:12 necolas

@necolas My bad I was speaking from a Markdown perspective mostly.

Speaking from a <TextInput> only perspective it seems to work pretty well. The react-native-web <Text> components stack fine and inside contentEditable they seem to work with styles just fine, even when backspacing until you have no content. Although I imagine there will be a lot of empty <Text>{wasContent}</Text> around; hence some sort of filter.

ollyde avatar Dec 06 '18 21:12 ollyde

@ollydixon How is the development going?

shakeabi avatar Jul 11 '19 07:07 shakeabi

@shakeabi I'm using a library called Quill, worked great for mobile and web :-)

ollyde avatar Jul 11 '19 09:07 ollyde

@ollydixon How are you using quilljs in native cuz there's no native supported quill yet, right? (If webview, then though it may work for various devices, it's still not purely native and can have unexpected behaviour)

shakeabi avatar Jul 11 '19 09:07 shakeabi

@shakeabi there was no native solution that included an editor.

ollyde avatar Jul 11 '19 09:07 ollyde

@ollydixon It's not that difficult to make a simple native rich text editor. My (partial) solution includes using nested <Text> inside <TextInput>. However, react-native-web doesn't support this as it renders either textarea or input tags (neither of them supports children tags). #1380: I've discussed the same in this issue. A probable solution would be to replace the TextInput version (textarea or input) react-native-web to content-editable divs.

shakeabi avatar Jul 11 '19 09:07 shakeabi

@shakeabi yes I discovered this as well. I no longer do React Native anymore though. Flutter is much better :-)

ollyde avatar Jul 11 '19 09:07 ollyde