diff --git a/apps/web/src/components/Editor.tsx b/apps/web/src/components/Editor.tsx index e4abc1c3..92046ad8 100644 --- a/apps/web/src/components/Editor.tsx +++ b/apps/web/src/components/Editor.tsx @@ -15,10 +15,15 @@ import { ReactRenderer, useEditor, } from "@tiptap/react"; -import { useEffect } from "react"; import StarterKit from "@tiptap/starter-kit"; import Suggestion from "@tiptap/suggestion"; -import { forwardRef, useImperativeHandle, useRef, useState } from "react"; +import { + forwardRef, + useEffect, + useImperativeHandle, + useRef, + useState, +} from "react"; import { HiH1, HiH2, @@ -373,7 +378,7 @@ export default function Editor({ {!readOnly && editor && } ); diff --git a/apps/web/src/views/card/components/ChecklistItemRow.tsx b/apps/web/src/views/card/components/ChecklistItemRow.tsx index e29132a0..0ee7da32 100644 --- a/apps/web/src/views/card/components/ChecklistItemRow.tsx +++ b/apps/web/src/views/card/components/ChecklistItemRow.tsx @@ -91,10 +91,20 @@ export default function ChecklistItemRow({ const [title, setTitle] = useState(item.title); const [completed, setCompleted] = useState(item.completed); + // Only resync from props when switching items to avoid clobbering edits useEffect(() => { setTitle(item.title); setCompleted(item.completed); - }, [item.publicId, item.title, item.completed]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [item.publicId]); + + const sanitizeHtmlToPlainText = (html: string): string => + html + .replace(/(\n)?/gi, "\n") + .replace(/
<\/div>/gi, "") + .replace(/<[^>]*>/g, "") + .replace(/ /g, " ") + .trim(); const handleToggleCompleted = () => { setCompleted((prev) => !prev); @@ -104,12 +114,13 @@ export default function ChecklistItemRow({ }); }; - const commitTitle = async () => { - const trimmed = title.trim(); - if (!trimmed || trimmed === item.title) return; + const commitTitle = (rawHtml: string) => { + const plain = sanitizeHtmlToPlainText(rawHtml); + if (!plain || plain === item.title) return; + setTitle(plain); updateItem.mutate({ checklistItemPublicId: item.publicId, - title: trimmed, + title: plain, }); }; @@ -118,40 +129,26 @@ export default function ChecklistItemRow({ }; return ( -
-