Skip to content

Commit 5b02798

Browse files
committed
refactor(user-input): extract adoptDomValue; drop flushSync pre-paint reconcile
1 parent 7c3e298 commit 5b02798

1 file changed

Lines changed: 14 additions & 7 deletions

File tree

  • apps/sim/app/workspace/[workspaceId]/home/components/user-input

apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,16 @@ export const UserInput = forwardRef<UserInputHandle, UserInputProps>(function Us
752752
}
753753
}, [onSubmit, textareaRef, resetTranscript])
754754

755+
/**
756+
* Adopts the textarea's DOM value into state. State and DOM can only drift
757+
* when an edit's input event is lost (programmatic edits pair setValue
758+
* synchronously) — the DOM is the user's intent.
759+
*/
760+
const adoptDomValue = useCallback((textarea: HTMLTextAreaElement) => {
761+
valueRef.current = textarea.value
762+
setValue(textarea.value)
763+
}, [])
764+
755765
const handleKeyDown = useCallback(
756766
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
757767
if (mentionRangeRef.current && !e.nativeEvent.isComposing) {
@@ -1060,13 +1070,10 @@ export const UserInput = forwardRef<UserInputHandle, UserInputProps>(function Us
10601070
// may get superseded — so edge-movement inference stays true to the DOM.
10611071
lastSelectionRef.current = { start, end }
10621072

1063-
// Controlled-value reconciliation: state and DOM can only drift when an
1064-
// edit's change event is lost (programmatic edits pair setValue
1065-
// synchronously). The DOM is the user's intent — adopt it and let the
1066-
// render rebuild the overlay; selection logic resumes on the next event.
1073+
// Reconciliation backstop for non-keyboard mutations; the render rebuilds
1074+
// the overlay and selection logic resumes on the next event.
10671075
if (textarea.value !== valueRef.current) {
1068-
valueRef.current = textarea.value
1069-
setValue(textarea.value)
1076+
adoptDomValue(textarea)
10701077
return
10711078
}
10721079

@@ -1117,7 +1124,7 @@ export const UserInput = forwardRef<UserInputHandle, UserInputProps>(function Us
11171124
const focusPos = textarea.selectionDirection === 'backward' ? start : end
11181125
syncMentionState(textarea, textarea.value, focusPos)
11191126
syncSlashState(textarea, textarea.value, focusPos)
1120-
}, [textareaRef, mentionTokensWithContext, syncMentionState, syncSlashState])
1127+
}, [textareaRef, mentionTokensWithContext, adoptDomValue, syncMentionState, syncSlashState])
11211128

11221129
const handleInput = useCallback(
11231130
(e: React.FormEvent<HTMLTextAreaElement>) => {

0 commit comments

Comments
 (0)