FPSMS-frontend
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

319 строки
12 KiB

  1. "use client";
  2. import { Button, ButtonGroup, Grid, IconButton, ToggleButton, ToggleButtonGroup } from "@mui/material";
  3. import "./MailField.css"
  4. import { useEditor, EditorContent, Editor } from "@tiptap/react"
  5. import FormatBoldIcon from '@mui/icons-material/FormatBold';
  6. import React, { useCallback } from "react";
  7. import { FormatItalic, FormatUnderlined } from "@mui/icons-material";
  8. import { MuiColorInput, MuiColorInputColors, MuiColorInputValue } from 'mui-color-input'
  9. import BorderColorIcon from '@mui/icons-material/BorderColor';
  10. import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
  11. import FormatColorTextIcon from '@mui/icons-material/FormatColorText';
  12. import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft';
  13. import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify';
  14. import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight';
  15. interface Props {
  16. editor: Editor | null;
  17. }
  18. const colorInputSx = {
  19. width: 150,
  20. height: 25,
  21. ".MuiInputBase-colorPrimary": {
  22. margin: -1,
  23. borderRadius: "0px 5px 5px 0px",
  24. borderColor: "rgba(0, 0, 0, 0)",
  25. backgroundColor: "rgba(0, 0, 0, 0)",
  26. },
  27. ".Mui-focused": {
  28. borderColor: "rgba(0, 0, 0, 0)",
  29. },
  30. ".MuiColorInput-Button": {
  31. marginBottom: 2,
  32. borderColor: "rgba(0, 0, 0, 0)",
  33. backgroundColor: "rgba(0, 0, 0, 0)",
  34. },
  35. ".MuiInputBase-input": {
  36. marginBottom: 1.5,
  37. },
  38. }
  39. const fontFamily = [
  40. {
  41. label: 'Arial',
  42. value: 'Arial',
  43. },
  44. {
  45. label: 'Times New Roman',
  46. value: 'Times New Roman',
  47. },
  48. {
  49. label: 'Courier New',
  50. value: 'Courier New',
  51. },
  52. {
  53. label: 'Georgia',
  54. value: 'Georgia',
  55. },
  56. {
  57. }
  58. ]
  59. const MailToolbar: React.FC<Props> = ({
  60. editor
  61. }) => {
  62. if (editor == null) {
  63. return null
  64. }
  65. const [fontStyle, setFontStyle] = React.useState<string[]>(() => ["alignLeft"]);
  66. const [colorHighlightValue, setColorHighlightValue] = React.useState<MuiColorInputValue>("red");
  67. const [colorTextValue, setColorTextValue] = React.useState<MuiColorInputValue>("black");
  68. const colorHighlightValueInputRef = React.useRef<any>(null);
  69. const colorTextValueInputRef = React.useRef<any>(null);
  70. const handleFontStyle = useCallback((
  71. event: React.MouseEvent<HTMLElement>,
  72. newFontStyles: string[],
  73. ) => {
  74. setFontStyle((prev) => {
  75. const id = event.currentTarget?.id
  76. const include = prev.includes(id)
  77. if (include) {
  78. return prev.filter(ele => ele !== id)
  79. } else {
  80. prev = prev.filter(ele => !ele.includes("align"))
  81. prev.push(id)
  82. return prev
  83. }
  84. });
  85. }, []);
  86. const handleColorHighlightValue = useCallback((value: string, colors: MuiColorInputColors) => {
  87. // console.log(colors)
  88. setColorHighlightValue(() => value)
  89. // editor.chain().focus().toggleHighlight({ color: value }).run()
  90. }, [])
  91. const handleColorHighlightValueClick = useCallback((event: React.MouseEvent<HTMLElement>) => {
  92. editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run()
  93. }, [colorHighlightValue])
  94. const handleColorHighlightValueClose = useCallback((event: {}, reason: "backdropClick" | "escapeKeyDown") => {
  95. // console.log(event)
  96. editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run()
  97. }, [colorHighlightValue])
  98. const handleColorHighlightValueBlur = useCallback((event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
  99. editor.chain().focus().toggleHighlight({ color: colorHighlightValue.toString() }).run()
  100. }, [colorHighlightValue])
  101. const handleColorTextValue = useCallback((value: string, colors: MuiColorInputColors) => {
  102. // console.log(colors)
  103. setColorTextValue(() => value)
  104. // if (editor.isActive("textStyle")) {
  105. // editor.chain().focus().unsetColor().run()
  106. // } else {
  107. // editor.chain().focus().setColor(value).run()
  108. // }
  109. }, [])
  110. const handleColorTextValueClick = useCallback((event: React.MouseEvent<HTMLElement>) => {
  111. if (editor.isActive("textStyle", { color: colorTextValue.toString() })) {
  112. editor.chain().focus().unsetColor().run()
  113. } else {
  114. editor.chain().focus().setColor(colorTextValue.toString()).run()
  115. }
  116. }, [colorTextValue])
  117. const handleColorTextValueClose = useCallback((event: {}, reason: "backdropClick" | "escapeKeyDown") => {
  118. if (editor.isActive("textStyle", { color: colorTextValue.toString() })) {
  119. editor.chain().focus().unsetColor().run()
  120. } else {
  121. editor.chain().focus().setColor(colorTextValue.toString()).run()
  122. }
  123. }, [colorTextValue])
  124. const handleColorTextValueBlur = useCallback((event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {
  125. if (editor.isActive("textStyle", { color: colorTextValue.toString() })) {
  126. editor.chain().focus().unsetColor().run()
  127. } else {
  128. editor.chain().focus().setColor(colorTextValue.toString()).run()
  129. }
  130. }, [colorTextValue])
  131. const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
  132. if (event.key === 'Enter') {
  133. if (colorHighlightValueInputRef.current !== null) {
  134. colorHighlightValueInputRef.current.blur();
  135. }
  136. if (colorTextValueInputRef.current !== null) {
  137. colorTextValueInputRef.current.blur();
  138. }
  139. }
  140. }
  141. const handleTextAlign = useCallback((event: React.MouseEvent<HTMLElement, MouseEvent>, value: any) => {
  142. console.log(value)
  143. switch (value) {
  144. case "alignLeft":
  145. if (editor.isActive({ textAlign: 'left' })) {
  146. editor.chain().focus().unsetTextAlign().run()
  147. } else {
  148. editor.chain().focus().setTextAlign('left').run()
  149. }
  150. break;
  151. case "alignCenter":
  152. if (editor.isActive({ textAlign: 'center' })) {
  153. editor.chain().focus().unsetTextAlign().run()
  154. } else {
  155. editor.chain().focus().setTextAlign('center').run()
  156. }
  157. break;
  158. case "alignRight":
  159. if (editor.isActive({ textAlign: 'right' })) {
  160. editor.chain().focus().unsetTextAlign().run()
  161. } else {
  162. editor.chain().focus().setTextAlign('right').run()
  163. }
  164. break;
  165. default:
  166. break;
  167. }
  168. }, [])
  169. React.useEffect(() => {
  170. editor.on('selectionUpdate', ({ editor }) => {
  171. const currentFormatList: string[] = []
  172. if (editor.isActive("bold")) {
  173. currentFormatList.push("bold")
  174. }
  175. if (editor.isActive("italic")) {
  176. currentFormatList.push("italic")
  177. }
  178. if (editor.isActive("underline")) {
  179. currentFormatList.push("underline")
  180. }
  181. if (editor.isActive("highlight", { color: colorHighlightValue.toString() })) {
  182. currentFormatList.push("highlight")
  183. }
  184. if (editor.isActive("textStyle", { color: colorTextValue.toString() })) {
  185. currentFormatList.push("textStyle")
  186. }
  187. if (editor.isActive({ textAlign: 'left' })) {
  188. currentFormatList.push("alignLeft")
  189. }
  190. if (editor.isActive({ textAlign: 'center' })) {
  191. currentFormatList.push("alignCenter")
  192. }
  193. if (editor.isActive({ textAlign: 'right' })) {
  194. currentFormatList.push("alignRight")
  195. }
  196. console.log(currentFormatList)
  197. setFontStyle(() => currentFormatList)
  198. })
  199. }, [editor])
  200. return (
  201. <Grid container>
  202. <ToggleButtonGroup
  203. value={fontStyle}
  204. onChange={handleFontStyle}
  205. >
  206. <ToggleButton id="bold" value="bold" onClick={() => editor.chain().focus().toggleBold().run()}>
  207. <FormatBoldIcon />
  208. </ToggleButton>
  209. <ToggleButton id="italic" value="italic" onClick={() => editor.chain().focus().toggleItalic().run()}>
  210. <FormatItalic />
  211. </ToggleButton>
  212. <ToggleButton id="underline" value="underline" onClick={() => editor.chain().focus().toggleUnderline().run()}>
  213. <FormatUnderlined />
  214. </ToggleButton>
  215. </ToggleButtonGroup>
  216. <ToggleButtonGroup
  217. value={fontStyle}
  218. onChange={handleFontStyle}
  219. sx={{ marginLeft: 2 }}
  220. >
  221. <ToggleButton id="highlight" value="highlight" onClick={handleColorHighlightValueClick}>
  222. <BorderColorIcon sx={{ color: colorHighlightValue as string }} />
  223. </ToggleButton>
  224. {/* <ToggleButton value="" onClick={() => console.log("Expand more")}>
  225. <ExpandMoreIcon sx={{ width: 15 }} fontSize="large"/>
  226. </ToggleButton> */}
  227. <ToggleButton id="highlight" value="highlight">
  228. <MuiColorInput
  229. sx={colorInputSx}
  230. format="hex8"
  231. value={colorHighlightValue}
  232. onBlur={handleColorHighlightValueBlur}
  233. onChange={handleColorHighlightValue}
  234. onKeyDown={handleKeyDown}
  235. inputRef={colorHighlightValueInputRef}
  236. PopoverProps={{
  237. onClose: handleColorHighlightValueClose
  238. }}
  239. />
  240. </ToggleButton>
  241. </ToggleButtonGroup>
  242. <ToggleButtonGroup
  243. value={fontStyle}
  244. onChange={handleFontStyle}
  245. sx={{ marginLeft: 2 }}
  246. >
  247. <ToggleButton id="textStyle" value="textStyle" onClick={handleColorTextValueClick}>
  248. <FormatColorTextIcon sx={{ color: colorTextValue as string }} />
  249. </ToggleButton>
  250. <ToggleButton id="textStyle" value="textStyle">
  251. <MuiColorInput
  252. sx={colorInputSx}
  253. format="hex8"
  254. value={colorTextValue}
  255. onBlur={handleColorTextValueBlur}
  256. onChange={handleColorTextValue}
  257. onKeyDown={handleKeyDown}
  258. inputRef={colorTextValueInputRef}
  259. PopoverProps={{
  260. onClose: handleColorTextValueClose
  261. }}
  262. />
  263. </ToggleButton>
  264. </ToggleButtonGroup>
  265. <ToggleButtonGroup
  266. value={fontStyle}
  267. onChange={handleFontStyle}
  268. sx={{ marginLeft: 2 }}
  269. >
  270. <ToggleButton id="alignLeft" value="alignLeft" onClick={handleTextAlign}>
  271. <FormatAlignLeftIcon />
  272. </ToggleButton>
  273. <ToggleButton id="alignCenter" value="alignCenter" onClick={handleTextAlign}>
  274. <FormatAlignJustifyIcon />
  275. </ToggleButton>
  276. <ToggleButton id="alignRight" value="alignRight" onClick={handleTextAlign}>
  277. <FormatAlignRightIcon />
  278. </ToggleButton>
  279. </ToggleButtonGroup>
  280. </Grid>
  281. );
  282. };
  283. export default MailToolbar;