TextInput: multiline rich content support
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.
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!
@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
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>) => {
}
}
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 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.
@ollydixon How is the development going?
@shakeabi I'm using a library called Quill, worked great for mobile and web :-)
@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 there was no native solution that included an editor.
@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 yes I discovered this as well. I no longer do React Native anymore though. Flutter is much better :-)