From 60d7870c7c8786cfe6d0143177ec250d3683faf7 Mon Sep 17 00:00:00 2001 From: yousefed Date: Wed, 18 Mar 2026 19:33:49 +0100 Subject: [PATCH] fix: save file caption/name on every keystroke instead of on close Previously, caption/name values were stored in local state and only saved to the block on Enter. Clicking outside the popover discarded input, and Enter didn't close the popover. Now handleChange calls editor.updateBlock directly, input reads from block props, and the popover is controlled so Enter closes it. Co-Authored-By: Claude Opus 4.6 --- .../DefaultButtons/FileCaptionButton.tsx | 44 ++++++++---------- .../DefaultButtons/FileRenameButton.tsx | 45 ++++++++----------- 2 files changed, 38 insertions(+), 51 deletions(-) diff --git a/packages/react/src/components/FormattingToolbar/DefaultButtons/FileCaptionButton.tsx b/packages/react/src/components/FormattingToolbar/DefaultButtons/FileCaptionButton.tsx index 8d1ff3d343..309cc10e13 100644 --- a/packages/react/src/components/FormattingToolbar/DefaultButtons/FileCaptionButton.tsx +++ b/packages/react/src/components/FormattingToolbar/DefaultButtons/FileCaptionButton.tsx @@ -9,7 +9,6 @@ import { ChangeEvent, KeyboardEvent, useCallback, - useEffect, useState, } from "react"; import { RiInputField } from "react-icons/ri"; @@ -59,54 +58,49 @@ export const FileCaptionButton = () => { }, }); - const [currentEditingCaption, setCurrentEditingCaption] = useState(); - - useEffect(() => { - if (block === undefined) { - return; - } - setCurrentEditingCaption(block.props.caption); - }, [block]); + const [popoverOpen, setPopoverOpen] = useState(false); const handleChange = useCallback( - (event: ChangeEvent) => - setCurrentEditingCaption(event.currentTarget.value), - [], - ); - - const handleEnter = useCallback( - (event: KeyboardEvent) => { + (event: ChangeEvent) => { if ( block !== undefined && editorHasBlockWithType(editor, block.type, { caption: "string", - }) && - event.key === "Enter" && - !event.nativeEvent.isComposing + }) ) { - event.preventDefault(); editor.updateBlock(block.id, { props: { - caption: currentEditingCaption, + caption: event.currentTarget.value, }, }); } }, - [block, currentEditingCaption, editor], + [block, editor], ); + const handleKeyDown = useCallback((event: KeyboardEvent) => { + if (event.key === "Enter" && !event.nativeEvent.isComposing) { + event.preventDefault(); + setPopoverOpen(false); + } + }, []); + if (block === undefined) { return null; } return ( - + } + onClick={() => setPopoverOpen((open) => !open)} /> { } - value={currentEditingCaption || ""} + value={block.props.caption} autoFocus={true} placeholder={dict.formatting_toolbar.file_caption.input_placeholder} - onKeyDown={handleEnter} + onKeyDown={handleKeyDown} onChange={handleChange} /> diff --git a/packages/react/src/components/FormattingToolbar/DefaultButtons/FileRenameButton.tsx b/packages/react/src/components/FormattingToolbar/DefaultButtons/FileRenameButton.tsx index 863febd7d4..87c30fef22 100644 --- a/packages/react/src/components/FormattingToolbar/DefaultButtons/FileRenameButton.tsx +++ b/packages/react/src/components/FormattingToolbar/DefaultButtons/FileRenameButton.tsx @@ -9,7 +9,6 @@ import { ChangeEvent, KeyboardEvent, useCallback, - useEffect, useState, } from "react"; import { RiFontFamily } from "react-icons/ri"; @@ -59,49 +58,42 @@ export const FileRenameButton = () => { }, }); - const [currentEditingName, setCurrentEditingName] = useState(); - - useEffect(() => { - if (block === undefined) { - return; - } - - setCurrentEditingName(block.props.name); - }, [block]); + const [popoverOpen, setPopoverOpen] = useState(false); const handleChange = useCallback( - (event: ChangeEvent) => - setCurrentEditingName(event.currentTarget.value), - [], - ); - - const handleEnter = useCallback( - (event: KeyboardEvent) => { + (event: ChangeEvent) => { if ( block !== undefined && editorHasBlockWithType(editor, block.type, { name: "string", - }) && - event.key === "Enter" && - !event.nativeEvent.isComposing + }) ) { - event.preventDefault(); editor.updateBlock(block.id, { props: { - name: currentEditingName, + name: event.currentTarget.value, }, }); } }, - [block, currentEditingName, editor], + [block, editor], ); + const handleKeyDown = useCallback((event: KeyboardEvent) => { + if (event.key === "Enter" && !event.nativeEvent.isComposing) { + event.preventDefault(); + setPopoverOpen(false); + } + }, []); + if (block === undefined) { return null; } return ( - + { dict.formatting_toolbar.file_rename.tooltip["file"] } icon={} + onClick={() => setPopoverOpen((open) => !open)} /> { } - value={currentEditingName || ""} + value={block.props.name} autoFocus={true} placeholder={ dict.formatting_toolbar.file_rename.input_placeholder[ block.type ] || dict.formatting_toolbar.file_rename.input_placeholder["file"] } - onKeyDown={handleEnter} + onKeyDown={handleKeyDown} onChange={handleChange} />