UNPKG

mui-tiptap

Version:

A Material-UI (MUI) styled WYSIWYG rich text editor, using Tiptap

95 lines (94 loc) 4.9 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { styled, useThemeProps } from "@mui/material/styles"; import { clsx } from "clsx"; import FieldContainer from "./FieldContainer"; import MenuBar from "./MenuBar"; import RichTextContent from "./RichTextContent"; import { richTextFieldClasses, } from "./RichTextField.classes"; import { useRichTextEditorContext } from "./context"; import useDebouncedFocus from "./hooks/useDebouncedFocus"; import { getUtilityComponentName } from "./styles"; import DebounceRender from "./utils/DebounceRender"; const componentName = getUtilityComponentName("RichTextField"); const RichTextFieldRoot = styled(FieldContainer, { name: componentName, slot: "root", overridesResolver: (props, styles) => [ styles.root, props.ownerState.variant === "outlined" && styles.outlined, props.ownerState.variant === "standard" && styles.standard, ], })(({ theme, ownerState }) => ({ // This first class is added to allow convenient user overrides. Users can // similarly override the other classes below. // TODO(Steven DeMartini): We could seemingly switch to using `styled()` // wrappers for the content and menu bar elements, and apply the styles // directly rather than with nested selectors. ...(ownerState.variant === "standard" && { // We don't need horizontal spacing when not using the outlined variant [`& .${richTextFieldClasses.content}`]: { padding: theme.spacing(1.5, 0), }, [`& .${richTextFieldClasses.menuBarContent}`]: { padding: theme.spacing(1, 0), }, }), ...(ownerState.variant === "outlined" && { // Add padding around the input area and menu bar, since they're // contained in the outline [`& .${richTextFieldClasses.content}`]: { padding: theme.spacing(1.5), }, [`& .${richTextFieldClasses.menuBarContent}`]: { padding: theme.spacing(1, 1.5), }, }), })); /** * Renders the Tiptap rich text editor content and a controls menu bar. * * With the "outlined" variant, renders a bordered UI similar to the Material UI * `TextField`. The "standard" variant does not have an outline/border. * * Must be a child of the RichTextEditorProvider so that the `editor` context is * available. */ export default function RichTextField(inProps) { var _a, _b; const props = useThemeProps({ props: inProps, name: componentName }); const { variant = "outlined", controls, disableDebounceRenderControls = false, disabled, className, classes = {}, footer, MenuBarProps, RichTextContentProps, sx, ...fieldContainerProps } = props; const editor = useRichTextEditorContext(); const ownerState = { variant, disabled, disableDebounceRenderControls, }; // Because the user interactions with the editor menu bar buttons unfocus the editor // (since it's not part of the editor content), we'll debounce our visual focused // state so that the (outlined) field focus styles don't "flash" whenever that happens const isFieldFocused = useDebouncedFocus({ editor }); return (_jsxs(RichTextFieldRoot, { ...fieldContainerProps, variant: variant, focused: !disabled && isFieldFocused, disabled: disabled, className: clsx([ richTextFieldClasses.root, classes.root, variant === "outlined" ? [richTextFieldClasses.outlined, classes.outlined] : [richTextFieldClasses.standard, classes.standard], className, ]), ownerState: ownerState, sx: sx, children: [controls && (_jsx(MenuBar, { ...MenuBarProps, classes: { ...MenuBarProps === null || MenuBarProps === void 0 ? void 0 : MenuBarProps.classes, root: clsx([ richTextFieldClasses.menuBar, classes.menuBar, (_a = MenuBarProps === null || MenuBarProps === void 0 ? void 0 : MenuBarProps.classes) === null || _a === void 0 ? void 0 : _a.root, ]), content: clsx([ richTextFieldClasses.menuBarContent, classes.menuBarContent, (_b = MenuBarProps === null || MenuBarProps === void 0 ? void 0 : MenuBarProps.classes) === null || _b === void 0 ? void 0 : _b.content, ]), }, children: disableDebounceRenderControls ? (controls) : (_jsx(DebounceRender, { children: controls })) })), _jsx(RichTextContent, { ...RichTextContentProps, className: clsx([ richTextFieldClasses.content, classes.content, RichTextContentProps === null || RichTextContentProps === void 0 ? void 0 : RichTextContentProps.className, ]) }), footer] })); }