From d0357fb7d43eb50b0f2a9c8b939aa713e84a6428 Mon Sep 17 00:00:00 2001 From: Parshva Bhadra Date: Mon, 30 Sep 2024 11:38:23 +0000 Subject: [PATCH 1/4] Refactor: Add text editor component --- frontend/package-lock.json | 143 +++++++-- frontend/package.json | 3 + frontend/src/App.js | 2 + frontend/src/components/textEditor/Editor.jsx | 19 ++ .../src/components/textEditor/TextEditor.jsx | 263 +++------------- .../textEditor/TextEditor.module.css | 103 +++++++ .../src/components/textEditor/Toolbar.jsx | 280 ++++++++++++++++++ frontend/yarn.lock | 65 ++-- 8 files changed, 604 insertions(+), 274 deletions(-) create mode 100644 frontend/src/components/textEditor/Editor.jsx create mode 100644 frontend/src/components/textEditor/TextEditor.module.css create mode 100644 frontend/src/components/textEditor/Toolbar.jsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 139fb187..c5920883 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,7 @@ "@emotion/styled": "^11.13.0", "@nextui-org/button": "^2.0.38", "@nextui-org/navbar": "^2.0.37", - "@nextui-org/react": "^2.4.8", + "@nextui-org/react": "latest", "@nextui-org/system": "^2.2.6", "@nextui-org/table": "^2.0.40", "@nextui-org/theme": "^2.2.11", @@ -21,11 +21,17 @@ "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", + "@reduxjs/toolkit": "^2.2.7", + "@remixicon/react": "^4.2.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@tiptap/core": "^2.7.4", "@tiptap/extension-color": "^2.7.4", + "@tiptap/extension-heading": "^2.7.4", "@tiptap/extension-text-style": "^2.7.4", + "@tiptap/extension-underline": "^2.7.4", + "@tiptap/pm": "^2.7.4", "@tiptap/react": "^2.0.0", "@tiptap/starter-kit": "^2.0.0", "axios": "^1.7.7", @@ -35,9 +41,10 @@ "framer-motion": "^11.8.0", "lucide-react": "^0.446.0", "next": "^14.2.13", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "react": "^17.x || ^18.x", + "react-dom": "^17.x || ^18.x", "react-flow-renderer": "^10.3.17", + "react-redux": "^9.1.2", "reactflow": "11.11.4", "sass": "^1.79.3", "tailwind-merge": "^2.5.2", @@ -46,9 +53,9 @@ "zustand": "^5.0.0-rc.2" }, "devDependencies": { - "autoprefixer": "^10.4.20", - "postcss": "^8.4.47", - "tailwindcss": "^3.4.13", + "autoprefixer": "^10.x", + "postcss": "^8.x", + "tailwindcss": "^3.x", "typescript": "5.6.2" } }, @@ -5009,12 +5016,45 @@ } } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz", + "integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==", + "license": "MIT", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@remirror/core-constants": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", "license": "MIT" }, + "node_modules/@remixicon/react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@remixicon/react/-/react-4.2.0.tgz", + "integrity": "sha512-eGhKpZ88OU0qkcY9pJu6khBmItDV82nU130E6C68yc+FbljueHlUYy/4CrJsmf860RIDMay2Rpzl27OSJ81miw==", + "license": "Apache-2.0", + "peerDependencies": { + "react": ">=18.2.0" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -5129,9 +5169,9 @@ } }, "node_modules/@tiptap/core": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.7.2.tgz", - "integrity": "sha512-rGAH90LPMR5OIG7vuTDRw8WxDYxPXSxuGtu++mxPF+Bv7V2ijPOy3P1oyV1G3KGoS0pPiNugLh+tVLsElcx/9Q==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.7.4.tgz", + "integrity": "sha512-1VTQdNQChgxdVC8+b8QEW6cUxPSD9EDTzg9YRSLWtTtUDQ09sRSVs7eHIn1LcRHVs6PwcAsNgKE4FSjBw0sRlg==", "license": "MIT", "funding": { "type": "github", @@ -5228,6 +5268,7 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/@tiptap/extension-color/-/extension-color-2.7.4.tgz", "integrity": "sha512-UI6RvjD0vBA2KyQ8E4gQHqCRimUw8M/LpnpumcgFpXCrZTO4ltADuR+7cHhXvNfcVxY17/bPY/WF3yTsR0dqiQ==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5309,9 +5350,9 @@ } }, "node_modules/@tiptap/extension-heading": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.2.tgz", - "integrity": "sha512-i26Skx/womkqkG3aQW9PPh8UUS5znAWxNb5SzxBowJoISq1thOUsdmb16PdL9tljsO8vKy4sAPOx3hT5oVN7uw==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.4.tgz", + "integrity": "sha512-ZLFHhFvmDD6YKPf4wftZd4wtT510yHjzG90A14wyKCpm0Bq9wOYzx4Q+owvlp5vMwenqHuq3KGz4Sf3w6N5gkw==", "license": "MIT", "funding": { "type": "github", @@ -5431,6 +5472,20 @@ "version": "2.7.4", "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.7.4.tgz", "integrity": "sha512-KQ50wDxwH0tFs+9vWP56aaJVyCRl93e3B/cIVJtvTV1HANtkjxFAdrvW1HOaUk9aVBdeLRFbz+YIzf/LxNZ2Wg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.7.0" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.7.4.tgz", + "integrity": "sha512-1WT2ZHjBoyW6MzKrLC1v2KJszuozh6jzIbcabslRRNaEJFfsjIFgfU3TBpaXF+JKEBCi3h1JpWMgmtnr0puFVA==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5440,9 +5495,9 @@ } }, "node_modules/@tiptap/pm": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.2.tgz", - "integrity": "sha512-RiRPlwpuE6IHDJytE0tglbFlWELOaqeyGRGv25wBTjzV1plnqC5B3U65XY/8kKuuLjdd3NpRfR68DXBafusSBg==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.4.tgz", + "integrity": "sha512-YXjgPLN6/msTkKakuzgBm6Dd/Li3ORtysSki3fHnOFcy8R4c5JZLkYECQk6aJHsxvl/vGvNgaJy5yCDbhnaTAg==", "license": "MIT", "dependencies": { "prosemirror-changeset": "^2.2.1", @@ -7655,12 +7710,10 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", "license": "MIT", - "optional": true, - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -9113,6 +9166,35 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/react-redux": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", + "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.3", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25", + "react": "^18.0", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", + "license": "MIT" + }, "node_modules/react-remove-scroll": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", @@ -9248,6 +9330,21 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -9266,6 +9363,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", diff --git a/frontend/package.json b/frontend/package.json index 68325e8e..3dd1ece9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,8 +21,11 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "@tiptap/core": "^2.7.4", "@tiptap/extension-color": "^2.7.4", "@tiptap/extension-text-style": "^2.7.4", + "@tiptap/extension-underline": "^2.7.4", + "@tiptap/pm": "^2.7.4", "@tiptap/react": "^2.0.0", "@tiptap/starter-kit": "^2.0.0", "axios": "^1.7.7", diff --git a/frontend/src/App.js b/frontend/src/App.js index 58823905..30c8d623 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,10 +1,12 @@ import { Provider } from 'react-redux'; import store from './store/store'; +import Editor from './components/textEditor/Editor'; function App() { return ( {/* ... existing components ... */} + ); } diff --git a/frontend/src/components/textEditor/Editor.jsx b/frontend/src/components/textEditor/Editor.jsx new file mode 100644 index 00000000..2bb16b8d --- /dev/null +++ b/frontend/src/components/textEditor/Editor.jsx @@ -0,0 +1,19 @@ +'use client' + +import React, { useState } from 'react' +import TextEditor from './TextEditor' + +const Editor = () => { + const [content, setContent] = useState('') + const handleContentChange = (input) => { + setContent(input) + } + return ( + + ) +} + +export default Editor \ No newline at end of file diff --git a/frontend/src/components/textEditor/TextEditor.jsx b/frontend/src/components/textEditor/TextEditor.jsx index 2a015672..98d62de7 100644 --- a/frontend/src/components/textEditor/TextEditor.jsx +++ b/frontend/src/components/textEditor/TextEditor.jsx @@ -1,233 +1,48 @@ +"use client"; + +import { useEditor, EditorContent } from "@tiptap/react"; +import StarterKit from "@tiptap/starter-kit"; +import Toolbar from "./Toolbar"; +import Underline from "@tiptap/extension-underline"; +import styles from "./TextEditor.module.css"; import { Color } from '@tiptap/extension-color' -import ListItem from '@tiptap/extension-list-item' -import TextStyle from '@tiptap/extension-text-style' -import { EditorProvider, useCurrentEditor } from '@tiptap/react' -import StarterKit from '@tiptap/starter-kit' -import React from 'react' +import TextStyle from "@tiptap/extension-text-style"; -const MenuBar = () => { - const { editor } = useCurrentEditor() - if (!editor) { - return null - } +const TextEditor = ({ content, onChange = () => { } }) => { - return ( -
-
- - - - - - - - - - - - - - - - - - - - - - -
-
- ) -} + const handleChange = (newContent) => { + onChange(newContent); + }; -const extensions = [ - Color.configure({ types: [TextStyle.name, ListItem.name] }), - TextStyle.configure({ types: [ListItem.name] }), - StarterKit.configure({ - bulletList: { - keepMarks: true, - keepAttributes: false, // TODO : Making this as `false` becase marks are not preserved when I try to preserve attrs, awaiting a bit of help + const editor = useEditor({ + extensions: [ + StarterKit, + Underline, + TextStyle, + Color + ], + content: content, + editorProps: { + attributes: { + class: + "flex flex-col px-4 py-3 justify-start border-b border-r border-l border-gray-700 items-start w-full gap-3 font-medium pt-4 rounded-bl-md rounded-br-md outline-none", + }, }, - orderedList: { - keepMarks: true, - keepAttributes: false, // TODO : Making this as `false` becase marks are not preserved when I try to preserve attrs, awaiting a bit of help + onUpdate: ({ editor }) => { + handleChange(editor.getHTML()); }, - }), -] + immediatelyRender: false, + }); -const content = ` -

- Hi there, -

-

- this is a basic example of Tiptap. Sure, there are all kind of basic text styles you’d probably expect from a text editor. But wait until you see the lists: -

- -

- Isn’t that great? And all of that is editable. But wait, there’s more. Let’s try a code block: -

-
body {
-  display: none;
-}
-

- I know, I know, this is impressive. It’s only the tip of the iceberg though. Give it a try and click a little bit around. Don’t forget to check the other examples too. -

-
- Wow, that’s amazing. Good work, boy! 👏 -
- — Mom -
-` - -export default () => { return ( - } extensions={extensions} content={content}> - ) -} \ No newline at end of file +
+ +
+ +
+
+ ); +}; + +export default TextEditor; \ No newline at end of file diff --git a/frontend/src/components/textEditor/TextEditor.module.css b/frontend/src/components/textEditor/TextEditor.module.css new file mode 100644 index 00000000..90d04ad7 --- /dev/null +++ b/frontend/src/components/textEditor/TextEditor.module.css @@ -0,0 +1,103 @@ +.tiptap { + background: transparent; + border-radius: 0 0 5px 5px; + min-height: 100px; +} + +.tiptap>*+* { + margin-top: 0; +} + +.tiptap ul { + padding: 0 1rem; + list-style: disc !important; +} + +.tiptap ol { + padding: 0 1rem; + list-style: decimal !important; +} + +.tiptap h1, +.tiptap h2, +.tiptap h3, +.tiptap h4, +.tiptap h5, +.tiptap h6 { + font-size: 2rem; + line-height: 1.1; + text-wrap: pretty; + margin-bottom: 1rem; +} + +.tiptap h1, +.tiptap h2 { + margin-bottom: 1.5rem; +} + +.tiptap h1 { + font-size: 1.4rem; +} + +.tiptap h2 { + font-size: 1.2rem; +} + +.tiptap h3 { + font-size: 1.1rem; +} + +.tiptap h4, +.tiptap h5, +.tiptap h6 { + font-size: 1rem; +} + +.tiptap h4 { + margin-bottom: 1.33rem; +} + +.tiptap h5 { + margin-bottom: 1.67rem; +} + +.tiptap h6 { + margin-bottom: 2.33rem; +} + +.tiptap code { + background-color: rgba(88, 5, 255, .05) !important; + border-radius: 0.4rem !important; + color: #000000; + font-size: 0.85rem !important; + padding: 0.25em 0.3em + ; +} + +.tiptap pre { + background: #0d0d0d; + color: #fff; + font-family: 'JetBrainsMono', monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + width: 100%; +} + +.tiptap code { + color: inherit; + padding: 0; + background: none; + font-size: 0.8rem; +} + +.tiptap blockquote { + padding-left: 1rem; + border-left: 3px solid #999999; +} + +.tiptap hr { + border: none; + border-top: 1px solid #999999; + margin: 2rem 0; + width: 100% +} \ No newline at end of file diff --git a/frontend/src/components/textEditor/Toolbar.jsx b/frontend/src/components/textEditor/Toolbar.jsx new file mode 100644 index 00000000..7ffaf3ac --- /dev/null +++ b/frontend/src/components/textEditor/Toolbar.jsx @@ -0,0 +1,280 @@ +"use client"; + +import React from "react"; +import { + Bold, + Strikethrough, + Italic, + List, + ListOrdered, + Underline, + Quote, + Undo, + Redo, + Code, +} from "lucide-react"; + +const Toolbar = ({ editor, content }) => { + if (!editor) { + return null; + } + return ( +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ ); +}; + +export default Toolbar; \ No newline at end of file diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 4868963d..350f3c9f 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -382,7 +382,7 @@ "@next/swc-darwin-arm64@14.2.13": version "14.2.13" - resolved "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.13.tgz" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.13.tgz#76f08d78360c4d27d444df7f35a56f59a48f4808" integrity sha512-IkAmQEa2Htq+wHACBxOsslt+jMoV3msvxCn0WFSfJSkv/scy+i/EukBKNad36grRxywaXUYJc9mxEGkeIs8Bzg== "@next/swc-darwin-x64@14.2.13": @@ -402,12 +402,12 @@ "@next/swc-linux-x64-gnu@14.2.13": version "14.2.13" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.13.tgz#8cb8480dfeee512648e4e08c2095aac0461b876f" + resolved "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.13.tgz" integrity sha512-aVc7m4YL7ViiRv7SOXK3RplXzOEe/qQzRA5R2vpXboHABs3w8vtFslGTz+5tKiQzWUmTmBNVW0UQdhkKRORmGA== "@next/swc-linux-x64-musl@14.2.13": version "14.2.13" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.13.tgz#df5ca922fa1e1ee81b15a06a2d3d3ace0efd2bd7" + resolved "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.13.tgz" integrity sha512-4wWY7/OsSaJOOKvMsu1Teylku7vKyTuocvDLTZQq0TYv9OjiYYWt63PiE1nTuZnqQ4RPvME7Xai+9enoiN0Wrg== "@next/swc-win32-arm64-msvc@14.2.13": @@ -901,7 +901,7 @@ "@nextui-org/react@latest": version "2.4.8" - resolved "https://registry.yarnpkg.com/@nextui-org/react/-/react-2.4.8.tgz#2a430cca1d2e1dc812a55ca763d61e2ba5b0e195" + resolved "https://registry.npmjs.org/@nextui-org/react/-/react-2.4.8.tgz" integrity sha512-ZwXg6As3A+Gs+Jyc42t4MHNupHEsh9YmEaypE20ikqIPTCLQnrGQ/RWOGwzZ2a9kZWbZ89a/3rJwZMRKdcemxg== dependencies: "@nextui-org/accordion" "2.0.40" @@ -2798,7 +2798,7 @@ "@reduxjs/toolkit@^2.2.7": version "2.2.7" - resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.2.7.tgz#199e3d10ccb39267cb5aee92c0262fd9da7fdfb2" + resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz" integrity sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g== dependencies: immer "^10.0.3" @@ -2813,7 +2813,7 @@ "@remixicon/react@^4.2.0": version "4.2.0" - resolved "https://registry.yarnpkg.com/@remixicon/react/-/react-4.2.0.tgz#9093ea394e288ee9a88d0613bd38739c728f02ac" + resolved "https://registry.npmjs.org/@remixicon/react/-/react-4.2.0.tgz" integrity sha512-eGhKpZ88OU0qkcY9pJu6khBmItDV82nU130E6C68yc+FbljueHlUYy/4CrJsmf860RIDMay2Rpzl27OSJ81miw== "@sinclair/typebox@^0.27.8": @@ -2879,10 +2879,10 @@ dependencies: "@babel/runtime" "^7.12.5" -"@tiptap/core@^2.7.2": - version "2.7.2" - resolved "https://registry.npmjs.org/@tiptap/core/-/core-2.7.2.tgz" - integrity sha512-rGAH90LPMR5OIG7vuTDRw8WxDYxPXSxuGtu++mxPF+Bv7V2ijPOy3P1oyV1G3KGoS0pPiNugLh+tVLsElcx/9Q== +"@tiptap/core@^2.7.2", "@tiptap/core@^2.7.4": + version "2.7.4" + resolved "https://registry.npmjs.org/@tiptap/core/-/core-2.7.4.tgz" + integrity sha512-1VTQdNQChgxdVC8+b8QEW6cUxPSD9EDTzg9YRSLWtTtUDQ09sRSVs7eHIn1LcRHVs6PwcAsNgKE4FSjBw0sRlg== "@tiptap/extension-blockquote@^2.7.2": version "2.7.2" @@ -2948,10 +2948,10 @@ resolved "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.7.2.tgz" integrity sha512-44dZMi0N1fNhQ8i7bFnj4JYfhn4B6+vHuEueJPZS1iOsJc715m3e8ZSfDBk7VXCGKrksCxPMJ7guO0Y1PVryow== -"@tiptap/extension-heading@^2.7.2": - version "2.7.2" - resolved "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.2.tgz" - integrity sha512-i26Skx/womkqkG3aQW9PPh8UUS5znAWxNb5SzxBowJoISq1thOUsdmb16PdL9tljsO8vKy4sAPOx3hT5oVN7uw== +"@tiptap/extension-heading@^2.7.2", "@tiptap/extension-heading@^2.7.4": + version "2.7.4" + resolved "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.7.4.tgz" + integrity sha512-ZLFHhFvmDD6YKPf4wftZd4wtT510yHjzG90A14wyKCpm0Bq9wOYzx4Q+owvlp5vMwenqHuq3KGz4Sf3w6N5gkw== "@tiptap/extension-history@^2.7.2": version "2.7.2" @@ -2998,10 +2998,15 @@ resolved "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.7.2.tgz" integrity sha512-VjzG7W53Lx2q8XV0rUHetVTQWDK28XTCTW3IzxYxHp2joB/k9q3xgE/5Vs+7DOLSHIKq2BmwQNyaE+XjUF5iYQ== -"@tiptap/pm@^2.7.2": - version "2.7.2" - resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.2.tgz" - integrity sha512-RiRPlwpuE6IHDJytE0tglbFlWELOaqeyGRGv25wBTjzV1plnqC5B3U65XY/8kKuuLjdd3NpRfR68DXBafusSBg== +"@tiptap/extension-underline@^2.7.4": + version "2.7.4" + resolved "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.7.4.tgz" + integrity sha512-1WT2ZHjBoyW6MzKrLC1v2KJszuozh6jzIbcabslRRNaEJFfsjIFgfU3TBpaXF+JKEBCi3h1JpWMgmtnr0puFVA== + +"@tiptap/pm@^2.7.2", "@tiptap/pm@^2.7.4": + version "2.7.4" + resolved "https://registry.npmjs.org/@tiptap/pm/-/pm-2.7.4.tgz" + integrity sha512-YXjgPLN6/msTkKakuzgBm6Dd/Li3ORtysSki3fHnOFcy8R4c5JZLkYECQk6aJHsxvl/vGvNgaJy5yCDbhnaTAg== dependencies: prosemirror-changeset "^2.2.1" prosemirror-collab "^1.3.1" @@ -3369,7 +3374,7 @@ "@types/use-sync-external-store@^0.0.3": version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" + resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz" integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== "@types/use-sync-external-store@^0.0.6": @@ -3480,7 +3485,7 @@ asynckit@^0.4.0: autoprefixer@^10.x: version "10.4.20" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" + resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz" integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== dependencies: browserslist "^4.23.3" @@ -4100,7 +4105,7 @@ framer-motion@^11.8.0: fsevents@~2.3.2: version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.2: @@ -4227,7 +4232,7 @@ hoist-non-react-statics@^3.3.1: immer@^10.0.3: version "10.1.1" - resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.1.tgz#206f344ea372d8ea176891545ee53ccc062db7bc" + resolved "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz" integrity sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw== immutable@^4.0.0: @@ -4876,7 +4881,7 @@ postcss@8.4.31: postcss@^8.4.23, postcss@^8.x: version "8.4.47" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz" integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== dependencies: nanoid "^3.3.7" @@ -5071,7 +5076,7 @@ queue-microtask@^1.2.2: "react-dom@^17.x || ^18.x": version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" @@ -5108,7 +5113,7 @@ react-is@^18.0.0: react-redux@^9.1.2: version "9.1.2" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.2.tgz#deba38c64c3403e9abd0c3fbeab69ffd9d8a7e4b" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz" integrity sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w== dependencies: "@types/use-sync-external-store" "^0.0.3" @@ -5164,7 +5169,7 @@ react-textarea-autosize@^8.5.3: "react@^17.x || ^18.x": version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" @@ -5210,12 +5215,12 @@ redent@^3.0.0: redux-thunk@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3" + resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz" integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== redux@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" + resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== regenerator-runtime@^0.14.0: @@ -5235,7 +5240,7 @@ regexp.prototype.flags@^1.5.1: reselect@^5.1.0: version "5.1.1" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e" + resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz" integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w== resolve-from@^4.0.0: @@ -5505,7 +5510,7 @@ tailwindcss-animate@^1.0.7: tailwindcss@^3.x: version "3.4.13" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.13.tgz#3d11e5510660f99df4f1bfb2d78434666cb8f831" + resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz" integrity sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw== dependencies: "@alloc/quick-lru" "^5.2.0" From 6697e76319890e6a17e22ef5208fbb88e1ddd4a0 Mon Sep 17 00:00:00 2001 From: Parshva Bhadra Date: Mon, 30 Sep 2024 12:07:08 +0000 Subject: [PATCH 2/4] Refactor: Update text editor component with new features and styling --- .../src/components/textEditor/TextEditor.jsx | 19 ++++++++++++++----- .../textEditor/TextEditor.module.css | 4 +++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/textEditor/TextEditor.jsx b/frontend/src/components/textEditor/TextEditor.jsx index 98d62de7..1993c0f9 100644 --- a/frontend/src/components/textEditor/TextEditor.jsx +++ b/frontend/src/components/textEditor/TextEditor.jsx @@ -7,7 +7,7 @@ import Underline from "@tiptap/extension-underline"; import styles from "./TextEditor.module.css"; import { Color } from '@tiptap/extension-color' import TextStyle from "@tiptap/extension-text-style"; - +import ListItem from '@tiptap/extension-list-item' const TextEditor = ({ content, onChange = () => { } }) => { @@ -17,10 +17,19 @@ const TextEditor = ({ content, onChange = () => { } }) => { const editor = useEditor({ extensions: [ - StarterKit, + Color.configure({ types: [TextStyle.name, ListItem.name] }), + TextStyle.configure({ types: [ListItem.name] }), + StarterKit.configure({ + bulletList: { + keepMarks: true, + keepAttributes: false, // TODO : Making this as `false` becase marks are not preserved when I try to preserve attrs, awaiting a bit of help + }, + orderedList: { + keepMarks: true, + keepAttributes: false, // TODO : Making this as `false` becase marks are not preserved when I try to preserve attrs, awaiting a bit of help + }, + }), Underline, - TextStyle, - Color ], content: content, editorProps: { @@ -32,7 +41,7 @@ const TextEditor = ({ content, onChange = () => { } }) => { onUpdate: ({ editor }) => { handleChange(editor.getHTML()); }, - immediatelyRender: false, + immediatelyRender: false, }); return ( diff --git a/frontend/src/components/textEditor/TextEditor.module.css b/frontend/src/components/textEditor/TextEditor.module.css index 90d04ad7..3724ef3c 100644 --- a/frontend/src/components/textEditor/TextEditor.module.css +++ b/frontend/src/components/textEditor/TextEditor.module.css @@ -2,6 +2,7 @@ background: transparent; border-radius: 0 0 5px 5px; min-height: 100px; + caret-color: #958DF1; } .tiptap>*+* { @@ -100,4 +101,5 @@ border-top: 1px solid #999999; margin: 2rem 0; width: 100% -} \ No newline at end of file +} + From ab5607b14d794e362a954ecc8950cd29c1ee1bb0 Mon Sep 17 00:00:00 2001 From: Parshva Bhadra Date: Mon, 30 Sep 2024 12:25:42 +0000 Subject: [PATCH 3/4] Refactor: Update padding in TextEditor module CSS --- frontend/src/components/textEditor/TextEditor.module.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/components/textEditor/TextEditor.module.css b/frontend/src/components/textEditor/TextEditor.module.css index 3724ef3c..359fd0cb 100644 --- a/frontend/src/components/textEditor/TextEditor.module.css +++ b/frontend/src/components/textEditor/TextEditor.module.css @@ -71,8 +71,7 @@ border-radius: 0.4rem !important; color: #000000; font-size: 0.85rem !important; - padding: 0.25em 0.3em - ; + padding: 0.25em 0.3em; } .tiptap pre { From fa015d8f92a32167ccfa005d432e71d2e163ec65 Mon Sep 17 00:00:00 2001 From: Parshva Bhadra Date: Mon, 30 Sep 2024 12:43:12 +0000 Subject: [PATCH 4/4] Refactor: Update Toolbar component with new features and styling --- .../src/components/textEditor/Toolbar.jsx | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/frontend/src/components/textEditor/Toolbar.jsx b/frontend/src/components/textEditor/Toolbar.jsx index 7ffaf3ac..31484841 100644 --- a/frontend/src/components/textEditor/Toolbar.jsx +++ b/frontend/src/components/textEditor/Toolbar.jsx @@ -14,7 +14,7 @@ import { Code, } from "lucide-react"; -const Toolbar = ({ editor, content }) => { +const Toolbar = ({ editor }) => { if (!editor) { return null; } @@ -38,7 +38,7 @@ const Toolbar = ({ editor, content }) => { className={ editor.isActive("bold") ? "bg-purple-600 text-white px-2 py-1 rounded-lg" - : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out" + : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" } > @@ -57,7 +57,7 @@ const Toolbar = ({ editor, content }) => { className={ editor.isActive("italic") ? "bg-purple-600 text-white px-2 py-1 rounded-lg" - : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out" + : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" } > @@ -76,7 +76,7 @@ const Toolbar = ({ editor, content }) => { className={ editor.isActive("underline") ? "bg-purple-600 text-white px-2 py-1 rounded-lg" - : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out" + : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" } > @@ -95,11 +95,30 @@ const Toolbar = ({ editor, content }) => { className={ editor.isActive("strike") ? "bg-purple-600 text-white px-2 py-1 rounded-lg" - : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out" + : "bg-gray-300 px-2 py-1 rounded-lg hover:bg-gray-400 transition duration-100 ease-in-out disabled:opacity-50 disabled:cursor-not-allowed" } > + - - - + +