UNPKG

mui-tiptap

Version:

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

83 lines (82 loc) 5.45 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import Button from "@mui/material/Button"; import ClickAwayListener from "@mui/material/ClickAwayListener"; import Fade from "@mui/material/Fade"; import Paper from "@mui/material/Paper"; import Popper from "@mui/material/Popper"; import Stack from "@mui/material/Stack"; import Tooltip from "@mui/material/Tooltip"; import { styled, useThemeProps, } from "@mui/material/styles"; import { clsx } from "clsx"; import { useEffect, useState } from "react"; import { getUtilityComponentName } from "../styles"; import { ColorPicker } from "./ColorPicker"; import { colorPickerPopperClasses, } from "./ColorPickerPopper.classes"; // NOTE: This component's state logic is able to be kept simple because the // component is unmounted whenever the outer Popper is not open, so we don't // have to worry about resetting the state ourselves when the user cancels, for // instance. export function ColorPickerPopperBody({ value, onCancel, onSave, swatchColors, labels = {}, ColorPickerProps, }) { const { removeColorButton = "None", removeColorButtonTooltipTitle = "", cancelButton = "Cancel", saveButton = "OK", } = labels; // Because color can change rapidly as the user drags the color in the // ColorPicker gradient, we'll wait until "Save" to call the onSave prop, and // we'll store an internal localColor until then. (This could alternatively be // implemented such that we "save" directly whenever a swatch preset is // clicked, by looking at the `source` from `ColorPicker.onChange`, but it may // be useful to tweak a color from a swatch before saving.) const [localColor, setLocalColor] = useState(value); // Update our internal value whenever the `color` prop changes (since this is // a controlled component) useEffect(() => { setLocalColor(value); }, [value]); return (_jsxs(_Fragment, { children: [_jsx(ColorPicker, { swatchColors: swatchColors, value: localColor, onChange: (newColor) => { setLocalColor(newColor); }, labels: labels, ...ColorPickerProps }), _jsxs(Stack, { direction: "row", sx: { justifyContent: "space-between", mt: 1 }, children: [_jsx(Tooltip, { title: removeColorButtonTooltipTitle, arrow: true, children: _jsx(Button, { onClick: () => { // No color being specified can mean "none" in some scenarios // (e.g. highlighting) and "default color"/reset in others (text) onSave(""); }, size: "small", children: removeColorButton }) }), _jsx(Button, { onClick: onCancel, size: "small", children: cancelButton }), _jsx(Button, { onClick: () => { onSave(localColor); }, size: "small", children: saveButton })] })] })); } const componentName = getUtilityComponentName("ColorPickerPopper"); const ColorPickerPopperRoot = styled(Popper, { name: componentName, slot: "root", overridesResolver: (props, styles) => styles.root, })(({ theme }) => ({ // Ensure the popper is above modals, in case the editor is rendered in a // modal, consistent with recommendations here // https://github.com/mui/material-ui/issues/14216. See // https://github.com/sjdemartini/mui-tiptap/issues/206. zIndex: theme.zIndex.tooltip, // This width seems to work well to allow exactly 8 swatches, as well as the // default button content width: 235, })); /** * Renders the ColorPicker inside of a Popper interface, for use with the * MenuButtonColorPicker. */ export function ColorPickerPopper(inProps) { const props = useThemeProps({ props: inProps, name: componentName }); const { value, onSave, onCancel, swatchColors, ColorPickerProps, labels, classes = {}, sx, ...popperProps } = props; return (_jsx(ColorPickerPopperRoot, { transition: true, placement: "bottom-start", ...popperProps, className: clsx([ colorPickerPopperClasses.root, classes.root, popperProps.className, ]), sx: sx, children: ({ TransitionProps }) => (_jsx(Fade, { ...TransitionProps, timeout: 100, children: _jsx("div", { children: _jsx(ClickAwayListener // Listen for "leading" events (the start of a click or touch) // rather than the trailing events (the end of a click) which is // the default, since it's easy to accidentally drag the // color-picker saturation/hue gradients beyond the edge of the // Popper, and we don't want to close in that situation. , { // Listen for "leading" events (the start of a click or touch) // rather than the trailing events (the end of a click) which is // the default, since it's easy to accidentally drag the // color-picker saturation/hue gradients beyond the edge of the // Popper, and we don't want to close in that situation. mouseEvent: "onMouseDown", touchEvent: "onTouchStart", onClickAway: onCancel, children: _jsx(Paper, { elevation: 5, sx: { p: 2.5, pb: 1 }, children: _jsx(ColorPickerPopperBody, { value: value || "", onSave: onSave, onCancel: onCancel, swatchColors: swatchColors, ColorPickerProps: ColorPickerProps, labels: labels }) }) }) }) })) })); }