From 54296a80e466510b96c863439d0f930647650744 Mon Sep 17 00:00:00 2001 From: Jaleel Bennett Date: Wed, 18 Sep 2024 21:39:49 -0400 Subject: [PATCH] feat(article): implemented editable mode for action toolbar --- app/article/article-viewer.tsx | 12 +- components/article-toolbar-options.tsx | 183 ++++++++++++++++++++++--- components/article-toolbar.tsx | 2 +- components/ui/dialog.tsx | 4 +- 4 files changed, 180 insertions(+), 21 deletions(-) diff --git a/app/article/article-viewer.tsx b/app/article/article-viewer.tsx index bddc412..735b571 100644 --- a/app/article/article-viewer.tsx +++ b/app/article/article-viewer.tsx @@ -38,6 +38,7 @@ import { useZoom } from "@/stores/article-store"; import { FloatingBubbleMenu } from "@/components/bubble-menu"; import TextAlign from "@tiptap/extension-text-align"; import Color from "@tiptap/extension-color"; +import { cn } from "@/lib/utils"; // Make sure you have this utility function function literalTemplate( strings: TemplateStringsArray, @@ -118,7 +119,10 @@ export function ArticleViewer({ ], editorProps: { attributes: { - class: "prose dark:prose-dark", + class: cn( + "prose dark:prose-dark", + "focus:outline-none", // Remove focus outline + ), }, handleKeyDown: (view, event) => { // Prevent deletion of content @@ -167,7 +171,10 @@ export function ArticleViewer({ return (
Promise; isSummarizing: boolean; - summary: string | null; } export function SummaryOption({ onSummarize, isSummarizing, - summary, }: SummaryOptionProps) { const [isPending, startTransition] = useTransition(); + const summary = useSummary(); const handleSummarizeClick = () => { if (!isSummarizing && !isPending && !summary) { @@ -154,19 +188,15 @@ export function SummaryOption({ ); } -interface ZoomOptionProps { - zoom: number; - zoomIn: () => void; - zoomOut: () => void; - resetZoom: () => void; -} +export function ZoomOption() { + const zoom = useZoom(); + const zoomActions = useZoomActions(); + + const { zoomIn, zoomOut, resetZoom } = useMemo( + () => zoomActions, + [zoomActions], + ); -export function ZoomOption({ - zoom, - zoomIn, - zoomOut, - resetZoom, -}: ZoomOptionProps) { return (
@@ -193,3 +223,124 @@ export function ZoomOption({
); } + +const fontFamilies = [ + { value: "Arial", label: "Arial" }, + { value: "Helvetica", label: "Helvetica" }, + { value: "Times New Roman", label: "Times New Roman" }, + { value: "Courier", label: "Courier" }, + { value: "Verdana", label: "Verdana" }, + { value: "Georgia", label: "Georgia" }, +]; + +export function EditOption() { + const isEditable = useIsEditable(); + const toggleEditable = useToggleEditable(); + const editor = useEditor(); + + useEffect(() => { + if (isEditable) { + toast.info("Editing mode enabled"); + } + }, [isEditable]); + + const handleToggleEditable = () => { + const wasEditable = isEditable; + toggleEditable(); + if (wasEditable) { + toast.info("Editing mode disabled."); + } + }; + + const setFontFamily = (font: string) => { + if (editor) { + editor.commands.selectAll(); + editor.chain().focus().setFontFamily(font).run(); + editor.commands.setTextSelection({ from: 0, to: 0 }); + } + }; + + const clearFormatting = () => { + if (editor) { + editor + .chain() + .focus() + .unsetAllMarks() + .unsetFontFamily() + .unsetTextAlign() + .setTextSelection(editor.state.doc.content.size) + .run(); + + // Manually clear formatting for specific node types + editor.state.doc.descendants((node, pos) => { + if (node.type.name === "paragraph" || node.type.name === "heading") { + editor + .chain() + .focus() + .setNodeSelection(pos) + .unsetAllMarks() + .unsetFontFamily() + .unsetTextAlign() + .run(); + } + }); + } + }; + + const saveChanges = () => { + if (editor) { + const content = editor.getHTML(); + console.log("Saving changes:", content); + toast.success("Changes saved successfully"); + } + }; + + return ( +
+
+ Enable Editing + +
+ {isEditable && ( +
+
+ Font Family + +
+
+ + +
+
+ )} +
+ ); +} diff --git a/components/article-toolbar.tsx b/components/article-toolbar.tsx index 983cace..95c8d95 100644 --- a/components/article-toolbar.tsx +++ b/components/article-toolbar.tsx @@ -124,7 +124,7 @@ export function DynamicToolbar({ }, }, final: { - width: "320px", + width: "350px", height: "270px", borderRadius: "16px", transition: { diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index bd8d604..6d6a170 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef<