Skip to content

Commit bf812fa

Browse files
committed
when select an actual (non-collapsed) range, suggestions disappear
1 parent b19b804 commit bf812fa

4 files changed

Lines changed: 41 additions & 23 deletions

File tree

packages/react-textarea/src/hooks/useAutocomplete.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
EditorAutocompleteState,
1111
areEqual_autocompleteState,
1212
} from "../types/types";
13+
import { nullableCompatibleEqualityCheck } from "../lib/utils";
1314

1415
export interface AutocompleteSuggestion {
1516
text: string;
@@ -25,11 +26,7 @@ export function useAutocomplete(
2526
autocompleteConfig: AutocompleteConfig
2627
): UseAutocompleteResult {
2728
const [previousAutocompleteState, setPreviousAutocompleteState] =
28-
useState<EditorAutocompleteState>({
29-
cursorPoint: { path: [0, 0], offset: 0 },
30-
textBeforeCursor: "",
31-
textAfterCursor: "",
32-
});
29+
useState<EditorAutocompleteState | null>(null);
3330

3431
const [currentAutocompleteSuggestion, setCurrentAutocompleteSuggestion] =
3532
useState<AutocompleteSuggestion | null>(null);
@@ -72,7 +69,8 @@ export function useAutocomplete(
7269
const onChange = useCallback(
7370
(editor: CustomEditor) => {
7471
const newEditorState = getTextAroundCursor(editor);
75-
const editorStateHasChanged = !areEqual_autocompleteState(
72+
const editorStateHasChanged = !nullableCompatibleEqualityCheck(
73+
areEqual_autocompleteState,
7674
previousAutocompleteState,
7775
newEditorState
7876
);
@@ -84,9 +82,14 @@ export function useAutocomplete(
8482
}
8583

8684
// if change, then first null out the current suggestion
87-
// then try to get a new suggestion, debouncing to avoid too many requests while typing
8885
setCurrentAutocompleteSuggestion(null);
89-
debouncedFunction.debounce(awaitForAndAppendSuggestion, newEditorState);
86+
87+
// then try to get a new suggestion, debouncing to avoid too many requests while typing
88+
if (newEditorState) {
89+
debouncedFunction.debounce(awaitForAndAppendSuggestion, newEditorState);
90+
} else {
91+
debouncedFunction.cancel();
92+
}
9093
},
9194
[
9295
previousAutocompleteState,

packages/react-textarea/src/lib/debouncer.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ export class Debouncer<T extends any[]> {
1010

1111
debounce = async (func: AsyncFunction<T>, ...args: T) => {
1212
// Abort the previous promise immediately
13-
if (this.activeAbortController) {
14-
this.activeAbortController.abort();
15-
this.activeAbortController = undefined;
16-
}
17-
18-
if (this.timeoutId !== undefined) {
19-
clearTimeout(this.timeoutId);
20-
}
13+
this.cancel();
2114

2215
this.timeoutId = setTimeout(async () => {
2316
try {
@@ -30,4 +23,16 @@ export class Debouncer<T extends any[]> {
3023
} catch (error) {}
3124
}, this.wait);
3225
};
26+
27+
cancel = () => {
28+
if (this.activeAbortController) {
29+
this.activeAbortController.abort();
30+
this.activeAbortController = undefined;
31+
}
32+
33+
if (this.timeoutId !== undefined) {
34+
clearTimeout(this.timeoutId);
35+
this.timeoutId = undefined;
36+
}
37+
};
3338
}

packages/react-textarea/src/lib/getTextAroundCursor.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { Editor, Node, Path, Range, Text, Element, BasePoint } from "slate";
22
import { EditorAutocompleteState } from "../types/types";
33

4-
export function getTextAroundCursor(editor: Editor): EditorAutocompleteState {
4+
export function getTextAroundCursor(
5+
editor: Editor
6+
): EditorAutocompleteState | null {
57
const { selection } = editor;
68

7-
if (!selection) {
8-
return {
9-
cursorPoint: { path: [], offset: 0 },
10-
textBeforeCursor: "",
11-
textAfterCursor: "",
12-
};
9+
if (!selection || !Range.isCollapsed(selection)) {
10+
return null;
1311
}
1412

1513
// Helper function to extract text with newlines

packages/react-textarea/src/lib/utils.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,15 @@ export function formatDate(input: string | number | Date): string {
4545
export const arraysAreEqual = (arr1: number[], arr2: number[]): boolean =>
4646
arr1.length === arr2.length &&
4747
arr1.every((value, index) => value === arr2[index]);
48+
49+
export function nullableCompatibleEqualityCheck<T>(
50+
naiveEqualityCheck: (a: T, b: T) => boolean,
51+
a: T | null | undefined,
52+
b: T | null | undefined
53+
): boolean {
54+
if (a === null || a === undefined || b === null || b === undefined) {
55+
return a === b;
56+
}
57+
58+
return naiveEqualityCheck(a, b);
59+
}

0 commit comments

Comments
 (0)