This commit is contained in:
iqudoo
2026-06-13 01:35:20 +08:00
parent 4167fb2683
commit f2689520bd
3 changed files with 68 additions and 10 deletions

View File

@@ -25,6 +25,12 @@ export const CommitInput: React.FC<CommitInputProps> = ({
}) => { }) => {
const [localVal, setLocalVal] = useState<string>(String(value)); const [localVal, setLocalVal] = useState<string>(String(value));
const focusedRef = useRef(false); 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(() => { useEffect(() => {
if (!focusedRef.current) { if (!focusedRef.current) {
@@ -32,12 +38,27 @@ export const CommitInput: React.FC<CommitInputProps> = ({
} }
}, [value]); }, [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<HTMLInputElement>) => { const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
focusedRef.current = false; focusedRef.current = false;
onBlur?.(e); onBlur?.(e);
if (localVal !== String(value)) { commitIfChanged();
onCommit(localVal);
}
}; };
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {

View File

@@ -73,6 +73,17 @@ const MARQUEE_MIN_PX = 4;
const DRAG_START_THRESHOLD_PX = 4; const DRAG_START_THRESHOLD_PX = 4;
const MODERATE_ZOOM_MAX = 2.0; 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( function rectFullyContains(
outer: { left: number; top: number; right: number; bottom: number }, outer: { left: number; top: number; right: number; bottom: number },
inner: { 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<LabelDesignerProps> = ({
if (isTiny) { if (isTiny) {
if (!state.additive) { if (!state.additive) {
onSelectElements([]); requestAnimationFrame(() => onSelectElements([]));
} }
return; return;
} }
@@ -618,6 +629,8 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
const canvas = canvasRef.current; const canvas = canvasRef.current;
if (!canvas) return; if (!canvas) return;
blurActiveField();
const rect = canvas.getBoundingClientRect(); const rect = canvas.getBoundingClientRect();
const startX = e.clientX - rect.left; const startX = e.clientX - rect.left;
const startY = e.clientY - rect.top; const startY = e.clientY - rect.top;
@@ -814,7 +827,7 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
return; return;
} }
if (e.target === e.currentTarget) { if (e.target === e.currentTarget) {
onSelectElements([]); requestAnimationFrame(() => onSelectElements([]));
} }
}} }}
> >

View File

@@ -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 { LabelTemplate, TemplateElement, PaperConfig, VisibilityRule } from '../types';
import { import {
extractTemplateVariables, extractTemplateVariables,
@@ -101,14 +101,35 @@ interface PropTextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAr
const PropTextarea: React.FC<PropTextareaProps> = ({ value, onCommit, ...props }) => { const PropTextarea: React.FC<PropTextareaProps> = ({ value, onCommit, ...props }) => {
const [localVal, setLocalVal] = useState<string>(value); 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(() => { useEffect(() => {
setLocalVal(value); if (!focusedRef.current) {
setLocalVal(value);
}
}, [value]); }, [value]);
useEffect(() => {
return () => {
if (
focusedRef.current &&
localValRef.current !== valueRef.current
) {
onCommitRef.current(localValRef.current);
}
};
}, []);
const handleBlur = () => { const handleBlur = () => {
if (localVal !== value) { focusedRef.current = false;
onCommit(localVal); if (localValRef.current !== valueRef.current) {
onCommitRef.current(localValRef.current);
} }
}; };
@@ -117,6 +138,9 @@ const PropTextarea: React.FC<PropTextareaProps> = ({ value, onCommit, ...props }
{...props} {...props}
value={localVal} value={localVal}
onChange={(e) => setLocalVal(e.target.value)} onChange={(e) => setLocalVal(e.target.value)}
onFocus={() => {
focusedRef.current = true;
}}
onBlur={handleBlur} onBlur={handleBlur}
/> />
); );
@@ -722,7 +746,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
</div> </div>
<p className="text-[10px] text-[#777] leading-normal flex items-center gap-1 bg-[#1e1e1e] p-2 border border-[#3a3a3a]"> <p className="text-[10px] text-[#777] leading-normal flex items-center gap-1 bg-[#1e1e1e] p-2 border border-[#3a3a3a]">
<HelpCircle className="w-3.5 h-3.5 text-[#31a8ff] shrink-0" /> <HelpCircle className="w-3.5 h-3.5 text-[#31a8ff] shrink-0" />
<span></span> <span></span>
</p> </p>
</div> </div>
</div> </div>