fix: prevent local edit prompt focus loss
This commit is contained in:
parent
7421e158d1
commit
d370c68b43
@ -1984,6 +1984,7 @@ export function ImageNode({
|
||||
const localEditPromptInputRefs = useRef<
|
||||
Record<string, HTMLInputElement | null>
|
||||
>({});
|
||||
const localEditPromptDraftRefs = useRef<Record<string, string>>({});
|
||||
|
||||
const updateNode = useCanvasStore((state) => state.updateNode);
|
||||
const deleteNode = useCanvasStore((state) => state.deleteNode);
|
||||
@ -2459,6 +2460,8 @@ export function ImageNode({
|
||||
const input = localEditPromptInputRefs.current[regionId];
|
||||
if (!input) return;
|
||||
input.focus({ preventScroll: true });
|
||||
const cursorPosition = input.value.length;
|
||||
input.setSelectionRange(cursorPosition, cursorPosition);
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -2473,6 +2476,9 @@ export function ImageNode({
|
||||
regions.slice(0, LOCAL_EDIT_MAX_REGIONS)
|
||||
);
|
||||
setLocalEditRegions(nextRegions);
|
||||
localEditPromptDraftRefs.current = Object.fromEntries(
|
||||
nextRegions.map((region) => [region.id, region.prompt])
|
||||
);
|
||||
|
||||
const nextMetadata =
|
||||
data.metadata && typeof data.metadata === "object"
|
||||
@ -3417,21 +3423,9 @@ export function ImageNode({
|
||||
[localEditMode]
|
||||
);
|
||||
|
||||
const updateLocalEditRegionPrompt = useCallback(
|
||||
(regionId: string, prompt: string) => {
|
||||
setLocalEditRegions((prevRegions) =>
|
||||
reindexLocalEditRegions(
|
||||
prevRegions.map((region) =>
|
||||
region.id === regionId ? { ...region, prompt } : region
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const persistLocalEditRegionPrompt = useCallback(
|
||||
(regionId: string, prompt: string) => {
|
||||
localEditPromptDraftRefs.current[regionId] = prompt;
|
||||
commitLocalEditRegions(
|
||||
localEditRegions.map((region) =>
|
||||
region.id === regionId ? { ...region, prompt } : region
|
||||
@ -3443,6 +3437,7 @@ export function ImageNode({
|
||||
|
||||
const deleteLocalEditRegion = useCallback(
|
||||
(regionId: string) => {
|
||||
delete localEditPromptDraftRefs.current[regionId];
|
||||
commitLocalEditRegions(
|
||||
localEditRegions.filter((region) => region.id !== regionId)
|
||||
);
|
||||
@ -3454,6 +3449,7 @@ export function ImageNode({
|
||||
);
|
||||
|
||||
const clearLocalEditRegions = useCallback(() => {
|
||||
localEditPromptDraftRefs.current = {};
|
||||
commitLocalEditRegions([]);
|
||||
setEditingLocalEditRegionId(null);
|
||||
}, [commitLocalEditRegions]);
|
||||
@ -3475,7 +3471,9 @@ export function ImageNode({
|
||||
const validRegions = reindexLocalEditRegions(
|
||||
localEditRegions.map((region) => ({
|
||||
...region,
|
||||
prompt: region.prompt.trim(),
|
||||
prompt: (
|
||||
localEditPromptDraftRefs.current[region.id] ?? region.prompt
|
||||
).trim(),
|
||||
}))
|
||||
);
|
||||
|
||||
@ -8159,33 +8157,32 @@ export function ImageNode({
|
||||
className="nodrag nopan nowheel h-9 min-w-0 flex-1 rounded-full border border-slate-300 bg-white/95 px-3 text-[12px] font-medium text-slate-950 caret-slate-950 shadow-[0_10px_24px_rgba(15,23,42,0.14)] outline-none ring-2 ring-transparent transition placeholder:text-slate-400 focus:border-slate-950 focus:ring-slate-950/15 dark:border-white/20 dark:bg-slate-950/88 dark:text-white dark:caret-white dark:placeholder:text-white/42 dark:focus:border-white/40 dark:focus:ring-white/18"
|
||||
data-canvas-no-drag="true"
|
||||
data-local-edit-control="true"
|
||||
onBlur={(event) => {
|
||||
const relatedTarget =
|
||||
event.relatedTarget instanceof HTMLElement
|
||||
? event.relatedTarget
|
||||
: null;
|
||||
const nextPrompt = event.currentTarget.value;
|
||||
if (nextPrompt.trim()) {
|
||||
persistLocalEditRegionPrompt(region.id, nextPrompt);
|
||||
setEditingLocalEditRegionId(null);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
editingLocalEditRegionId === region.id &&
|
||||
!relatedTarget?.closest("[data-local-edit-control='true']")
|
||||
) {
|
||||
focusLocalEditPromptInput(region.id);
|
||||
}
|
||||
}}
|
||||
onChange={(event) =>
|
||||
updateLocalEditRegionPrompt(region.id, event.target.value)
|
||||
defaultValue={
|
||||
localEditPromptDraftRefs.current[region.id] ?? region.prompt
|
||||
}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
focusLocalEditPromptInput(region.id);
|
||||
onBlur={(event) => {
|
||||
const nextPrompt = event.currentTarget.value;
|
||||
localEditPromptDraftRefs.current[region.id] = nextPrompt;
|
||||
persistLocalEditRegionPrompt(region.id, nextPrompt);
|
||||
setEditingLocalEditRegionId(null);
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
onFocus={(event) => {
|
||||
event.stopPropagation();
|
||||
setEditingLocalEditRegionId((current) =>
|
||||
current === region.id ? current : region.id
|
||||
);
|
||||
}}
|
||||
onInput={(event) => {
|
||||
localEditPromptDraftRefs.current[region.id] =
|
||||
event.currentTarget.value;
|
||||
}}
|
||||
onFocus={() => setEditingLocalEditRegionId(region.id)}
|
||||
onKeyDown={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
@ -8204,19 +8201,32 @@ export function ImageNode({
|
||||
setEditingLocalEditRegionId(null);
|
||||
}
|
||||
}}
|
||||
onKeyUp={(event) => event.stopPropagation()}
|
||||
onMouseDown={(event) => event.stopPropagation()}
|
||||
onMouseDownCapture={(event) => event.stopPropagation()}
|
||||
onPointerDown={(event) => event.stopPropagation()}
|
||||
onPointerDownCapture={(event) => {
|
||||
onKeyUp={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
focusLocalEditPromptInput(region.id);
|
||||
}}
|
||||
onMouseDown={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onMouseDownCapture={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
onPointerDown={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onPointerDownCapture={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation?.();
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
placeholder={`区域 ${region.index} 提示词`}
|
||||
ref={(input) => {
|
||||
localEditPromptInputRefs.current[region.id] = input;
|
||||
}}
|
||||
value={region.prompt}
|
||||
/>
|
||||
) : (
|
||||
<button
|
||||
@ -8286,8 +8296,7 @@ export function ImageNode({
|
||||
className="mr-1 inline-flex h-10 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-xl bg-emerald-600 px-3 font-semibold text-[13px] text-white hover:bg-emerald-500 hover:text-white disabled:bg-slate-300 disabled:text-slate-500 dark:bg-emerald-500 dark:disabled:bg-slate-700 dark:disabled:text-slate-400 dark:hover:bg-emerald-400"
|
||||
disabled={
|
||||
isSubmittingLocalEdit ||
|
||||
localEditRegions.length === 0 ||
|
||||
localEditRegions.some((region) => !region.prompt.trim())
|
||||
localEditRegions.length === 0
|
||||
}
|
||||
onClick={() => void handleSubmitLocalEdit()}
|
||||
title="生成局部编辑结果"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user