diff --git a/src/components/CommitInput.tsx b/src/components/CommitInput.tsx index b9ed422..e69b93c 100644 --- a/src/components/CommitInput.tsx +++ b/src/components/CommitInput.tsx @@ -25,6 +25,12 @@ export const CommitInput: React.FC = ({ }) => { const [localVal, setLocalVal] = useState(String(value)); const focusedRef = useRef(false); + const localValRef = useRef(localVal); + const valueRef = useRef(value); + const onCommitRef = useRef(onCommit); + localValRef.current = localVal; + valueRef.current = value; + onCommitRef.current = onCommit; useEffect(() => { if (!focusedRef.current) { @@ -32,12 +38,27 @@ export const CommitInput: React.FC = ({ } }, [value]); + useEffect(() => { + return () => { + if ( + focusedRef.current && + localValRef.current !== String(valueRef.current) + ) { + onCommitRef.current(localValRef.current); + } + }; + }, []); + + const commitIfChanged = () => { + if (localValRef.current !== String(valueRef.current)) { + onCommitRef.current(localValRef.current); + } + }; + const handleBlur = (e: React.FocusEvent) => { focusedRef.current = false; onBlur?.(e); - if (localVal !== String(value)) { - onCommit(localVal); - } + commitIfChanged(); }; const handleKeyDown = (e: React.KeyboardEvent) => { diff --git a/src/components/LabelDesigner.tsx b/src/components/LabelDesigner.tsx index 9c8048c..7dc90c5 100644 --- a/src/components/LabelDesigner.tsx +++ b/src/components/LabelDesigner.tsx @@ -73,6 +73,17 @@ const MARQUEE_MIN_PX = 4; const DRAG_START_THRESHOLD_PX = 4; const MODERATE_ZOOM_MAX = 2.0; +function blurActiveField() { + const active = document.activeElement; + if ( + active instanceof HTMLInputElement || + active instanceof HTMLTextAreaElement || + active instanceof HTMLSelectElement + ) { + active.blur(); + } +} + function rectFullyContains( outer: { left: number; top: number; right: number; bottom: number }, inner: { left: number; top: number; right: number; bottom: number } @@ -445,7 +456,7 @@ export const LabelDesigner: React.FC = ({ if (isTiny) { if (!state.additive) { - onSelectElements([]); + requestAnimationFrame(() => onSelectElements([])); } return; } @@ -618,6 +629,8 @@ export const LabelDesigner: React.FC = ({ const canvas = canvasRef.current; if (!canvas) return; + blurActiveField(); + const rect = canvas.getBoundingClientRect(); const startX = e.clientX - rect.left; const startY = e.clientY - rect.top; @@ -814,7 +827,7 @@ export const LabelDesigner: React.FC = ({ return; } if (e.target === e.currentTarget) { - onSelectElements([]); + requestAnimationFrame(() => onSelectElements([])); } }} > diff --git a/src/components/PropSidebar.tsx b/src/components/PropSidebar.tsx index c5fcf97..2a2efe5 100644 --- a/src/components/PropSidebar.tsx +++ b/src/components/PropSidebar.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo } from 'react'; +import React, { useState, useEffect, useMemo, useRef } from 'react'; import { LabelTemplate, TemplateElement, PaperConfig, VisibilityRule } from '../types'; import { extractTemplateVariables, @@ -101,14 +101,35 @@ interface PropTextareaProps extends Omit = ({ value, onCommit, ...props }) => { const [localVal, setLocalVal] = useState(value); + const focusedRef = useRef(false); + const localValRef = useRef(localVal); + const valueRef = useRef(value); + const onCommitRef = useRef(onCommit); + localValRef.current = localVal; + valueRef.current = value; + onCommitRef.current = onCommit; useEffect(() => { - setLocalVal(value); + if (!focusedRef.current) { + setLocalVal(value); + } }, [value]); + useEffect(() => { + return () => { + if ( + focusedRef.current && + localValRef.current !== valueRef.current + ) { + onCommitRef.current(localValRef.current); + } + }; + }, []); + const handleBlur = () => { - if (localVal !== value) { - onCommit(localVal); + focusedRef.current = false; + if (localValRef.current !== valueRef.current) { + onCommitRef.current(localValRef.current); } }; @@ -117,6 +138,9 @@ const PropTextarea: React.FC = ({ value, onCommit, ...props } {...props} value={localVal} onChange={(e) => setLocalVal(e.target.value)} + onFocus={() => { + focusedRef.current = true; + }} onBlur={handleBlur} /> ); @@ -722,7 +746,7 @@ export const PropSidebar: React.FC = ({

- 点击画布元素以编辑属性,或在下方图层面板中选择。 + 选中元素以编辑属性