UNPKG

@dotcms/react

Version:

Official React Components library to render a dotCMS page.

182 lines (179 loc) 5.74 kB
import { jsx } from 'react/jsx-runtime'; import { Editor } from '@tinymce/tinymce-react'; import { useRef, useState, useEffect } from 'react'; import { UVE_MODE, DotCMSUVEAction } from '@dotcms/types'; import { __DOTCMS_UVE_EVENT__ } from '@dotcms/types/internal'; import { getUVEState, sendMessageToUVE } from '@dotcms/uve'; import { __TINYMCE_PATH_ON_DOTCMS__ } from '@dotcms/uve/internal'; import { TINYMCE_CONFIG } from './utils.esm.js'; /** * Allows inline edit content pulled from dotCMS API using TinyMCE editor * * @export * @component * @param {Readonly<DotCMSEditableTextProps>} props { * mode = 'plain', * format = 'text', * contentlet, * fieldName = '' * } * @example * ```javascript * import { DotCMSEditableText } from '@dotcms/react'; * * const MyContentletWithTitle = ({ contentlet }) => ( * <h2> * <DotCMSEditableText * contentlet={contentlet} * fieldName="title" * mode='full' * format='text'/> * </h2> * ); * ``` * @returns {JSX.Element} A component to edit content inline */ function DotCMSEditableText({ mode = 'plain', format = 'text', contentlet, fieldName }) { const editorRef = useRef(null); const [scriptSrc, setScriptSrc] = useState(''); const [initEditor, setInitEditor] = useState(false); const [content, setContent] = useState((contentlet == null ? void 0 : contentlet[fieldName]) || ''); useEffect(() => { setContent((contentlet == null ? void 0 : contentlet[fieldName]) || ''); }, [fieldName, contentlet]); useEffect(() => { var _state$dotCMSHost, _editorRef$current; const state = getUVEState(); setInitEditor((state == null ? void 0 : state.mode) === UVE_MODE.EDIT && !!(state != null && (_state$dotCMSHost = state.dotCMSHost) != null && _state$dotCMSHost.length)); if (!contentlet || !fieldName) { console.error('[DotCMSEditableText]: contentlet or fieldName is missing', 'Ensure that all needed props are passed to view and edit the content'); return; } if (state && state.mode !== UVE_MODE.EDIT) { console.warn('[DotCMSEditableText]: TinyMCE is not available in the current mode'); return; } if (!(state != null && state.dotCMSHost)) { console.warn('[DotCMSEditableText]: The `dotCMSHost` parameter is not defined. Check that the UVE is sending the correct parameters.'); return; } const createURL = new URL(__TINYMCE_PATH_ON_DOTCMS__, state.dotCMSHost); setScriptSrc(createURL.toString()); const content = (contentlet == null ? void 0 : contentlet[fieldName]) || ''; (_editorRef$current = editorRef.current) == null || _editorRef$current.setContent(content, { format }); }, [format, fieldName, contentlet, content]); useEffect(() => { var _getUVEState; if (((_getUVEState = getUVEState()) == null ? void 0 : _getUVEState.mode) !== UVE_MODE.EDIT) { return; } const onMessage = ({ data }) => { const { name, payload } = data; if (name !== __DOTCMS_UVE_EVENT__.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS) { return; } const { oldInode, inode } = payload; const currentInode = contentlet.inode; const shouldFocus = currentInode === oldInode || currentInode === inode; if (shouldFocus) { var _editorRef$current2; (_editorRef$current2 = editorRef.current) == null || _editorRef$current2.focus(); } }; window.addEventListener('message', onMessage); return () => { window.removeEventListener('message', onMessage); }; }, [contentlet == null ? void 0 : contentlet.inode]); const onMouseDown = event => { var _editorRef$current3; const { onNumberOfPages = 1 } = contentlet; const { inode, languageId: language } = contentlet; if (Number(onNumberOfPages) <= 1 || (_editorRef$current3 = editorRef.current) != null && _editorRef$current3.hasFocus()) { return; } event.stopPropagation(); event.preventDefault(); sendMessageToUVE({ action: DotCMSUVEAction.COPY_CONTENTLET_INLINE_EDITING, payload: { dataset: { inode, language, fieldName } } }); }; const onFocusOut = () => { var _editorRef$current4, _editorRef$current5; const editedContent = ((_editorRef$current4 = editorRef.current) == null ? void 0 : _editorRef$current4.getContent({ format: format })) || ''; const { inode, languageId: langId } = contentlet; if (!((_editorRef$current5 = editorRef.current) != null && _editorRef$current5.isDirty()) || !didContentChange(editedContent)) { return; } sendMessageToUVE({ action: DotCMSUVEAction.UPDATE_CONTENTLET_INLINE_EDITING, payload: { content: editedContent, dataset: { inode, langId, fieldName } } }); }; const didContentChange = editedContent => { return content !== editedContent; }; if (!initEditor) { // We can let the user pass the Child Component and create a root to get the HTML for the editor return jsx("span", { dangerouslySetInnerHTML: { __html: content } }); } return jsx("div", { style: { outline: '2px solid #006ce7', borderRadius: '4px' }, children: jsx(Editor, { tinymceScriptSrc: scriptSrc, inline: true, onInit: (_, editor) => editorRef.current = editor, init: TINYMCE_CONFIG[mode], initialValue: content, onMouseDown: onMouseDown, onFocusOut: onFocusOut }) }); } export { DotCMSEditableText };