Skip to content

Instantly share code, notes, and snippets.

@kaleem-elahi
Last active April 5, 2024 15:30
Show Gist options
  • Save kaleem-elahi/7d73bb5505518c3f1868f54d11ee3f80 to your computer and use it in GitHub Desktop.
Save kaleem-elahi/7d73bb5505518c3f1868f54d11ee3f80 to your computer and use it in GitHub Desktop.
WYSIWYG Editor for React apps with redux-form field
import React from 'react';
import RichTextEditorWYSWYG from '../../../../shared/compound/RichTextEditorWYSWYG';
import { Form, Field, reduxForm } from 'redux-form';
<Field
label="jobDescription"
name="description"
component={RichTextEditorWYSWYG}
value={props.initialValues.description || ''}
/>
import React, { Component } from 'react';
// import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Linkify from 'react-linkify';
import {
renderToString,
} from 'react-dom/server';
import Parser from 'html-react-parser';
const style =
'<style>*:not(h1, h2, h3, h4, h5, h6){font-size: 12px;}body{font-family:sans-serif,Arial,Verdana,"Trebuchet MS";font-size:13px;line-height:1.6;word-wrap:break-word;color:#333;}blockquote{font-family: Georgia, Times, "Times New Roman", serif;padding: 5px 16px;border-left:5px solid #ccc;font-style:italic}.marker{background-color:#ff0}</style>';
const linkify = data => renderToString(<Linkify>{Parser(data)}</Linkify>);
class Frame extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.resizeIframe = this.resizeIframe.bind(this);
}
componentDidMount() {
this.resizeIframe();
}
resizeIframe() {
this.myRef.current.style.height =
`${this.myRef.current.contentDocument.body.clientHeight + 35}px`;
this.myRef.current.style.transition = 'height .3s';
const x = this.myRef.current.contentDocument.querySelectorAll('a');
// eslint-disable-next-line no-plusplus
for (let i = 0; i < x.length; i++) {
x[i].setAttribute('target', '_blank');
}
}
render() {
return (
<div className="job-description rtf">
<iframe
ref={this.myRef}
onLoad={this.resizeIframe}
scrolling="auto"
title="iframe"
srcDoc={linkify(`<base target="_blank">${style}${this.props.html}`)}
> <base target="_blank" />
</iframe>
</div>
);
}
}
Frame.propTypes = {
html: PropTypes.string,
};
Frame.defaultProps = {
html:
'<!DOCTYPE html><html><head></head><body><div class="frame-root">No Description Found!</div></body></html>',
};
export default Frame;
/* eslint-disable react/prop-types */
import React from 'react';
import { compose, withHandlers, withState, withPropsOnChange } from 'recompose';
import { EditorState, ContentState, convertToRaw } from 'draft-js';
import htmlToDraft from 'html-to-draftjs';
import draftToHtml from 'draftjs-to-html';
import { Editor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
const RichTextEditorWYSIWYG =
({
// input: {
// value,
// onChange,
// },
meta: { touched, error },
editorState,
onEditorStateChange,
}) => (
<div className="WysiwygEditor">
{
editorState &&
<Editor
editorState={editorState}
onEditorStateChange={onEditorStateChange}
editorClassName="editor"
toolbarClassName="toolbar"
toolbar={{ options: ['inline', 'blockType', 'fontSize', 'list', 'textAlign', 'link', 'history'] }}
/>
}
{touched && error && <div>{error}</div>}
</div>
);
export default compose(
withState('editorState', 'setEditorState', EditorState.createEmpty()),
withPropsOnChange(
['input'],
({
input: {
value,
},
meta: {
dirty,
},
setEditorState,
}) => {
if (dirty) {
return;
}
if (!value) {
return;
}
const contentBlock = htmlToDraft(value);
const contentState = ContentState.createFromBlockArray(contentBlock.contentBlocks);
const editorState = EditorState.createWithContent(contentState);
setEditorState(editorState);
},
),
withHandlers({
onEditorStateChange: ({
input: {
onChange,
},
setEditorState,
}) => (editorState) => {
setEditorState(editorState);
const html = draftToHtml(convertToRaw(editorState.getCurrentContent()));
onChange(html);
},
}),
)(RichTextEditorWYSIWYG);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment