Skip to content

Commit

Permalink
Merge pull request #49 from niuware/development
Browse files Browse the repository at this point in the history
Add custom component feature for toolbar controls
  • Loading branch information
niuware authored Oct 29, 2019
2 parents f5effbe + 084433b commit fe7c587
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 83 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# mui-rte
The Material-UI Rich Text Editor and Viewer

<img src="http://niuware.github.io/public/assets/mui-rte/editor-w-controls-1-2-0.png" width="600" />
<img src="http://niuware.github.io/public/assets/mui-rte/editor-1-9-0.png" width="600" />

**mui-rte** is a complete text editor and viewer for `material-ui` v3 and v4 based on `draft-js` and written in Typescript. It is ready to use out of the box yet supports user defined blocks, styles, callbacks, and decorators as well as toolbar and theme customization to enhance the editor to all needs.

Expand Down Expand Up @@ -50,7 +50,7 @@ Check the [examples](https://github.com/niuware/mui-rte/tree/master/examples) di

## Custom Controls

You can define your custom inline styles, blocks, atomic blocks and callback actions to the editor. Just select an icon from `@material-ui/icons` and define your rules.
You can define your custom inline styles, blocks, atomic blocks and callback actions to the editor. Just select an icon from `@material-ui/icons` or create your own `FunctionComponent` and define your rules.

### Adding a custom inline style

Expand Down Expand Up @@ -78,7 +78,7 @@ import InvertColorsIcon from '@material-ui/icons/InvertColors'

### Adding a custom block

This sample adds a block to the editor based on a `React Element` defined:
This sample adds a block to the editor based on a `React Element`:

```js
import MUIRichTextEditor from 'mui-rte'
Expand Down Expand Up @@ -111,7 +111,7 @@ const MyBlock = (props) => {

### Adding a custom atomic block

Check [this sample](https://github.com/niuware/mui-rte/blob/master/examples/atomic-custom-block/index.tsx) that shows how to create a control to add a `@material-ui` Card component to the editor.
Check [this sample](https://github.com/niuware/mui-rte/blob/master/examples/atomic-custom-block/index.tsx) that shows how to create a control to add a `@material-ui/core` Card component to the editor.

### Adding a custom callback control

Expand All @@ -128,7 +128,7 @@ import DoneIcon from '@material-ui/icons/Done'
name: "my-callback",
icon: <DoneIcon />,
type: "callback",
onClick: (editorState, name) => {
onClick: (editorState, name, anchor) => {
console.log(`Clicked ${name} control`)
}
}
Expand Down Expand Up @@ -246,6 +246,7 @@ Object.assign(defaultTheme, {
|id|`string`|optional|The HTML id attribute for the control|
|name|`string`|required|The name of the custom control. For rendering the control this name should be added to the `MUIRichTextEditor` `controls` property.|
|icon|`JSX.Element`|optional|The `@material-ui/icons` icon for the control. For "atomic" control type, the icon is not required. [Check this](https://material.io/resources/icons/?style=baseline) for available icons.|
|component|`React.FunctionComponent<TToolbarComponentProps>`|optional|The custom function component for the control. The icon has priority over the component, so if the icon is set the component will be ignored. For "atomic" control type, the component is not required.|
|type|`string`|required|Either "inline", "block", "atomic" or "callback"|
|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.|
Expand All @@ -254,6 +255,17 @@ Object.assign(defaultTheme, {

<br />

`TToolbarComponentProps`

|Property|Type|description|
|---|---|---|---|
|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.|

<br />

`TDecorator`

|Property|Type||description|
Expand Down
38 changes: 32 additions & 6 deletions examples/custom-controls/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import MUIRichTextEditor from '../../'
import React, { FunctionComponent } from 'react'
import { Chip, Avatar, Button } from '@material-ui/core'
import InvertColorsIcon from '@material-ui/icons/InvertColors'
import TableChartIcon from '@material-ui/icons/TableChart'
import DoneIcon from '@material-ui/icons/Done'
import MUIRichTextEditor from '../../'
import { TToolbarComponentProps } from '../../src/components/Toolbar'

const save = (data: string) => {
console.log(data)
Expand All @@ -20,6 +20,32 @@ const MyBlock = (props: any) => {
)
}

const MyCallbackComponent: FunctionComponent<TToolbarComponentProps> = (props) => {
return (
<Chip
id={props.id}
avatar={<Avatar>C</Avatar>}
onClick={props.onMouseDown}
label="Callback"
disabled={props.disabled}
/>
)
}

const MyBlockComponent: FunctionComponent<TToolbarComponentProps> = (props) => {
return (
<Button
id={props.id}
variant="contained"
onMouseDown={props.onMouseDown}
color={props.active ? "primary": "default"}
disabled={props.disabled}
>
My Block
</Button>
)
}

const CustomControls = () => {
return (
<MUIRichTextEditor
Expand All @@ -38,13 +64,13 @@ const CustomControls = () => {
},
{
name: "my-block",
icon: <TableChartIcon />,
component: MyBlockComponent,
type: "block",
blockWrapper: <MyBlock />
},
{
name: "my-callback",
icon: <DoneIcon />,
component: MyCallbackComponent,
type: "callback",
onClick: (_, name) => {
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.8.2",
"version": "1.9.0",
"description": "Material-UI Rich Text Editor and Viewer",
"keywords": [
"material-ui",
Expand Down
32 changes: 16 additions & 16 deletions src/MUIRichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
DraftHandleValue, DraftStyleMap, ContentBlock, DraftDecorator, getVisibleSelectionRect,
SelectionState
} from 'draft-js'
import EditorControls, { TEditorControl, TCustomControl } from './components/EditorControls'
import Toolbar, { TToolbarControl, TCustomControl } from './components/Toolbar'
import Link from './components/Link'
import Media from './components/Media'
import Blockquote from './components/Blockquote'
Expand Down Expand Up @@ -83,14 +83,14 @@ interface IMUIRichTextEditorProps extends WithStyles<typeof styles> {
readOnly?: boolean
inheritFontSize?: boolean
error?: boolean
controls?: Array<TEditorControl>
controls?: Array<TToolbarControl>
onSave?: (data: string) => void
onChange?: (state: EditorState) => void
customControls?: TCustomControl[],
decorators?: TDecorator[]
toolbar?: boolean
inlineToolbar?: boolean
inlineToolbarControls?: Array<TEditorControl>
inlineToolbarControls?: Array<TToolbarControl>
}

type IMUIRichTextEditorState = {
Expand Down Expand Up @@ -346,7 +346,7 @@ const MUIRichTextEditor: RefForwardingComponent<any, IMUIRichTextEditorProps> =
setEditorState(EditorState.redo(editorState))
}

const handlePrompt = (lastState: EditorState, type: "link" | "media", toolbarMode?: boolean) => {
const handlePrompt = (lastState: EditorState, type: "link" | "media", inlineMode?: boolean) => {
const selectionInfo = getSelectionInfo(lastState)
const contentState = lastState.getCurrentContent()
const linkKey = selectionInfo.linkKey
Expand All @@ -358,24 +358,24 @@ const MUIRichTextEditor: RefForwardingComponent<any, IMUIRichTextEditorProps> =
setState({
urlData: data,
urlKey: linkKey,
toolbarPosition: !toolbarMode ? undefined : state.toolbarPosition,
anchorUrlPopover: !toolbarMode ? document.getElementById(`mui-rte-${type}-control`)!
toolbarPosition: !inlineMode ? undefined : state.toolbarPosition,
anchorUrlPopover: !inlineMode ? document.getElementById(`mui-rte-${type}-control`)!
: document.getElementById(`mui-rte-${type}-control-toolbar`)!,
urlIsMedia: type === "media" ? true : undefined
})
}

const handlePromptForLink = (toolbarMode?: boolean) => {
const handlePromptForLink = (inlineMode?: boolean) => {
const selection = editorState.getSelection()

if (!selection.isCollapsed()) {
handlePrompt(editorState, "link", toolbarMode)
handlePrompt(editorState, "link", inlineMode)
}
}

const handlePromptForMedia = (toolbarMode?: boolean, newState?: EditorState) => {
const handlePromptForMedia = (inlineMode?: boolean, newState?: EditorState) => {
const lastState = newState || editorState
handlePrompt(lastState, "media", toolbarMode)
handlePrompt(lastState, "media", inlineMode)
}

const handleConfirmPrompt = (isMedia?: boolean, ...args: any) => {
Expand All @@ -386,7 +386,7 @@ const MUIRichTextEditor: RefForwardingComponent<any, IMUIRichTextEditorProps> =
confirmLink(...args)
}

const handleToolbarClick = (style: string, type: string, id: string, toolbarMode?: boolean) => {
const handleToolbarClick = (style: string, type: string, id: string, inlineMode?: boolean) => {
if (type === "inline") {
return toggleInlineStyle(style)
}
Expand All @@ -401,10 +401,10 @@ const MUIRichTextEditor: RefForwardingComponent<any, IMUIRichTextEditorProps> =
handleRedo()
break
case "LINK":
handlePromptForLink(toolbarMode)
handlePromptForLink(inlineMode)
break
case "IMAGE":
handlePromptForMedia(toolbarMode)
handlePromptForMedia(inlineMode)
break
case "clear":
handleClearFormat()
Expand Down Expand Up @@ -656,17 +656,17 @@ const MUIRichTextEditor: RefForwardingComponent<any, IMUIRichTextEditorProps> =
top: state.toolbarPosition.top,
left: state.toolbarPosition.left
}}>
<EditorControls
<Toolbar
editorState={editorState}
onClick={handleToolbarClick}
controls={inlineToolbarControls}
customControls={customControls}
toolbarMode={true}
inlineMode={true}
/>
</Paper>
: null}
{editable || renderToolbar ?
<EditorControls
<Toolbar
editorState={editorState}
onClick={handleToolbarClick}
controls={controls}
Expand Down
39 changes: 0 additions & 39 deletions src/components/EditorButton.tsx

This file was deleted.

Loading

0 comments on commit fe7c587

Please sign in to comment.