Skip to content

Commit

Permalink
Add handleDroppedFiles property (#122)
Browse files Browse the repository at this point in the history
* Export props types

* Reorder properties

* Add handleDroppedFiles property to draftEditorProps

* Update async image upload example

* Update custom controls example

* Update README

* Update package version

* Update README
  • Loading branch information
niuware authored May 25, 2020
1 parent 703945e commit ab0c188
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 21 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const MyBlock = (props) => {

<img src="https://raw.githubusercontent.com/niuware/niuware.github.io/master/public/assets/mui-rte/async-upload-demo.gif" width="600" />

It is possible to insert custom blocks based on asynchronous behavior using the `insertAtomicBlockAsync` API. The above example shows an [example](https://github.com/niuware/mui-rte/blob/master/examples/async-image-upload/index.tsx) on how to upload an image and use the `MUIRichTextEditor` default image control for further edition.
It is possible to insert custom blocks based on asynchronous behavior using the `insertAtomicBlockAsync` API. The above example shows an [example](https://github.com/niuware/mui-rte/blob/master/examples/async-image-upload/index.tsx) on how to upload an image and use the `MUIRichTextEditor` default image control for further edition. You can use this behavior to upload a file when dropping it inside the editor and render it as an image entity after upload.

Check this [other sample](https://github.com/niuware/mui-rte/blob/master/examples/async-atomic-custom-block/index.tsx) that shows how to add a `@material-ui/core` Card with asynchronous downloaded content.

Expand Down Expand Up @@ -279,7 +279,7 @@ Object.assign(defaultTheme, {

## API

`<MUIRichTextEditor />`
`<MUIRichTextEditor /> (TMUIRichTextEditorProps)`

|Property|Type||description|
|---|---|---|---|
Expand All @@ -291,8 +291,6 @@ Object.assign(defaultTheme, {
|defaultValue|`string`|optional|Default content to load. Should be a stringified `Draft.Model.Encoding.RawDraftContentState` object.|
|inheritFontSize|`boolean`|optional|Inherit font size from parent. Useful for read only mode.|
|error|`boolean`|optional|Renders the editor with an error style.|
|onSave|`(data:string) => void`|optional|Function triggered when the save button is pressed. The `data` is a stringified `Draft.Model.Encoding.RawDraftContentState` object.|
|onChange|`(state: EditorState) => void`|optional|Function triggered on any change in the editor (key input, delete, etc.). The `state` is a `Draft.Model.ImmutableData.EditorState` object.
|controls|`string[]`|optional|List of controls to display in the main toolbar. If not provided, all controls will be rendered. Current available values are: "title", "bold", "italic", "underline", "strikethrough", "highlight", "undo", "redo", "link", "media", "numberList", "bulletList", "quote", "code", "clear", "save".|
|customControls|`TCustomControl[]`|optional|Defines an array of user custom inline styles, blocks and callbacks. See more information in 'Custom Controls' below.|
|decorators|`TDecorator[]`|optional|Defines an array of user custom decorators. See more information in 'Custom Decorators'.|
Expand All @@ -304,7 +302,8 @@ Object.assign(defaultTheme, {
|draftEditorProps|`TDraftEditorProps`|optional|Defines an object containing specific `draft-js` `Editor` properties.|
|maxLength|`number`|optional|Sets the maximum characters count that can be input into the editor.|
|autocomplete|`TAutocomplete`|optional|Sets autocomplete strategies to present suggestion lists as the user types into the editor.|

|onSave|`(data:string) => void`|optional|Function triggered when the save button is pressed. The `data` is a stringified `Draft.Model.Encoding.RawDraftContentState` object.|
|onChange|`(state: EditorState) => void`|optional|Function triggered on any change in the editor (key input, delete, etc.). The `state` is a `Draft.Model.ImmutableData.EditorState` object.|

<br />

Expand All @@ -320,7 +319,7 @@ Object.assign(defaultTheme, {
|inlineStyle|`string`|optional|The `React.CSSProperties` object for styling the text when using a custom inline style.|
|blockWrapper|`React.ReactElement`|optional|The custom React component used for rendering a custom block.|
|atomicComponent|`React.FunctionComponent`|optional|The custom React FunctionComponent used for rendering a custom atomic block.|
|onClick|`(editorState: EditorState, name: string, anchor: HTMLElement \| null) => EditorState \| void`|optional|The callback function triggered when the custom control is clicked. The received arguments include the current `EditorState` object, the name of the clicked control and the `HTMLElement` from which the click was raised. If a new `EditorState` object is returned it will be replace the current one in the editor (useful to explicitly modify the `EditorState`).|
|onClick|`(editorState: EditorState, name: string, anchor: HTMLElement | null) => EditorState | void`|optional|The callback function triggered when the custom control is clicked. The received arguments include the current `EditorState` object, the name of the clicked control and the `HTMLElement` from which the click was raised. If a new `EditorState` object is returned it will be replace the current one in the editor (useful to explicitly modify the `EditorState`).|

<br />

Expand All @@ -331,7 +330,7 @@ Object.assign(defaultTheme, {
|id|string|The id for the component.|
|onMouseDown|(e: React.MouseEvent) => void|The `mousedown` handler.|
|active|boolean|Defines if the block or inline type is active for the current editor selection.|
|disabled|boolean|Sets if the toolbar is disabled.|
|disabled|boolean|Sets if the toolbar is disabled.|

<br />

Expand All @@ -350,7 +349,7 @@ Object.assign(defaultTheme, {
|---|---|---|---|
|key|`number`|required|The code of the key to bind.|
|name|`string`|required|The name of the command.|
|callback|`(state: EditorState) => EditorState`|required|The callback function to execute when the key binding is matched. It should return the `EditorState` to set.|
|callback|`(state: EditorState) => EditorState`|required|The callback function to execute when the key binding is matched. It should return the `EditorState` to set.|

<br />

Expand All @@ -359,7 +358,8 @@ Object.assign(defaultTheme, {
|Property|Type||description|
|---|---|---|---|
|spellCheck|`boolean`|optional|Use browser spelling check.|
|stripPastedStyles|`boolean`|optional|Remove styles when pasting text into the editor.|
|stripPastedStyles|`boolean`|optional|Remove styles when pasting text into the editor.|
|handleDroppedFiles|`(selectionState: SelectionState, files: Blob[]) => DraftHandleValue`|optional|Handle files that have been dropped into the editor.|

<br />

Expand Down
25 changes: 19 additions & 6 deletions examples/async-image-upload/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ const cardPopverStyles = makeStyles({

const uploadImageToServer = (file: File) => {
return new Promise(resolve => {
console.log(`Uploading image ${file.name}...`)
console.log(`Uploading image ${file.name} ...`)
setTimeout(() => {
console.log("Uploaded successful")
resolve("https://return_uploaded_image_url")
console.log("Upload successful")
resolve(`https://return_uploaded_image_url/${file.name}`)
}, 2000)
})
}
Expand Down Expand Up @@ -158,22 +158,26 @@ const UploadImagePopover: FunctionComponent<IUploadImagePopoverProps> = (props)
}

const AsyncImageUpload: FunctionComponent = () => {

const ref = useRef<TMUIRichTextEditorRef>(null)
const [anchor, setAnchor] = useState<HTMLElement | null>(null)

const handleFileUpload = (file: File) => {
ref.current?.insertAtomicBlockAsync("IMAGE", uploadImage(file), "Uploading now...")
}

return (
<>
<UploadImagePopover
anchor={anchor}
onSubmit={(data, insert) => {
if (insert && data.file) {
ref.current?.insertAtomicBlockAsync("IMAGE", uploadImage(data.file), "Uploading now...")
handleFileUpload(data.file)
}
setAnchor(null)
}}
/>
<MUIRichTextEditor
label="Press the last icon in the toolbar to simulate uploading an image...."
label="Drop a file inside the editor or press the last icon in the toolbar to simulate uploading an image...."
ref={ref}
controls={["title", "bold", "underline", "media", "upload-image"]}
customControls={[
Expand All @@ -186,6 +190,15 @@ const AsyncImageUpload: FunctionComponent = () => {
}
}
]}
draftEditorProps={{
handleDroppedFiles: (_selectionState, files) => {
if (files.length && (files[0] as File).name !== undefined) {
handleFileUpload(files[0] as File)
return "handled"
}
return "not-handled"
}
}}
/>
</>
)
Expand Down
2 changes: 1 addition & 1 deletion examples/custom-controls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const CustomControls = () => {
name: "my-callback",
component: MyCallbackComponent,
type: "callback",
onClick: (_, name) => {
onClick: (_editorState, name, _anchor) => {
console.log(`Clicked ${name} control`)
}
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mui-rte",
"version": "1.18.0",
"version": "1.19.0",
"description": "Material-UI Rich Text Editor and Viewer",
"keywords": [
"material-ui",
Expand Down
11 changes: 7 additions & 4 deletions src/MUIRichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@ export type TMUIRichTextEditorRef = {
insertAtomicBlockAsync: (name: string, promise: Promise<TAsyncAtomicBlockResponse>, placeholder?: string) => void
}

type TDraftEditorProps = {
export type TDraftEditorProps = {
spellCheck?: boolean
stripPastedStyles?: boolean
handleDroppedFiles?: (selectionState: SelectionState, files: Blob[]) => DraftHandleValue
}

type TKeyCommand = {
export type TKeyCommand = {
key: number
name: string
callback: (state: EditorState) => EditorState
}

interface IMUIRichTextEditorProps extends WithStyles<typeof styles> {
export type TMUIRichTextEditorProps = {
id?: string
/**
* @deprecated Use `defaultValue` instead.
Expand All @@ -83,11 +84,13 @@ interface IMUIRichTextEditorProps extends WithStyles<typeof styles> {
draftEditorProps?: TDraftEditorProps
keyCommands?: TKeyCommand[]
maxLength?: number
autocomplete?: TAutocomplete
onSave?: (data: string) => void
onChange?: (state: EditorState) => void
autocomplete?: TAutocomplete
}

interface IMUIRichTextEditorProps extends TMUIRichTextEditorProps, WithStyles<typeof styles> {}

type TMUIRichTextEditorState = {
anchorUrlPopover?: HTMLElement
urlKey?: string
Expand Down

0 comments on commit ab0c188

Please sign in to comment.