diff --git a/package-lock.json b/package-lock.json index b25ee2c1..5f3d5fcf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "leaflet.locatecontrol": "^0.79.0", "radash": "^12.1.0", "react-colorful": "^5.6.1", + "react-icons": "^5.5.0", "react-image-crop": "^10.1.8", "react-inlinesvg": "^4.2.0", "react-leaflet": "^4.2.1", @@ -6318,9 +6319,9 @@ } }, "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -11114,6 +11115,15 @@ "react": "16.8 - 19" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-image-crop": { "version": "10.1.8", "resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.8.tgz", @@ -12543,13 +12553,13 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { @@ -13241,18 +13251,18 @@ } }, "node_modules/vite": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.0.tgz", - "integrity": "sha512-9aC0n4pr6hIbvi1YOpFjwQ+QOTGssvbJKoeYkuHHGWwlXfdxQlI8L2qNMo9awEEcCPSiS+5mJZk5jH1PAqoDeQ==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", - "tinyglobby": "^0.2.12" + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" diff --git a/package.json b/package.json index 61d46b82..257e659b 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "leaflet.locatecontrol": "^0.79.0", "radash": "^12.1.0", "react-colorful": "^5.6.1", + "react-icons": "^5.5.0", "react-image-crop": "^10.1.8", "react-inlinesvg": "^4.2.0", "react-leaflet": "^4.2.1", diff --git a/src/Components/Input/RichTextEditor.tsx b/src/Components/Input/RichTextEditor.tsx index a6b6d725..58aa9548 100644 --- a/src/Components/Input/RichTextEditor.tsx +++ b/src/Components/Input/RichTextEditor.tsx @@ -1,210 +1,17 @@ -import { Color } from '@tiptap/extension-color' +import Color from '@tiptap/extension-color' import Image from '@tiptap/extension-image' import ListItem from '@tiptap/extension-list-item' import TextStyle from '@tiptap/extension-text-style' -import { EditorProvider, useCurrentEditor } from '@tiptap/react' +import Youtube from '@tiptap/extension-youtube' +import { EditorProvider } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import { useState } from 'react' import { Markdown } from 'tiptap-markdown' -import Youtube from '@tiptap/extension-youtube' + +import { TextEditorMenu } from './TextEditorMenu' import type { EditorEvents } from '@tiptap/react' -const MenuBar = () => { - const { editor } = useCurrentEditor() - - if (!editor) { - return null - } - - const [height, setHeight] = useState(480) - const [width, setWidth] = useState(640) - - const addYoutubeVideo = () => { - const url = prompt('Enter YouTube URL') - - if (url) { - editor.commands.setYoutubeVideo({ - src: url, - width: Math.max(320, width) || 640, - height: Math.max(180, height) || 480, - }) - } - } - - return ( -
-
- - - - - - - - - - - - - - - - - - - - - - -
-
- setWidth(parseInt(event.target.value))} - /> - setHeight(parseInt(event.target.value))} - /> - -
-
- ) -} - const extensions = [ Color.configure({ types: [TextStyle.name, ListItem.name] }), // TextStyle.configure({ types: [ListItem.name] }), @@ -281,16 +88,30 @@ export function RichTextEditor({ } return ( - } - extensions={extensions} - content={inputValue} - onUpdate={handleChange} - editorProps={{ - attributes: { - class: 'prose prose-sm sm:prose-base lg:prose-lg xl:prose-2xl m-5 focus:outline-none', - }, - }} - > +
+ {labelTitle ? ( + + ) : null} + +
+ + + } + extensions={extensions} + content={inputValue} + onUpdate={handleChange} + editorProps={{ + attributes: { + class: 'prose prose-sm sm:prose-base lg:prose-lg xl:prose-2xl m-5 focus:outline-none', + }, + }} + >
+
) } diff --git a/src/Components/Input/TextEditorMenu.tsx b/src/Components/Input/TextEditorMenu.tsx new file mode 100644 index 00000000..41069c53 --- /dev/null +++ b/src/Components/Input/TextEditorMenu.tsx @@ -0,0 +1,153 @@ +import BoldIcon from '@heroicons/react/24/solid/BoldIcon' +import CodeBracketIcon from '@heroicons/react/24/solid/CodeBracketIcon' +import H1Icon from '@heroicons/react/24/solid/H1Icon' +import H2Icon from '@heroicons/react/24/solid/H2Icon' +import H3Icon from '@heroicons/react/24/solid/H3Icon' +import ItalicIcon from '@heroicons/react/24/solid/ItalicIcon' +import ListBulletIcon from '@heroicons/react/24/solid/ListBulletIcon' +import NumberedListIcon from '@heroicons/react/24/solid/NumberedListIcon' +import { useCurrentEditor } from '@tiptap/react' +import { FaQuoteLeft } from 'react-icons/fa6' +import { MdUndo, MdRedo, MdHorizontalRule } from 'react-icons/md' + +export const TextEditorMenu = () => { + const { editor } = useCurrentEditor() + + if (!editor) { + return null + } + + const addYoutubeVideo = () => { + const url = prompt('Enter YouTube URL') + + if (url) { + editor.commands.setYoutubeVideo({ + src: url, + width: Math.max(320) || 640, + height: Math.max(180) || 480, + }) + } + } + + return ( + <> + + {/**
+
+ +
+
*/} + + ) +} diff --git a/src/assets/css/tiptap.css b/src/assets/css/tiptap.css index 0d9051a3..1d371e31 100644 --- a/src/assets/css/tiptap.css +++ b/src/assets/css/tiptap.css @@ -1,13 +1,3 @@ -.tiptap-toolbar { - button { - border: 2px solid black; - padding: 6px; - width: 80x; - border-radius: 8px; - background-color: #C1BCAC; - } -} - .tiptap h1, .tiptap h2, .tiptap h3,