UNPKG

burdy

Version:

Open Source Headless Platform

246 lines (245 loc) 10.4 kB
"use strict"; 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;