Skip to content

Commit

Permalink
Merge pull request #270 from niuware/add-mui-5-compatability
Browse files Browse the repository at this point in the history
Add MUI (Material-UI v5) compatibility
  • Loading branch information
niuware authored Sep 22, 2021
2 parents b7f70ed + 5225d08 commit c02652c
Show file tree
Hide file tree
Showing 31 changed files with 2,393 additions and 7,018 deletions.
14 changes: 0 additions & 14 deletions .github/workflows/main.yml

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode
node_modules
dist
dist
.DS_Store
50 changes: 31 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
# mui-rte
![Tests](https://github.com/niuware/mui-rte/workflows/Tests/badge.svg)
# mui-rte

The Material-UI Rich Text Editor and Viewer

<img src="https://raw.githubusercontent.com/niuware/niuware.github.io/master/public/assets/mui-rte/editor-1-9-0.png" width="600" />

**mui-rte** is a complete text editor and viewer for `material-ui` based on `draft-js` and written in Typescript. It is ready to use out of the box yet supports user defined blocks, styles, autocomplete strategies, async/sync custom atomic blocks, callbacks, and decorators as well as toolbar and theme customization to enhance the editor to all needs.
**mui-rte** is a complete text editor and viewer for the MUI library (formerly Material-UI) based on `draft-js` and written in Typescript. It is ready to use out of the box yet supports user defined blocks, styles, autocomplete strategies, async/sync custom atomic blocks, callbacks, and decorators as well as toolbar and theme customization to enhance the editor to all needs.

## Installation

```
npm install mui-rte --save
```

Install the peer dependencies: `@material-ui/core`, `@material-ui/icons`, `react` and `react-dom`.
Install the peer dependencies: `@mui/material`, `@mui/icons-material`, `@mui/styles`, `react` and `react-dom`. Also you will need to install the peer dependencies for MUI: `@emotion/react` and `@emotion/styled`.

## Demo

Expand All @@ -22,10 +21,17 @@ Install the peer dependencies: `@material-ui/core`, `@material-ui/icons`, `react
## Usage

```js
import { createTheme, ThemeProvider } from '@mui/material/styles'
import MUIRichTextEditor from 'mui-rte'

const myTheme = createTheme({
// Set up your custom MUI theme here
})

ReactDOM.render(
<MUIRichTextEditor label="Start typing..." />,
<ThemeProvider theme={myTheme}>
<MUIRichTextEditor label="Start typing..." />
</ThemeProvider>,
document.getElementById("root")
)
```
Expand All @@ -38,29 +44,35 @@ import MUIRichTextEditor from 'mui-rte'
const data = getContentStateAsStringFromSomewhere()

ReactDOM.render(
<MUIRichTextEditor
defaultValue={data}
label="Start typing..."
/>,
<ThemeProvider theme={myTheme}>
<MUIRichTextEditor
defaultValue={data}
label="Start typing..."
/>
</ThemeProvider>,
document.getElementById("root")
)
```

## Material-UI v4 compatibility

`mui-rte` version 2.x is compatible with MUI (v5) only. You can still use version [1.x](https://github.com/niuware/mui-rte/releases/tag/1.29.0) for Material-UI v4. Current code using `mui-rte` version 1.x should be compatible with version 2.x, the only breaking change is that it requires to be wrapped on a `ThemeProvider` as shown in the examples.

## Examples

Check the [examples](https://github.com/niuware/mui-rte/tree/master/examples) directory for more.

## 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` or create your own `FunctionComponent` 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 `@mui/icons-material` or create your own `FunctionComponent` and define your rules.

### Adding a custom inline style

This sample adds a control to change the background color and font color of the typed or selected text:

```js
import MUIRichTextEditor from 'mui-rte'
import InvertColorsIcon from '@material-ui/icons/InvertColors'
import InvertColorsIcon from '@mui/icons-material/InvertColors'

<MUIRichTextEditor
controls={["my-style"]}
Expand All @@ -84,7 +96,7 @@ This sample adds a block to the editor based on a `React Element`:

```js
import MUIRichTextEditor from 'mui-rte'
import TableChartIcon from '@material-ui/icons/TableChart'
import TableChartIcon from '@mui/icons-material/TableChart'

const MyBlock = (props) => {
return (
Expand Down Expand Up @@ -117,19 +129,19 @@ const MyBlock = (props) => {

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.
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 `@mui/material` Card with asynchronous downloaded content.

### Adding a custom atomic block (Sync)

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.
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 `@mui/material` Card component to the editor.

### Adding a custom callback control

This sample adds a control that will trigger a custom callback function to clear the editor state:

```js
import MUIRichTextEditor from 'mui-rte'
import DoneIcon from '@material-ui/icons/Done'
import DoneIcon from '@mui/icons-material/Done'
import { EditorState } from 'draft-js'

<MUIRichTextEditor
Expand Down Expand Up @@ -251,7 +263,7 @@ import MUIRichTextEditor from 'mui-rte'
You can style the editor using the `Material-UI` theming feature. First create a theme with `createMuiTheme` and override classes such as `root`, `container`, `editor`, and `editorContainer`. Check the examples directory for more.

```js
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles'
import { createMuiTheme, MuiThemeProvider } from '@mui/material/styles'
import MUIRichTextEditor from 'mui-rte'

const defaultTheme = createMuiTheme()
Expand Down Expand Up @@ -315,7 +327,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.|
|icon|`JSX.Element`|optional|The `@mui/icons-material` 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.|
Expand Down Expand Up @@ -424,13 +436,13 @@ Check the [release notes](https://github.com/niuware/mui-rte/releases) for the c
For development use:

```
$ npm run watch
$ npm run build
$ npm run serve
```

## Future plans

- Increase test coverage
- Add test coverage
- Refactor code
- Add new features

Expand Down
28 changes: 13 additions & 15 deletions examples/async-atomic-custom-block/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React, { useRef, useState, FunctionComponent, useEffect } from 'react'
import MUIRichTextEditor, { TMUIRichTextEditorRef, TAsyncAtomicBlockResponse } from '../..'
import { makeStyles } from '@material-ui/core/styles'
import Card from '@material-ui/core/Card'
import CardContent from '@material-ui/core/CardContent'
import Typography from '@material-ui/core/Typography'
import Grid from '@material-ui/core/Grid'
import Popover from '@material-ui/core/Popover'
import TextField from '@material-ui/core/TextField'
import Button from '@material-ui/core/Button'
import UpdateIcon from '@material-ui/icons/Update'
import DoneIcon from '@material-ui/icons/Done'
import CloseIcon from '@material-ui/icons/Close'
import { makeStyles } from '@mui/styles'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid'
import Popover from '@mui/material/Popover'
import TextField from '@mui/material/TextField'
import Button from '@mui/material/Button'
import UpdateIcon from '@mui/icons-material/Update'
import DoneIcon from '@mui/icons-material/Done'
import CloseIcon from '@mui/icons-material/Close'

type TMyCardData = {
searchTerm?: string
Expand Down Expand Up @@ -125,9 +125,6 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
<Popover
anchorEl={state.anchor}
open={state.anchor !== null}
onExited={() => {
props.onSubmit(data, !state.isCancelled)
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
Expand All @@ -147,7 +144,7 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
placeholder="Type anything here..."
/>
</Grid>
<Grid item container xs={12} justify="flex-end">
<Grid item container xs={12} justifyContent="flex-end">
<Button onClick={() => {
setState({
anchor: null,
Expand All @@ -162,6 +159,7 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
anchor: null,
isCancelled: false
})
props.onSubmit(data, !state.isCancelled)
}}
>
<DoneIcon />
Expand Down
26 changes: 12 additions & 14 deletions examples/async-image-upload/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React, { useRef, useState, FunctionComponent, useEffect } from 'react'
import MUIRichTextEditor, { TMUIRichTextEditorRef, TAsyncAtomicBlockResponse } from '../..'
import Grid from '@material-ui/core/Grid'
import { makeStyles } from '@material-ui/core/styles'
import Popover from '@material-ui/core/Popover'
import TextField from '@material-ui/core/TextField'
import IconButton from '@material-ui/core/IconButton'
import Button from '@material-ui/core/Button'
import BackupIcon from '@material-ui/icons/Backup'
import DoneIcon from '@material-ui/icons/Done'
import CloseIcon from '@material-ui/icons/Close'
import AttachFileIcon from '@material-ui/icons/AttachFile'
import Grid from '@mui/material/Grid'
import { makeStyles } from '@mui/styles'
import Popover from '@mui/material/Popover'
import TextField from '@mui/material/TextField'
import IconButton from '@mui/material/IconButton'
import Button from '@mui/material/Button'
import BackupIcon from '@mui/icons-material/Backup'
import DoneIcon from '@mui/icons-material/Done'
import CloseIcon from '@mui/icons-material/Close'
import AttachFileIcon from '@mui/icons-material/AttachFile'

interface IUploadImagePopoverProps {
anchor: TAnchor
Expand Down Expand Up @@ -91,9 +91,6 @@ const UploadImagePopover: FunctionComponent<IUploadImagePopoverProps> = (props)
<Popover
anchorEl={state.anchor}
open={state.anchor !== null}
onExited={() => {
props.onSubmit(data, !state.isCancelled)
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
Expand Down Expand Up @@ -131,7 +128,7 @@ const UploadImagePopover: FunctionComponent<IUploadImagePopoverProps> = (props)
</IconButton>
</label>
</Grid>
<Grid item container xs={12} justify="flex-end">
<Grid item container xs={12} justifyContent="flex-end">
<Button onClick={() => {
setState({
anchor: null,
Expand All @@ -146,6 +143,7 @@ const UploadImagePopover: FunctionComponent<IUploadImagePopoverProps> = (props)
anchor: null,
isCancelled: false
})
props.onSubmit(data, !state.isCancelled)
}}
>
<DoneIcon />
Expand Down
26 changes: 12 additions & 14 deletions examples/atomic-custom-block/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import MUIRichTextEditor, { TMUIRichTextEditorRef } from '../..'
import {
Card, CardHeader, Avatar, CardMedia, CardContent,
Typography, IconButton, CardActions, Grid
} from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import Popover from '@material-ui/core/Popover'
import TextField from '@material-ui/core/TextField'
import Button from '@material-ui/core/Button'
import WebAssetIcon from '@material-ui/icons/WebAsset'
import ShareIcon from '@material-ui/icons/Share'
import FavoriteIcon from '@material-ui/icons/Favorite'
import DoneIcon from '@material-ui/icons/Done'
import CloseIcon from '@material-ui/icons/Close'
} from '@mui/material'
import { makeStyles } from '@mui/styles'
import Popover from '@mui/material/Popover'
import TextField from '@mui/material/TextField'
import Button from '@mui/material/Button'
import WebAssetIcon from '@mui/icons-material/WebAsset'
import ShareIcon from '@mui/icons-material/Share'
import FavoriteIcon from '@mui/icons-material/Favorite'
import DoneIcon from '@mui/icons-material/Done'
import CloseIcon from '@mui/icons-material/Close'

type TMyCardData = {
title?: string
Expand Down Expand Up @@ -148,9 +148,6 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
<Popover
anchorEl={state.anchor}
open={state.anchor !== null}
onExited={() => {
props.onSubmit(data, !state.isCancelled)
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
Expand Down Expand Up @@ -190,7 +187,7 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
name="image"
/>
</Grid>
<Grid item container xs={12} justify="flex-end">
<Grid item container xs={12} justifyContent="flex-end">
<Button onClick={() => {
setState({
anchor: null,
Expand All @@ -205,6 +202,7 @@ const MyCardPopover: FunctionComponent<IMyCardPopoverProps> = (props) => {
anchor: null,
isCancelled: false
})
props.onSubmit(data, !state.isCancelled)
}}
>
<DoneIcon />
Expand Down
4 changes: 2 additions & 2 deletions examples/autocomplete-atomic/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FunctionComponent } from 'react'
import Avatar from '@material-ui/core/Avatar'
import Chip from '@material-ui/core/Chip'
import Avatar from '@mui/material/Avatar'
import Chip from '@mui/material/Chip'
import MUIRichTextEditor, { TAutocompleteItem } from '../../'

const save = (data: string) => {
Expand Down
6 changes: 3 additions & 3 deletions examples/autocomplete/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FunctionComponent } from 'react'
import ListItemText from '@material-ui/core/ListItemText'
import ListItemAvatar from '@material-ui/core/ListItemAvatar'
import Avatar from '@material-ui/core/Avatar'
import ListItemText from '@mui/material/ListItemText'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import Avatar from '@mui/material/Avatar'
import MUIRichTextEditor, { TAutocompleteItem } from '../../'

const save = (data: string) => {
Expand Down
6 changes: 3 additions & 3 deletions examples/custom-controls/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FunctionComponent } from 'react'
import { Chip, Avatar, Button } from '@material-ui/core'
import InvertColorsIcon from '@material-ui/icons/InvertColors'
import { Chip, Avatar, Button } from '@mui/material'
import InvertColorsIcon from '@mui/icons-material/InvertColors'
import MUIRichTextEditor, { TToolbarComponentProps } from '../../'
import { EditorState } from 'draft-js'

Expand Down Expand Up @@ -49,7 +49,7 @@ const MyBlockComponent: FunctionComponent<TToolbarComponentProps> = (props) => {
id={props.id}
variant="contained"
onMouseDown={props.onMouseDown}
color={props.active ? "primary" : "default"}
color={props.active ? "primary" : "inherit"}
disabled={props.disabled}
>
My Block
Expand Down
2 changes: 1 addition & 1 deletion examples/custom-inline-toolbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import MUIRichTextEditor from '../../'
import InvertColorsIcon from '@material-ui/icons/InvertColors'
import InvertColorsIcon from '@mui/icons-material/InvertColors'

const save = (data: string) => {
console.log(data)
Expand Down
Loading

0 comments on commit c02652c

Please sign in to comment.