UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

148 lines (140 loc) • 6.46 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { styled } from '@mui/material/styles'; import { FormattedMessage } from 'react-intl'; import { Box, Stack } from '@mui/material'; import classNames from 'classnames'; import { useThemeProps } from '@mui/system'; import nodes from './nodes'; import { LexicalComposer } from '@lexical/react/LexicalComposer'; import { ContentEditable } from '@lexical/react/LexicalContentEditable'; import ToolbarPlugin from './plugins/ToolbarPlugin'; import { PREFIX } from './constants'; import { HorizontalRulePlugin } from './plugins/HorizontalRulePlugin'; import { RichTextPlugin } from './plugins/LexicalRichTextPlugin'; import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'; import { AutoLinkPlugin, DefaultHtmlValuePlugin, EmojiPlugin, ImagePlugin, MentionsPlugin, OnChangePlugin } from './plugins'; import OnBlurPlugin from './plugins/OnBlurPlugin'; import OnFocusPlugin from './plugins/OnFocusPlugin'; import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'; import FloatingLinkPlugin from './plugins/FloatingLinkPlugin'; import ApiPlugin from './plugins/ApiPlugin'; import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'; import { ListPlugin } from '@lexical/react/LexicalListPlugin'; const classes = { root: `${PREFIX}-root`, focused: `${PREFIX}-focused`, toolbar: `${PREFIX}-toolbar`, content: `${PREFIX}-content`, placeholder: `${PREFIX}-placeholder`, actions: `${PREFIX}-actions` }; const Root = styled(Box, { name: PREFIX, slot: 'Root', overridesResolver: (props, styles) => { return [styles.root, props.className.includes(classes.toolbar) && styles.toolbar]; } })(({ theme }) => ({})); const editorTheme = { heading: { h1: `${PREFIX}-h1`, h2: `${PREFIX}-h2`, h3: `${PREFIX}-h3`, h4: `${PREFIX}-h4`, h5: `${PREFIX}-h5`, h6: `${PREFIX}-h6` }, link: `${PREFIX}-link`, list: { listitem: `${PREFIX}-listItem`, nested: { listitem: `${PREFIX}-nestedListItem` }, olDepth: [`${PREFIX}-ol1`, `${PREFIX}-ol2`, `${PREFIX}-ol3`, `${PREFIX}-ol4`, `${PREFIX}-ol5`], ul: `${PREFIX}-ul` }, ltr: `${PREFIX}-ltr`, paragraph: `${PREFIX}-paragraph`, image: `${PREFIX}-image`, quote: `${PREFIX}-quote`, rtl: `${PREFIX}-rtl`, text: { bold: `${PREFIX}-textBold`, italic: `${PREFIX}-textItalic`, strikethrough: `${PREFIX}-textStrikethrough`, subscript: `${PREFIX}-textSubscript`, superscript: `${PREFIX}-textSuperscript`, underline: `${PREFIX}-textUnderline`, underlineStrikethrough: `${PREFIX}-textUnderlineStrikethrough` } }; /** * > API documentation for the Community-JS Editor component. Learn about the available props and the CSS API. * * * This component renders a text editor. * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Editor) #### Import ```jsx import {Editor} from '@selfcommunity/react-ui'; ``` #### Component Name The name `SCEditor` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCEditor-root|Styles applied to the root element.| |toolbar|.SCEditor-toolbar|Styles applied to the toolbar element.| |content|.SCEditor-content|Styles applied to the content element.| |placeholder|.SCEditor-placeholder|Styles applied to the placeholder element.| |actions|.SCEditor-actions|Styles applied to the actions section.| * @param inProps */ const Editor = (inProps, ref) => { // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { id = 'editor', className = null, defaultValue = '', toolbar = false, uploadImage = false, editable = true, onChange = null, onFocus = null, onBlur = null } = props; const apiRef = useRef(); // STATE const [focused, setFocused] = useState(false); // HANDLERS const handleChange = (value) => { onChange && onChange(value); }; const handleError = (error, editor) => { console.log(error); }; const handleFocus = () => { apiRef.current.focus(); }; const handleHasFocus = useCallback((event) => { setFocused(true); onFocus && onFocus(event); }, [onFocus]); const handleHasBlur = useCallback((event) => { setFocused(false); onBlur && onBlur(event); }, [onBlur]); // EXPOSED METHODS useImperativeHandle(ref, () => ({ focus: () => { apiRef.current.focus(); } })); // RENDER // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore const initialConfig = useMemo(() => ({ namespace: 'LexicalEditor', editable: editable, onError: handleError, nodes: [...nodes], theme: editorTheme }), [editable]); return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className, { [classes.toolbar]: toolbar, [classes.focused]: focused }) }, { children: _jsxs(LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [toolbar ? (_jsxs(_Fragment, { children: [_jsx(ToolbarPlugin, { uploadImage: uploadImage }), _jsx(ListPlugin, {}), _jsx(HorizontalRulePlugin, {})] })) : (_jsxs(Stack, Object.assign({ className: classes.actions, direction: "row" }, { children: [uploadImage && _jsx(ImagePlugin, {}), _jsx(EmojiPlugin, {})] }))), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: classes.content }), placeholder: _jsx(Box, Object.assign({ className: classes.placeholder, onClick: handleFocus }, { children: _jsx(FormattedMessage, { id: "ui.editor.placeholder", defaultMessage: "ui.editor.placeholder" }) })), ErrorBoundary: LexicalErrorBoundary }), _jsx(DefaultHtmlValuePlugin, { defaultValue: defaultValue }), _jsx(HistoryPlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(OnBlurPlugin, { onBlur: handleHasBlur }), _jsx(OnFocusPlugin, { onFocus: handleHasFocus }), _jsx(AutoLinkPlugin, {}), _jsx(MentionsPlugin, {}), _jsx(LinkPlugin, {}), _jsx(FloatingLinkPlugin, {}), _jsx(ApiPlugin, { ref: apiRef })] })) }))); }; export default forwardRef(Editor);