Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an example of Material UI TextField integration #131

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions examples/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ResetValue from './reset-value'
import AtomicCustomBlock from './atomic-custom-block'
import KeyBindings from './key-bindings'
import MaxLength from './max-length'
import MUITextFieldIntegration from './mui-textfield-integration'
import Autocomplete from './autocomplete'
import AutocompleteAtomic from './autocomplete-atomic'
import AsyncImageUpload from './async-image-upload'
Expand Down Expand Up @@ -46,6 +47,7 @@ const App = () => {
<button onClick={() => setSample(<ResetValue />)}>Reset value</button>
<button onClick={() => setSample(<KeyBindings />)}>Key Bindings</button>
<button onClick={() => setSample(<MaxLength />)}>Max length</button>
<button onClick={() => setSample(<MUITextFieldIntegration />)}>Material UI TextField Integration</button>
<button onClick={() => setSample(<Autocomplete />)}>Autocomplete</button>
<button onClick={() => setSample(<AutocompleteAtomic />)}>Autocomplete Atomic</button>
<div style={{
Expand Down
91 changes: 91 additions & 0 deletions examples/mui-textfield-integration/RichTextField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { Ref, useRef, useImperativeHandle, useCallback, useEffect, useState } from 'react'
import TextField, { TextFieldProps } from '@material-ui/core/TextField'
import { InputBaseComponentProps } from '@material-ui/core/InputBase'
import { EditorState } from 'draft-js'
import MUIRichTextEditor from '../../'
import { TMUIRichTextEditorRef } from '../../src/MUIRichTextEditor'
import { TToolbarControl } from '../../src/components/Toolbar'

export interface RichTextInputProps extends Omit<InputBaseComponentProps, 'value'> {
inputRef?: Ref<unknown>
doFocus?: boolean
onStateChange?: (state: EditorState) => void
controls?: Array<TToolbarControl>
}

export const RichTextInput = ({
inputRef,
doFocus,
onStateChange,
controls,
...richTextProps
}: RichTextInputProps) => {
const acquireFocus = doFocus ?? false

// Setup ref for the rich text editor
const richTextRef = useRef<TMUIRichTextEditorRef>(null)

// Attempts to focus the rich text editor reference
const focusRichText = useCallback(() => richTextRef.current?.focus(), [richTextRef])

// Pass on the focus event of the input ref to the rich text ref
useImperativeHandle(inputRef, () => ({ focus: () => focusRichText }))

// If the `acquireFocus` is changed and its value is `true`, focus the editor
useEffect(() => {
if (acquireFocus) {
focusRichText()
}
}, [acquireFocus, focusRichText])

return (
<MUIRichTextEditor
{...richTextProps}
ref={richTextRef}
onChange={onStateChange}
controls={controls}
/>
)
}

export interface RichTextFieldProps extends Omit<TextFieldProps, 'value' | 'onChange'> {
onChange?: (state: EditorState) => void
}

const RichTextField = ({
id,
placeholder,
defaultValue,
onChange,
InputLabelProps,
variant,
...textFieldProps
}: RichTextFieldProps) => {
// Manually handle the TextField's focused state based on the editor's focused state
const [isFocused, setIsFocused] = useState(false)

const inputProps: RichTextInputProps = {
id: id,
steurt marked this conversation as resolved.
Show resolved Hide resolved
defaultValue: defaultValue,
label: placeholder,
inlineToolbar: true,
onStateChange: onChange,
doFocus: isFocused,
onFocus: () => setIsFocused(true),
onBlur: () => setIsFocused(false),
}

return (
<TextField
{...textFieldProps}
id={id}
variant={variant} // Required to compile due to TextFieldProps variant incompatibility
focused={isFocused}
onClick={() => setIsFocused(true)}
InputLabelProps={{ ...InputLabelProps, shrink: true }}
InputProps={{ inputComponent: RichTextInput, inputProps: inputProps }}
/>
)
}

export default RichTextField
32 changes: 32 additions & 0 deletions examples/mui-textfield-integration/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react'
import { makeStyles } from '@material-ui/core/styles'
import RichTextField from './RichTextField'
import { EditorState } from 'draft-js'

const useStyles = makeStyles({
richTextField: {
'& #mui-rte-root': {
minHeight: 192,
padding: '0 16px',
},
},
})

const change = (state: EditorState) => {
console.log(state)
}

const MUITextFieldIntegration = () => {
const classes = useStyles()
return (
<RichTextField
variant="outlined"
label="TextField label"
helperText="Some TextField helper text"
placeholder="Type something here..."
onChange={change}
className={classes.richTextField} />
)
}

export default MUITextFieldIntegration