burdy
Version:
Open Source Headless Platform
246 lines (245 loc) • 10.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const dynamic_richtext_context_1 = require("../dynamic-richtext.context");
const dynamic_form_1 = require("../dynamic-form");
const draft_js_1 = require("draft-js");
const react_2 = require("@fluentui/react");
const richtext_toolbar_1 = __importDefault(require("./components/richtext-toolbar"));
const draft_image_block_1 = __importDefault(require("./blocks/draft-image-block"));
const draft_ace_block_1 = __importDefault(require("./blocks/draft-ace-block"));
const use_debounce_1 = require("use-debounce");
const draft_component_block_1 = __importDefault(require("./blocks/draft-component-block"));
const draft_divider_block_1 = __importDefault(require("./blocks/draft-divider-block"));
const draft_link_inline_1 = require("./inline/draft-link-inline");
const useStyles = (0, react_2.makeStyles)((theme) => ({
editorToolbar: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
'> *': {
marginBottom: 4,
},
},
editor: {
display: 'grid',
overflowY: 'auto',
border: `1px solid ${theme.palette.neutralSecondary}`,
padding: 8,
'.DraftEditor-root': {
height: '400px',
},
'&:hover': {
cursor: 'text',
},
'* > figure': {
marginInlineStart: 20,
marginInlineEnd: 20,
},
},
editorDisabled: {
background: theme.semanticColors.disabledBackground,
borderColor: theme.semanticColors.disabledBorder,
color: theme.semanticColors.disabledText,
},
callout: {
width: 320,
padding: '20px 24px',
},
}));
const RichText = ({ field, name, onChange }) => {
var _a;
const classes = useStyles();
const { editorState, setEditorState, editor, setKeyMap, toggleInlineStyle, toggleBlockType, handleKeypress, handleKeyCommand, editorProps, forceUpdateState, } = (0, dynamic_richtext_context_1.useRichtext)();
const { disabled } = (0, dynamic_form_1.useExtendedFormContext)();
const disableHeaderBlock = () => {
const contentState = editorState.getCurrentContent();
const selection = editorState.getSelection();
const currentBlockType = contentState
.getBlockForKey(selection.getStartKey())
.getType();
if (!/^header-\w+$/i.test(currentBlockType)) {
return 'not-handled';
}
const focusOffset = selection.getFocusOffset();
const splitBlockContent = draft_js_1.Modifier.splitBlock(contentState, selection);
const newLineEditorState = draft_js_1.EditorState.push(editorState, splitBlockContent, 'split-block');
const newLineSelection = newLineEditorState.getSelection();
const newLineContent = newLineEditorState.getCurrentContent();
if (focusOffset === 0) {
setEditorState(newLineEditorState);
}
else {
setEditorState(draft_js_1.EditorState.push(newLineEditorState, draft_js_1.Modifier.setBlockType(newLineContent, newLineSelection, 'unstyled'), 'change-block-type'));
}
return 'handled';
};
(0, react_1.useEffect)(() => {
setKeyMap([
{
key: 'b',
name: 'bold',
ctrlKey: true,
handle: () => toggleInlineStyle('BOLD'),
},
{
key: 'i',
name: 'italic',
ctrlKey: true,
handle: () => toggleInlineStyle('ITALIC'),
},
{
key: 'u',
name: 'underline',
ctrlKey: true,
handle: () => toggleInlineStyle('UNDERLINE'),
},
{
key: '1',
name: 'h1',
ctrlKey: true,
handle: () => toggleBlockType('header-one'),
},
{
key: '2',
name: 'h2',
ctrlKey: true,
handle: () => toggleBlockType('header-two'),
},
{
key: '3',
name: 'h3',
ctrlKey: true,
handle: () => toggleBlockType('header-three'),
},
{
key: '4',
name: 'h4',
ctrlKey: true,
handle: () => toggleBlockType('header-four'),
},
{
key: '5',
name: 'h5',
ctrlKey: true,
handle: () => toggleBlockType('header-five'),
},
{
key: '6',
name: 'h6',
ctrlKey: true,
handle: () => toggleBlockType('header-six'),
},
{
key: 'o',
name: 'ordered-list',
ctrlKey: true,
handle: () => toggleBlockType('unordered-list-item'),
},
{
key: 'u',
name: 'unordered-list',
ctrlKey: true,
handle: () => toggleBlockType('ordered-list-item'),
},
]);
}, [editorState]);
const onTab = (e) => {
e.preventDefault();
// assign a constant for the new editorState
const newState = draft_js_1.RichUtils.onTab(e, editorState, 4);
// if a new editor state exists, set editor state to new state
// and return 'handled', otherwise return 'not-handled
if (newState) {
setEditorState(newState);
return 'handled';
}
return 'not-handled';
};
const handlePaste = (test, html, editorState) => {
try {
const parsed = JSON.parse(test);
if ((parsed === null || parsed === void 0 ? void 0 : parsed.entityMap) && Array.isArray(parsed === null || parsed === void 0 ? void 0 : parsed.blocks)) {
const contentState = (0, draft_js_1.convertFromRaw)(parsed);
const newEditorState = draft_js_1.EditorState.createWithContent(contentState, (0, draft_link_inline_1.createLinkDecorator)());
setEditorState(newEditorState);
return 'handled';
}
}
catch (_a) {
//
}
return 'not-handled';
};
const debounced = (0, use_debounce_1.useDebouncedCallback)((editorState) => {
onChange(JSON.stringify((0, draft_js_1.convertToRaw)(editorState.getCurrentContent())));
}, 300);
(0, react_1.useEffect)(() => {
debounced(editorState);
}, [name, editorState, forceUpdateState]);
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement(react_2.Label, null, ((_a = field === null || field === void 0 ? void 0 : field.label) === null || _a === void 0 ? void 0 : _a.length) > 0 ? field === null || field === void 0 ? void 0 : field.label : field === null || field === void 0 ? void 0 : field.name),
react_1.default.createElement("div", { className: classes.editorToolbar },
react_1.default.createElement(richtext_toolbar_1.default, null)),
react_1.default.createElement("div", { className: `${classes.editor} ${disabled && classes.editorDisabled}`, "data-cy": `richtext-${name}` },
react_1.default.createElement(draft_js_1.Editor, Object.assign({ ref: editor, editorState: editorState, onChange: (state) => {
setEditorState(state);
}, onTab: onTab, handlePastedText: handlePaste, handleReturn: disableHeaderBlock, readOnly: disabled, keyBindingFn: handleKeypress, handleKeyCommand: handleKeyCommand, blockRendererFn: (block) => {
if (block.getType() === 'atomic') {
const contentState = editorState.getCurrentContent();
const entity = block.getEntityAt(0);
if (!entity)
return null;
const type = contentState.getEntity(entity).getType();
if (type === 'IMAGE') {
return {
component: draft_image_block_1.default,
editable: false,
};
}
if (type === 'TEXT_EDITOR') {
return {
component: draft_ace_block_1.default,
editable: false,
};
}
if (type === 'COMPONENT') {
return {
component: draft_component_block_1.default,
editable: false,
};
}
if (type === 'DIVIDER') {
return {
component: draft_divider_block_1.default,
editable: false,
};
}
return null;
}
return null;
}, spellCheck: true }, editorProps)))));
};
exports.default = RichText;