mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
Revert "Improve quick note editor interactions & fix filter chips responsiveness" (#987)
This commit is contained in:
parent
7f6b28ab83
commit
ed809b26f9
7 changed files with 130 additions and 225 deletions
|
|
@ -20,9 +20,11 @@ export function NoteContent({
|
|||
const [content, setContent] = useState(initialContent ?? "")
|
||||
const [seededContent] = useState(initialContent || undefined)
|
||||
|
||||
const handleSubmit = (submittedContent = content) => {
|
||||
if (submittedContent.trim() && !isSubmitting && onSubmit) {
|
||||
onSubmit(submittedContent)
|
||||
const canSubmit = content.trim().length > 0 && !isSubmitting
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (canSubmit && onSubmit) {
|
||||
onSubmit(content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export interface TextEditorProps {
|
|||
hasUnsavedChanges: boolean
|
||||
isSaving: boolean
|
||||
onContentChange: (content: string) => void
|
||||
onSave: (content?: string) => void
|
||||
onSave: () => void
|
||||
onReset: () => void
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ export function TextEditorContent({
|
|||
<Button
|
||||
variant="insideOut"
|
||||
size="sm"
|
||||
onClick={() => onSave()}
|
||||
onClick={onSave}
|
||||
disabled={isSaving}
|
||||
className="hover:text-white rounded-full px-4"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -236,20 +236,15 @@ export function DocumentModal({
|
|||
draftContentString !== initialEditorString &&
|
||||
draftContentString !== lastSavedContent
|
||||
|
||||
const handleSave = useCallback(
|
||||
(submittedContent?: string) => {
|
||||
if (!_document?.id) return
|
||||
const content = submittedContent ?? draftContentString
|
||||
updateMutation.mutate(
|
||||
{ documentId: _document.id, content },
|
||||
{
|
||||
onSuccess: (_data, variables) =>
|
||||
setLastSavedContent(variables.content),
|
||||
},
|
||||
)
|
||||
},
|
||||
[_document?.id, draftContentString, updateMutation],
|
||||
)
|
||||
const handleSave = useCallback(() => {
|
||||
if (!_document?.id) return
|
||||
updateMutation.mutate(
|
||||
{ documentId: _document.id, content: draftContentString },
|
||||
{
|
||||
onSuccess: (_data, variables) => setLastSavedContent(variables.content),
|
||||
},
|
||||
)
|
||||
}, [_document?.id, draftContentString, updateMutation])
|
||||
|
||||
const textEditorProps = useMemo(
|
||||
() => ({
|
||||
|
|
|
|||
|
|
@ -52,15 +52,12 @@ export function FullscreenNoteModal({
|
|||
""
|
||||
const userName = displayName ? `${displayName.split(" ")[0]}'s` : "My"
|
||||
|
||||
const handleSave = useCallback(
|
||||
(submittedContent?: string) => {
|
||||
const currentContent = submittedContent ?? contentRef.current
|
||||
if (currentContent.trim() && !isSaving) {
|
||||
onSave(currentContent)
|
||||
}
|
||||
},
|
||||
[isSaving, onSave],
|
||||
)
|
||||
const handleSave = useCallback(() => {
|
||||
const currentContent = contentRef.current
|
||||
if (currentContent.trim() && !isSaving) {
|
||||
onSave(currentContent)
|
||||
}
|
||||
}, [isSaving, onSave])
|
||||
|
||||
const handleContentChange = useCallback(
|
||||
(newContent: string) => {
|
||||
|
|
@ -168,7 +165,7 @@ export function FullscreenNoteModal({
|
|||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSave()}
|
||||
onClick={handleSave}
|
||||
disabled={!canSave}
|
||||
className={cn(
|
||||
"bg-[#1B1F24] rounded-[8px] px-4 py-2.5 flex items-center justify-center gap-1.5 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
|
||||
|
|
|
|||
|
|
@ -542,13 +542,13 @@ export function MemoriesGrid({
|
|||
{!isEmpty && !isSelectionMode && (
|
||||
<div
|
||||
id="filter-pills"
|
||||
className="mb-3 flex flex-col gap-2 pr-2 sm:flex-row sm:items-center sm:justify-between sm:gap-4"
|
||||
className="flex items-center justify-between gap-4 mb-3 pr-2"
|
||||
>
|
||||
<div className="scrollbar-none -mx-1 flex items-center gap-1.5 overflow-x-auto px-1 pb-1 sm:mx-0 sm:flex-wrap sm:overflow-visible sm:px-0 sm:pb-0">
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
<Button
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"h-auto shrink-0 rounded-full border border-[#161F2C] bg-[#0D121A] px-2.5 py-1 text-xs hover:bg-[#00173C] hover:border-[#2261CA33]",
|
||||
"rounded-full border border-[#161F2C] bg-[#0D121A] px-2.5 py-1 text-xs h-auto hover:bg-[#00173C] hover:border-[#2261CA33]",
|
||||
selectedCategories.length === 0 &&
|
||||
"bg-[#00173C] border-[#2261CA33]",
|
||||
)}
|
||||
|
|
@ -566,7 +566,7 @@ export function MemoriesGrid({
|
|||
key={facet.category}
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"h-auto shrink-0 rounded-full border border-[#161F2C] bg-[#0D121A] px-2.5 py-1 text-xs hover:bg-[#00173C] hover:border-[#2261CA33]",
|
||||
"rounded-full border border-[#161F2C] bg-[#0D121A] px-2.5 py-1 text-xs h-auto hover:bg-[#00173C] hover:border-[#2261CA33]",
|
||||
selectedCategoriesSet.has(facet.category) &&
|
||||
"bg-[#00173C] border-[#2261CA33]",
|
||||
)}
|
||||
|
|
@ -577,7 +577,7 @@ export function MemoriesGrid({
|
|||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center justify-end gap-2">
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{/* View mode toggle — segmented control */}
|
||||
<div
|
||||
role="tablist"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
"use client"
|
||||
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useRef, useCallback } from "react"
|
||||
import { cn } from "@lib/utils"
|
||||
import { dmSansClassName } from "@/lib/fonts"
|
||||
import { Maximize2, Plus, Loader2 } from "lucide-react"
|
||||
import { useProject } from "@/stores"
|
||||
import { useQuickNoteDraft } from "@/stores/quick-note-draft"
|
||||
import { TextEditor } from "./text-editor"
|
||||
|
||||
interface QuickNoteCardProps {
|
||||
onSave: (content: string) => void
|
||||
|
|
@ -19,22 +18,27 @@ export function QuickNoteCard({
|
|||
onMaximize,
|
||||
isSaving = false,
|
||||
}: QuickNoteCardProps) {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||
const { selectedProject } = useProject()
|
||||
const { draft, setDraft } = useQuickNoteDraft(selectedProject)
|
||||
|
||||
const handleContentChange = useCallback(
|
||||
(content: string) => setDraft(content),
|
||||
const handleChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setDraft(e.target.value)
|
||||
},
|
||||
[setDraft],
|
||||
)
|
||||
|
||||
const handleEditorSubmit = useCallback(
|
||||
(content: string) => {
|
||||
if (content.trim() && !isSaving) {
|
||||
onSave(content)
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
||||
e.preventDefault()
|
||||
if (draft.trim() && !isSaving) {
|
||||
onSave(draft)
|
||||
}
|
||||
}
|
||||
},
|
||||
[isSaving, onSave],
|
||||
[draft, isSaving, onSave],
|
||||
)
|
||||
|
||||
const handleSaveClick = useCallback(() => {
|
||||
|
|
@ -47,172 +51,109 @@ export function QuickNoteCard({
|
|||
onMaximize(draft)
|
||||
}, [draft, onMaximize])
|
||||
|
||||
const handleBlurCapture = useCallback(
|
||||
(e: React.FocusEvent<HTMLDivElement>) => {
|
||||
if (e.currentTarget.contains(e.relatedTarget as Node | null)) return
|
||||
setIsExpanded(false)
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
const handleBackdropPointerDown = useCallback(() => {
|
||||
const activeElement = document.activeElement
|
||||
if (activeElement instanceof HTMLElement) {
|
||||
activeElement.blur()
|
||||
}
|
||||
setIsExpanded(false)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isExpanded) return
|
||||
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key !== "Escape") return
|
||||
const activeElement = document.activeElement
|
||||
if (activeElement instanceof HTMLElement) {
|
||||
activeElement.blur()
|
||||
}
|
||||
setIsExpanded(false)
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown)
|
||||
return () => window.removeEventListener("keydown", handleKeyDown)
|
||||
}, [isExpanded])
|
||||
|
||||
const canSave = draft.trim().length > 0 && !isSaving
|
||||
const hasDraft = draft.trim().length > 0
|
||||
const editorHeight = isExpanded
|
||||
? "min-h-[min(58dvh,520px)] sm:min-h-[min(54vh,560px)]"
|
||||
: hasDraft
|
||||
? "min-h-[188px]"
|
||||
: "min-h-[120px]"
|
||||
|
||||
return (
|
||||
<>
|
||||
{isExpanded && (
|
||||
<div
|
||||
className="fixed inset-0 z-[60] bg-[#05080D]/45 backdrop-blur-[10px]"
|
||||
onPointerDown={handleBackdropPointerDown}
|
||||
aria-hidden
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="bg-[#1B1F24] rounded-[22px] p-1"
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"relative w-full rounded-[22px] bg-[#1B1F24] p-1 transition-[box-shadow,transform,width] duration-200",
|
||||
isExpanded &&
|
||||
"z-[70] w-[min(calc(100vw-1.5rem),640px)] sm:w-full scale-[1.01]",
|
||||
)}
|
||||
id="quick-note-inner"
|
||||
className="bg-[#0B1017] rounded-[18px] p-3 relative"
|
||||
style={{
|
||||
boxShadow: isExpanded
|
||||
? "0 24px 80px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.08), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset"
|
||||
: "0 2.842px 14.211px 0 rgba(0, 0, 0, 0.25), 0.711px 0.711px 0.711px 0 rgba(255, 255, 255, 0.10) inset",
|
||||
boxShadow: "inset 1.421px 1.421px 4.263px 0 rgba(11, 15, 21, 0.4)",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
id="quick-note-inner"
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleMaximizeClick}
|
||||
className="absolute top-3 right-3 text-[#737373] hover:text-white transition-colors cursor-pointer"
|
||||
aria-label="Expand to full screen"
|
||||
>
|
||||
<Maximize2 className="size-[14px]" />
|
||||
</button>
|
||||
|
||||
<textarea
|
||||
ref={textareaRef}
|
||||
value={draft}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Start writing..."
|
||||
disabled={isSaving}
|
||||
className={cn(
|
||||
"relative flex flex-col rounded-[18px] bg-[#0B1017] p-3",
|
||||
isExpanded &&
|
||||
"fixed inset-x-3 top-[calc(env(safe-area-inset-top)+72px)] z-[71] max-h-[calc(100dvh-96px)] sm:static sm:inset-auto",
|
||||
dmSansClassName(),
|
||||
"w-full h-[120px] bg-transparent resize-none outline-none text-[12px] leading-normal text-white placeholder:text-[#737373] pr-5 disabled:opacity-50",
|
||||
)}
|
||||
onFocusCapture={() => setIsExpanded(true)}
|
||||
onBlurCapture={handleBlurCapture}
|
||||
/>
|
||||
|
||||
<div
|
||||
id="quick-note-action-bar"
|
||||
className="bg-[#1B1F24] rounded-[8px] px-2 py-1.5 flex items-center justify-center gap-8 w-full"
|
||||
style={{
|
||||
boxShadow: "inset 1.421px 1.421px 4.263px 0 rgba(11, 15, 21, 0.4)",
|
||||
boxShadow:
|
||||
"0 4px 20px 0 rgba(0, 0, 0, 0.25), inset 1px 1px 1px 0 rgba(255, 255, 255, 0.1)",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleMaximizeClick}
|
||||
className="absolute top-3 right-3 text-[#737373] hover:text-white transition-colors cursor-pointer"
|
||||
aria-label="Expand to full screen"
|
||||
>
|
||||
<Maximize2 className="size-[14px]" />
|
||||
</button>
|
||||
|
||||
<div
|
||||
onClick={handleSaveClick}
|
||||
disabled={!canSave}
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"w-full flex-1 overflow-y-auto pr-5 text-white disabled:opacity-50",
|
||||
"[&_.ProseMirror]:text-[12px] [&_.ProseMirror]:leading-normal [&_.ProseMirror_p.is-editor-empty:first-child::before]:text-[#737373]",
|
||||
editorHeight,
|
||||
"flex items-center gap-1.5 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
|
||||
)}
|
||||
aria-disabled={isSaving}
|
||||
>
|
||||
<TextEditor
|
||||
content={draft}
|
||||
onContentChange={handleContentChange}
|
||||
onSubmit={handleEditorSubmit}
|
||||
debounceMs={0}
|
||||
editable={!isSaving}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="quick-note-action-bar"
|
||||
className="mt-3 flex w-full items-center justify-center gap-8 rounded-[8px] bg-[#1B1F24] px-2 py-1.5"
|
||||
style={{
|
||||
boxShadow:
|
||||
"0 4px 20px 0 rgba(0, 0, 0, 0.25), inset 1px 1px 1px 0 rgba(255, 255, 255, 0.1)",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSaveClick}
|
||||
disabled={!canSave}
|
||||
className={cn(
|
||||
"flex items-center gap-1.5 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50",
|
||||
<span className="flex items-center gap-1.5">
|
||||
{isSaving ? (
|
||||
<Loader2 className="size-2 animate-spin text-[#fafafa]" />
|
||||
) : (
|
||||
<Plus className="size-2 text-[#fafafa]" />
|
||||
)}
|
||||
>
|
||||
<span className="flex items-center gap-1.5">
|
||||
{isSaving ? (
|
||||
<Loader2 className="size-2 animate-spin text-[#fafafa]" />
|
||||
) : (
|
||||
<Plus className="size-2 text-[#fafafa]" />
|
||||
)}
|
||||
<span
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"text-[10px] font-medium text-[#fafafa]",
|
||||
)}
|
||||
>
|
||||
{isSaving ? "Saving..." : "Save note"}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"bg-[rgba(33,33,33,0.5)] border border-[rgba(115,115,115,0.2)] rounded px-1 py-0.5 flex items-center gap-1 h-4",
|
||||
dmSansClassName(),
|
||||
"text-[10px] font-medium text-[#fafafa]",
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
className="size-[10px]"
|
||||
viewBox="0 0 9 9"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Command Key</title>
|
||||
<path
|
||||
d="M6.67 0.42C6.34 0.42 6.02 0.55 5.78 0.78C5.55 1.02 5.42 1.34 5.42 1.67V6.67C5.42 7 5.55 7.32 5.78 7.55C6.02 7.78 6.34 7.92 6.67 7.92C7 7.92 7.32 7.78 7.55 7.55C7.78 7.32 7.92 7 7.92 6.67C7.92 6.34 7.78 6.02 7.55 5.78C7.32 5.55 7 5.42 6.67 5.42H1.67C1.34 5.42 1.02 5.55 0.78 5.78C0.55 6.02 0.42 6.34 0.42 6.67C0.42 7 0.55 7.32 0.78 7.55C1.02 7.78 1.34 7.92 1.67 7.92C2 7.92 2.32 7.78 2.55 7.55C2.78 7.32 2.92 7 2.92 6.67V1.67C2.92 1.34 2.78 1.02 2.55 0.78C2.32 0.55 2 0.42 1.67 0.42C1.34 0.42 1.02 0.55 0.78 0.78C0.55 1.02 0.42 1.34 0.42 1.67C0.42 2 0.55 2.32 0.78 2.55C1.02 2.78 1.34 2.92 1.67 2.92H6.67C7 2.92 7.32 2.78 7.55 2.55C7.78 2.32 7.92 2 7.92 1.67C7.92 1.34 7.78 1.02 7.55 0.78C7.32 0.55 7 0.42 6.67 0.42Z"
|
||||
stroke="#737373"
|
||||
strokeWidth="0.833333"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"text-[10px] font-medium text-[#737373]",
|
||||
)}
|
||||
>
|
||||
Enter
|
||||
</span>
|
||||
{isSaving ? "Saving..." : "Save note"}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"bg-[rgba(33,33,33,0.5)] border border-[rgba(115,115,115,0.2)] rounded px-1 py-0.5 flex items-center gap-1 h-4",
|
||||
)}
|
||||
>
|
||||
<svg
|
||||
className="size-[10px]"
|
||||
viewBox="0 0 9 9"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Command Key</title>
|
||||
<path
|
||||
d="M6.67 0.42C6.34 0.42 6.02 0.55 5.78 0.78C5.55 1.02 5.42 1.34 5.42 1.67V6.67C5.42 7 5.55 7.32 5.78 7.55C6.02 7.78 6.34 7.92 6.67 7.92C7 7.92 7.32 7.78 7.55 7.55C7.78 7.32 7.92 7 7.92 6.67C7.92 6.34 7.78 6.02 7.55 5.78C7.32 5.55 7 5.42 6.67 5.42H1.67C1.34 5.42 1.02 5.55 0.78 5.78C0.55 6.02 0.42 6.34 0.42 6.67C0.42 7 0.55 7.32 0.78 7.55C1.02 7.78 1.34 7.92 1.67 7.92C2 7.92 2.32 7.78 2.55 7.55C2.78 7.32 2.92 7 2.92 6.67V1.67C2.92 1.34 2.78 1.02 2.55 0.78C2.32 0.55 2 0.42 1.67 0.42C1.34 0.42 1.02 0.55 0.78 0.78C0.55 1.02 0.42 1.34 0.42 1.67C0.42 2 0.55 2.32 0.78 2.55C1.02 2.78 1.34 2.92 1.67 2.92H6.67C7 2.92 7.32 2.78 7.55 2.55C7.78 2.32 7.92 2 7.92 1.67C7.92 1.34 7.78 1.02 7.55 0.78C7.32 0.55 7 0.42 6.67 0.42Z"
|
||||
stroke="#737373"
|
||||
strokeWidth="0.833333"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
className={cn(
|
||||
dmSansClassName(),
|
||||
"text-[10px] font-medium text-[#737373]",
|
||||
)}
|
||||
>
|
||||
Enter
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,30 +13,21 @@ import { cn } from "@lib/utils"
|
|||
|
||||
const extensions = [...defaultExtensions, slashCommand, Markdown]
|
||||
|
||||
function getEditorMarkdown(editor: Editor) {
|
||||
const json = editor.getJSON()
|
||||
return editor.storage.markdown?.manager?.serialize(json) ?? ""
|
||||
}
|
||||
|
||||
export function TextEditor({
|
||||
content: initialContent,
|
||||
onContentChange,
|
||||
onSubmit,
|
||||
debounceMs = 500,
|
||||
editable = true,
|
||||
}: {
|
||||
content: string | undefined
|
||||
onContentChange: (content: string) => void
|
||||
onSubmit: (content: string) => void
|
||||
onSubmit: () => void
|
||||
debounceMs?: number
|
||||
editable?: boolean
|
||||
}) {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const editorRef = useRef<Editor | null>(null)
|
||||
const onSubmitRef = useRef(onSubmit)
|
||||
const hasUserEditedRef = useRef(false)
|
||||
const lastAppliedContentRef = useRef(initialContent)
|
||||
const lastEmittedContentRef = useRef<string | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
onSubmitRef.current = onSubmit
|
||||
|
|
@ -44,8 +35,8 @@ export function TextEditor({
|
|||
|
||||
const debouncedUpdates = useDebouncedCallback((editor: Editor) => {
|
||||
if (!hasUserEditedRef.current) return
|
||||
const markdown = getEditorMarkdown(editor)
|
||||
lastEmittedContentRef.current = markdown
|
||||
const json = editor.getJSON()
|
||||
const markdown = editor.storage.markdown?.manager?.serialize(json) ?? ""
|
||||
onContentChange?.(markdown)
|
||||
}, debounceMs)
|
||||
|
||||
|
|
@ -53,7 +44,6 @@ export function TextEditor({
|
|||
extensions,
|
||||
content: initialContent,
|
||||
contentType: "markdown",
|
||||
editable,
|
||||
immediatelyRender: true,
|
||||
onCreate: ({ editor }) => {
|
||||
editorRef.current = editor
|
||||
|
|
@ -62,8 +52,8 @@ export function TextEditor({
|
|||
editorRef.current = editor
|
||||
if (!hasUserEditedRef.current) return
|
||||
if (debounceMs === 0) {
|
||||
const markdown = getEditorMarkdown(editor)
|
||||
lastEmittedContentRef.current = markdown
|
||||
const json = editor.getJSON()
|
||||
const markdown = editor.storage.markdown?.manager?.serialize(json) ?? ""
|
||||
onContentChange?.(markdown)
|
||||
return
|
||||
}
|
||||
|
|
@ -74,10 +64,7 @@ export function TextEditor({
|
|||
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
||||
event.preventDefault()
|
||||
debouncedUpdates.flush()
|
||||
const currentEditor = editorRef.current
|
||||
const markdown = currentEditor ? getEditorMarkdown(currentEditor) : ""
|
||||
lastEmittedContentRef.current = markdown
|
||||
onSubmitRef.current?.(markdown)
|
||||
onSubmitRef.current?.()
|
||||
return true
|
||||
}
|
||||
hasUserEditedRef.current = true
|
||||
|
|
@ -99,29 +86,12 @@ export function TextEditor({
|
|||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!editor || initialContent === undefined) return
|
||||
if (initialContent === lastAppliedContentRef.current) return
|
||||
|
||||
if (initialContent === lastEmittedContentRef.current) {
|
||||
lastAppliedContentRef.current = initialContent
|
||||
return
|
||||
if (editor && initialContent) {
|
||||
hasUserEditedRef.current = false
|
||||
editor.commands.setContent(initialContent, { contentType: "markdown" })
|
||||
}
|
||||
|
||||
const currentContent = getEditorMarkdown(editor)
|
||||
if (currentContent === initialContent) {
|
||||
lastAppliedContentRef.current = initialContent
|
||||
return
|
||||
}
|
||||
|
||||
hasUserEditedRef.current = false
|
||||
lastAppliedContentRef.current = initialContent
|
||||
editor.commands.setContent(initialContent, { contentType: "markdown" })
|
||||
}, [editor, initialContent])
|
||||
|
||||
useEffect(() => {
|
||||
editor?.setEditable(editable)
|
||||
}, [editor, editable])
|
||||
|
||||
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const target = e.target as HTMLElement
|
||||
if (target.closest(".ProseMirror")) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue