Simple wysyvig editor on React .
This is a simple editor, developed for internal needs. Support for single-level nesting tags is assumed.
- Install
- Struct data of Editor component
- Simple use Editor
- Custom Editor panel
- Add custom tags
$ npm i react-editor-wysyvig
The editor works with an array of data, each element of which completely describes one displayed element (symbol, image, link, etc.). See the example draw "ok":
import React, { useCallback, useState } from 'react';
import _ from 'lodash';
import Editor from 'react-editor-wysyvig';
import 'react-editor-wysyvig/style/Editor.scss';
const DATAS = [
{id:'1',type:'char',value:'o',style:{}},
{id:'2',type:'char',value:'k',style:{}},
];
function App() {
const [data, setData] = useState(DATAS);
const doChange = (newData) => {
setData(newData);
};
return (
<div>
<Editor onChange={doChange} data = {data}/>
</div>
);
}
name | type | notes |
---|---|---|
id | string | ident |
type | string | type of tag component |
value | string | displayed value |
style | object | react css style for draw |
The editor package includes a utility for converting simple HTML into editor data and back.
import React, { useCallback, useState } from 'react';
import _ from 'lodash';
import Editor from 'react-editor-wysyvig';
import Html from 'react-editor-wysyvig/utils/Html.js';
import 'react-editor-wysyvig/style/Editor.scss';
const HTML = 'Simple<br>text';// init html text';
function App() {
const [data, setData] = useState(Html.toData(HTML));
const [code, setCode] = useState('');
const doDecode = (from) => {
setCode(Html.fromData(from));
};
const decode = useCallback(_.debounce(doDecode, 1000), []);
const doChange = (newData) => {
setData(newData);
decode(newData);
};
return (
<>
<div>
<Editor onChange={doChange} data = {data}/>
</div>
<code>
{code}
</code>
</>
);
}
To replace the built-in style editing panel, add your own component inside the editor.
import React, { useCallback, useState } from 'react';
import _ from 'lodash';
import Editor from 'react-editor-wysyvig';
import 'react-editor-wysyvig/style/Editor.scss';
import Panel from './Panel.jsx';
const DATAS = [
{id:'1',type:'char',value:'o',style:{}},
{id:'2',type:'char',value:'k',style:{}},
];
function App() {
const [data, setData] = useState(DATAS);
const doChange = (newData) => {
setData(newData);
};
return (
<div>
<Editor onChange={doChange} data = {data}>
<Panel/>
</Editor>
</div>
);
}
Example of custom Panel component
import React, {
useCallback, useState,
} from 'react';
import Style from 'react-editor-wysyvig/utils/Style.js';
import EditorTagClass from './EditorTags/EditorTagClass.js';
import eq from 'react-editor-wysyvig/jsx/js/eq';
const Panel=({
data,
selects,
onChange,
cursor,
onSelect,
}) =>{
const change = (newData) => {
if (onChange) {
onChange(newData);
}
};
const changeStyle = (modif) => {
if (onChange) {
let define;
const newData = data.map((it) => {
if (selects.find((sid) => eq.id(it.id, sid))) {
define = define || modif(it.style || {});
return {
...it,
style: {
...it.style,
...define,
},
};
}
return { ...it };
});
onChange(newData);
}
};
const bold = () => {
changeStyle((style) => Style.toggle({ fontWeight: ['bold', ''] }, style));
};
const underline = () => {
changeStyle((style) => Style.toggle({ textDecoration: ['underline', ''] }, style));
};
const italic = () => {
changeStyle((style) => Style.toggle({ fontStyle: ['italic', ''] }, style));
};
return (
<>
<div className='editor-panel'>
<button onClick={bold} >B</button>
<button onClick={underline} >U</button>
<button onClick={italic} >I</button>
</div>
</>
);
}
export default Panel;
To add your custom tag, you need to create a component corresponding to it and register it.
/* eslint-disable camelcase */
import React from 'react';
import get from 'react-editor-wysyvig/jsx/js/get';
import getid from 'react-editor-wysyvig/jsx/js/getid';
function Block({
id,
type,
value,
style = {},
cursor = false,
select = false,
onClick,
}) {
const doClick = (sender) => {
if (onClick) {
onClick({
id, type, value, sender,
});
}
};
return (
<div
id={id}
style={{ ...style }}
className={`${cursor ? 'cursor' : ''} ${select ? 'select' : ''}` }
onMouseDown={doClick}
>
{value}
</div>
);
}
Block.createData = (data = {}) => ({
id: getid(),
type: 'block',
value: '',
...data,
style: { ...get(data, ['style'], {}) },
});
export default Block;
rigister it
import React from 'react';
import EditorTagClass from 'react-editor-wysyvig/jsx/EditorTags/EditorTagClass';
//register Block
EditorTagClass.add([{block:Block}]);