@purpurds/autocomplete 5.29.0 → 5.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LICENSE.txt +3 -3
- package/dist/autocomplete.cjs.js +15 -15
- package/dist/autocomplete.cjs.js.map +1 -1
- package/dist/autocomplete.d.ts +4 -0
- package/dist/autocomplete.d.ts.map +1 -1
- package/dist/autocomplete.es.js +575 -571
- package/dist/autocomplete.es.js.map +1 -1
- package/dist/useAutocomplete.d.ts +7 -3
- package/dist/useAutocomplete.d.ts.map +1 -1
- package/package.json +11 -9
- package/src/autocomplete.stories.tsx +75 -42
- package/src/autocomplete.test.tsx +23 -0
- package/src/autocomplete.tsx +2 -2
- package/src/useAutocomplete.ts +34 -10
|
@@ -9,8 +9,8 @@ export type Option = {
|
|
|
9
9
|
};
|
|
10
10
|
export type InputProps = Omit<ComponentPropsWithRef<"input">, "onFocus" | "onMouseDown"> & {
|
|
11
11
|
"data-testid"?: string;
|
|
12
|
-
onFocus: () => void;
|
|
13
|
-
onMouseDown: () => void;
|
|
12
|
+
onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;
|
|
13
|
+
onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;
|
|
14
14
|
};
|
|
15
15
|
export type UseAutocompleteOptions<T extends Option> = {
|
|
16
16
|
combobox?: boolean;
|
|
@@ -22,14 +22,18 @@ export type UseAutocompleteOptions<T extends Option> = {
|
|
|
22
22
|
listboxLabel: string;
|
|
23
23
|
listboxMaxHeight?: string | number;
|
|
24
24
|
noOptionsText?: ReactNode;
|
|
25
|
+
onInputBlur?: React.FocusEventHandler<HTMLInputElement>;
|
|
25
26
|
onInputChange?: (value: string) => void;
|
|
27
|
+
onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;
|
|
28
|
+
onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
|
29
|
+
onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;
|
|
26
30
|
openOnFocus?: boolean;
|
|
27
31
|
onSelect?: (option: T | undefined) => void;
|
|
28
32
|
options: T[];
|
|
29
33
|
selectedOption?: T;
|
|
30
34
|
["data-testid"]?: string;
|
|
31
35
|
};
|
|
32
|
-
export declare const useAutocomplete: <T extends Option>({ combobox, highlightFirstOption, defaultInputValue, inputValue, filterOption, id, listboxLabel, listboxMaxHeight, onInputChange, openOnFocus, noOptionsText, onSelect, options, selectedOption, ["data-testid"]: dataTestid, }: UseAutocompleteOptions<T>) => {
|
|
36
|
+
export declare const useAutocomplete: <T extends Option>({ combobox, highlightFirstOption, defaultInputValue, inputValue, filterOption, id, listboxLabel, listboxMaxHeight, onInputBlur, onInputChange, onInputFocus, onInputKeyDown, onInputMouseDown, openOnFocus, noOptionsText, onSelect, options, selectedOption, ["data-testid"]: dataTestid, }: UseAutocompleteOptions<T>) => {
|
|
33
37
|
id: string;
|
|
34
38
|
inputProps: InputProps;
|
|
35
39
|
internalRef: import('react').MutableRefObject<HTMLDivElement | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../src/useAutocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIxE,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../src/useAutocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIxE,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,GAAG;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IACzE,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;CAC9E,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,MAAM,IAAI;IAIrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAI/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAI3B,UAAU,CAAC,EAAE,MAAM,CAAC;IAIpB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IAItE,EAAE,EAAE,MAAM,CAAC;IAIX,YAAY,EAAE,MAAM,CAAC;IAIrB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAInC,aAAa,CAAC,EAAE,SAAS,CAAC;IAI1B,WAAW,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IAIxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAIxC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,SAAS,KAAK,SAAS,CAAC;IAIpF,cAAc,CAAC,EAAE,KAAK,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;IAI9D,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,SAAS,KAAK,SAAS,CAAC;IAIxF,WAAW,CAAC,EAAE,OAAO,CAAC;IAItB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IAI3C,OAAO,EAAE,CAAC,EAAE,CAAC;IAIb,cAAc,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,gSAoB7C,sBAAsB,CAAC,CAAC,CAAC;;;;;;;;kCAyLW,CAAC,SAAS,MAAM,KAAG,gBAAgB;;CAqDzE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@purpurds/autocomplete",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.30.1",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"main": "./dist/autocomplete.cjs.js",
|
|
6
6
|
"types": "./dist/autocomplete.d.ts",
|
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"source": "src/autocomplete.tsx",
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"classnames": "~2.5.0",
|
|
18
|
-
"@purpurds/
|
|
19
|
-
"@purpurds/
|
|
20
|
-
"@purpurds/
|
|
21
|
-
"@purpurds/
|
|
22
|
-
"@purpurds/
|
|
18
|
+
"@purpurds/heading": "5.30.1",
|
|
19
|
+
"@purpurds/icon": "5.30.1",
|
|
20
|
+
"@purpurds/listbox": "5.30.1",
|
|
21
|
+
"@purpurds/text-field": "5.30.1",
|
|
22
|
+
"@purpurds/notification": "5.30.1",
|
|
23
|
+
"@purpurds/paragraph": "5.30.1",
|
|
24
|
+
"@purpurds/tokens": "5.30.1"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
27
|
"@rushstack/eslint-patch": "~1.10.0",
|
|
@@ -45,10 +47,10 @@
|
|
|
45
47
|
"typescript": "^5.6.3",
|
|
46
48
|
"vite": "5.4.8",
|
|
47
49
|
"vitest": "^2.1.2",
|
|
48
|
-
"@purpurds/
|
|
50
|
+
"@purpurds/icon": "5.30.1",
|
|
51
|
+
"@purpurds/button": "5.30.1",
|
|
49
52
|
"@purpurds/component-rig": "1.0.0",
|
|
50
|
-
"@purpurds/
|
|
51
|
-
"@purpurds/search-field": "5.29.0"
|
|
53
|
+
"@purpurds/search-field": "5.30.1"
|
|
52
54
|
},
|
|
53
55
|
"scripts": {
|
|
54
56
|
"build:dev": "vite",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { Notification } from "@purpurds/notification";
|
|
2
3
|
import { Paragraph } from "@purpurds/paragraph";
|
|
3
4
|
import { SearchField } from "@purpurds/search-field";
|
|
4
5
|
import { TextField } from "@purpurds/text-field";
|
|
@@ -10,6 +11,9 @@ import "@purpurds/button/styles";
|
|
|
10
11
|
import "@purpurds/listbox/styles";
|
|
11
12
|
import "@purpurds/search-field/styles";
|
|
12
13
|
import "@purpurds/text-field/styles";
|
|
14
|
+
import "@purpurds/notification/styles";
|
|
15
|
+
import "@purpurds/paragraph/styles";
|
|
16
|
+
import "@purpurds/heading/styles";
|
|
13
17
|
import { Autocomplete } from "./autocomplete";
|
|
14
18
|
|
|
15
19
|
const options = [
|
|
@@ -35,6 +39,22 @@ const options = [
|
|
|
35
39
|
{ id: "19", label: "Strawberry" },
|
|
36
40
|
];
|
|
37
41
|
|
|
42
|
+
const OnInputEventPitfallNotification = () => (
|
|
43
|
+
<div style={{ marginTop: "var(--purpur-spacing-150)", marginRight: "-200px" }}>
|
|
44
|
+
<Notification status="warning" heading="Pitfall alert">
|
|
45
|
+
<Paragraph>
|
|
46
|
+
To handle input events, <b>always pass handlers to Autocomplete if defined</b> instead of
|
|
47
|
+
directly to the input. Autocomplete internally uses input events, and setting them yourself
|
|
48
|
+
will override the internal functionality.
|
|
49
|
+
</Paragraph>
|
|
50
|
+
<Paragraph style={{ marginTop: "var(--purpur-spacing-150)" }} variant="paragraph-100-bold">
|
|
51
|
+
This goes for <i>onInputChange</i>, <i>onInputKeyDown</i>, <i>onInputFocus</i>,{" "}
|
|
52
|
+
<i>onInputMouseDown</i> and <i>onInputBlur</i>.
|
|
53
|
+
</Paragraph>
|
|
54
|
+
</Notification>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
|
|
38
58
|
const meta = {
|
|
39
59
|
title: "Inputs/Autocomplete",
|
|
40
60
|
component: Autocomplete,
|
|
@@ -108,20 +128,23 @@ export const WithTextField: Story = {
|
|
|
108
128
|
const [{ selectedOption }, updateArgs] = useArgs(); // eslint-disable-line react-hooks/rules-of-hooks
|
|
109
129
|
|
|
110
130
|
return (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
131
|
+
<>
|
|
132
|
+
<Autocomplete
|
|
133
|
+
{...args}
|
|
134
|
+
selectedOption={selectedOption}
|
|
135
|
+
onSelect={(selectedOption) => updateArgs({ selectedOption })}
|
|
136
|
+
renderInput={(inputProps) => (
|
|
137
|
+
<TextField
|
|
138
|
+
{...inputProps}
|
|
139
|
+
label="With Text Field"
|
|
140
|
+
id="autocomplete-input"
|
|
141
|
+
type="text"
|
|
142
|
+
placeholder="Enter a fruit"
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
145
|
+
/>
|
|
146
|
+
<OnInputEventPitfallNotification />
|
|
147
|
+
</>
|
|
125
148
|
);
|
|
126
149
|
},
|
|
127
150
|
tags: ["visual:check"],
|
|
@@ -142,7 +165,14 @@ export const WithSearchField: Story = {
|
|
|
142
165
|
code: `
|
|
143
166
|
<Autocomplete
|
|
144
167
|
selectedOption={selectedOption}
|
|
145
|
-
|
|
168
|
+
/*
|
|
169
|
+
* NOTE! To handle input change events, always use onInputChange on Autocomplete instead of
|
|
170
|
+
* onChange on the input (SearchField). Autocomplete internally uses onChange on the input,
|
|
171
|
+
* and setting it yourself will override this.
|
|
172
|
+
*/
|
|
173
|
+
onInputChange={(value) => {
|
|
174
|
+
setInputValue(value);
|
|
175
|
+
}}
|
|
146
176
|
renderInput={(inputProps) => (
|
|
147
177
|
<SearchField
|
|
148
178
|
{...inputProps}
|
|
@@ -157,33 +187,36 @@ export const WithSearchField: Story = {
|
|
|
157
187
|
const [{ selectedOption }, updateArgs] = useArgs(); // eslint-disable-line react-hooks/rules-of-hooks
|
|
158
188
|
|
|
159
189
|
return (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
190
|
+
<>
|
|
191
|
+
<Autocomplete
|
|
192
|
+
{...args}
|
|
193
|
+
selectedOption={selectedOption}
|
|
194
|
+
onSelect={(selectedOption) => updateArgs({ selectedOption })}
|
|
195
|
+
onInputChange={(value) => {
|
|
196
|
+
setInputValue(value);
|
|
197
|
+
updateArgs({ selectedOption: undefined });
|
|
198
|
+
}}
|
|
199
|
+
inputValue={inputValue}
|
|
200
|
+
renderInput={(inputProps) => (
|
|
201
|
+
<SearchField
|
|
202
|
+
{...inputProps}
|
|
203
|
+
label="With Search Field"
|
|
204
|
+
id="autocomplete-input"
|
|
205
|
+
type="text"
|
|
206
|
+
onClear={() => {
|
|
207
|
+
setInputValue("");
|
|
208
|
+
updateArgs({ selectedOption: undefined });
|
|
209
|
+
}}
|
|
210
|
+
placeholder="Find your fruit"
|
|
211
|
+
clearButtonAllyLabel="Clear search field"
|
|
212
|
+
variant="button-attached"
|
|
213
|
+
iconOnlySearchButton
|
|
214
|
+
searchButtonLabel="Search"
|
|
215
|
+
/>
|
|
216
|
+
)}
|
|
217
|
+
/>
|
|
218
|
+
<OnInputEventPitfallNotification />
|
|
219
|
+
</>
|
|
187
220
|
);
|
|
188
221
|
},
|
|
189
222
|
tags: ["visual:check"],
|
|
@@ -643,4 +643,27 @@ describe("B2xAutocomplete", () => {
|
|
|
643
643
|
expect(input.value).toEqual(options[0].label);
|
|
644
644
|
});
|
|
645
645
|
});
|
|
646
|
+
|
|
647
|
+
it.each([["focus" as const], ["blur" as const], ["keyDown" as const], ["mouseDown" as const]])(
|
|
648
|
+
"should invoke onInput correctly: %s",
|
|
649
|
+
async (eventName) => {
|
|
650
|
+
const onInputEventMock = vi.fn();
|
|
651
|
+
const onInputEventPropName = `onInput${eventName[0].toUpperCase()}${eventName.slice(1)}`;
|
|
652
|
+
render(
|
|
653
|
+
<Autocomplete
|
|
654
|
+
options={options}
|
|
655
|
+
id="test-id"
|
|
656
|
+
data-testid="test-id"
|
|
657
|
+
listboxLabel="Options"
|
|
658
|
+
renderInput={(props) => <input {...props} data-testid="autocomplete-input" />}
|
|
659
|
+
{...{ [onInputEventPropName]: onInputEventMock }}
|
|
660
|
+
/>
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
const input: HTMLInputElement = screen.getByTestId("autocomplete-input");
|
|
664
|
+
fireEvent[eventName](input);
|
|
665
|
+
|
|
666
|
+
expect(onInputEventMock).toBeCalledTimes(1);
|
|
667
|
+
}
|
|
668
|
+
);
|
|
646
669
|
});
|
package/src/autocomplete.tsx
CHANGED
|
@@ -76,8 +76,8 @@ const AutocompleteComponent = <T extends Option>(
|
|
|
76
76
|
type="button"
|
|
77
77
|
className={cx(`${rootClassName}__chevron-button`)}
|
|
78
78
|
onClick={() => {
|
|
79
|
-
inputProps.onFocus();
|
|
80
|
-
inputProps.onMouseDown();
|
|
79
|
+
inputProps.onFocus(undefined);
|
|
80
|
+
inputProps.onMouseDown(undefined);
|
|
81
81
|
}}
|
|
82
82
|
aria-hidden="true"
|
|
83
83
|
>
|
package/src/useAutocomplete.ts
CHANGED
|
@@ -13,8 +13,8 @@ export type Option = {
|
|
|
13
13
|
|
|
14
14
|
export type InputProps = Omit<ComponentPropsWithRef<"input">, "onFocus" | "onMouseDown"> & {
|
|
15
15
|
"data-testid"?: string;
|
|
16
|
-
onFocus: () => void;
|
|
17
|
-
onMouseDown: () => void;
|
|
16
|
+
onFocus: (event: React.FocusEvent<HTMLInputElement> | undefined) => void;
|
|
17
|
+
onMouseDown: (event: React.MouseEvent<HTMLInputElement> | undefined) => void;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export type UseAutocompleteOptions<T extends Option> = {
|
|
@@ -55,9 +55,25 @@ export type UseAutocompleteOptions<T extends Option> = {
|
|
|
55
55
|
*/
|
|
56
56
|
noOptionsText?: ReactNode;
|
|
57
57
|
/*
|
|
58
|
-
* Event handler invoked
|
|
58
|
+
* NOTE! Always use this instead of onBlur directly on the input element. Event handler invoked on input blur.
|
|
59
|
+
*/
|
|
60
|
+
onInputBlur?: React.FocusEventHandler<HTMLInputElement>;
|
|
61
|
+
/*
|
|
62
|
+
* NOTE! Always use this instead of onChange directly on the input element. Event handler invoked when the input value changes.
|
|
59
63
|
*/
|
|
60
64
|
onInputChange?: (value: string) => void;
|
|
65
|
+
/*
|
|
66
|
+
* NOTE! Always use this instead of onFocus directly on the input element. Event handler invoked on input focus.
|
|
67
|
+
*/
|
|
68
|
+
onInputFocus?: (event: React.FocusEvent<HTMLInputElement> | undefined) => undefined;
|
|
69
|
+
/*
|
|
70
|
+
* NOTE! Always use this instead of onKeyDown directly on the input element. Event handler invoked on input key down.
|
|
71
|
+
*/
|
|
72
|
+
onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
|
73
|
+
/*
|
|
74
|
+
* NOTE! Always use this instead of onMouseDown directly on the input element. Event handler invoked on input mouse down.
|
|
75
|
+
*/
|
|
76
|
+
onInputMouseDown?: (event: React.MouseEvent<HTMLInputElement> | undefined) => undefined;
|
|
61
77
|
/*
|
|
62
78
|
* Set to open the listbox when input gets focus.
|
|
63
79
|
*/
|
|
@@ -86,7 +102,11 @@ export const useAutocomplete = <T extends Option>({
|
|
|
86
102
|
id,
|
|
87
103
|
listboxLabel,
|
|
88
104
|
listboxMaxHeight,
|
|
105
|
+
onInputBlur,
|
|
89
106
|
onInputChange,
|
|
107
|
+
onInputFocus,
|
|
108
|
+
onInputKeyDown,
|
|
109
|
+
onInputMouseDown,
|
|
90
110
|
openOnFocus,
|
|
91
111
|
noOptionsText,
|
|
92
112
|
onSelect,
|
|
@@ -204,12 +224,13 @@ export const useAutocomplete = <T extends Option>({
|
|
|
204
224
|
nextOption && scrollOptionIntoView(optionRefs.current[nextOption.id]);
|
|
205
225
|
};
|
|
206
226
|
|
|
207
|
-
const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (
|
|
208
|
-
|
|
227
|
+
const handleOnKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
|
|
228
|
+
onInputKeyDown?.(event);
|
|
229
|
+
switch (event.key) {
|
|
209
230
|
case "ArrowUp":
|
|
210
231
|
case "ArrowDown":
|
|
211
|
-
|
|
212
|
-
highlightNextOption(
|
|
232
|
+
event.preventDefault(); // Preventing default to not move cursor in input
|
|
233
|
+
highlightNextOption(event.key);
|
|
213
234
|
break;
|
|
214
235
|
case "Enter": {
|
|
215
236
|
const optionToSelect = highlightedOption || (highlightFirstOption ? options[0] : undefined);
|
|
@@ -234,16 +255,19 @@ export const useAutocomplete = <T extends Option>({
|
|
|
234
255
|
scrollOptionIntoView(optionRefs.current[nextOptionsToShow[0].id]);
|
|
235
256
|
};
|
|
236
257
|
|
|
237
|
-
const handleOnMouseDown = () => {
|
|
258
|
+
const handleOnMouseDown = (event: React.MouseEvent<HTMLInputElement> | undefined) => {
|
|
259
|
+
onInputMouseDown?.(event);
|
|
238
260
|
showListbox ? closeListbox() : openListbox({ eventType: "CLICK" });
|
|
239
261
|
};
|
|
240
262
|
|
|
241
|
-
const handleOnFocus = () => {
|
|
263
|
+
const handleOnFocus = (event: React.FocusEvent<HTMLInputElement> | undefined) => {
|
|
264
|
+
onInputFocus?.(event);
|
|
242
265
|
!listboxIsOpen && openOnFocus && openListbox({ eventType: "KEYBOARD" });
|
|
243
266
|
inputRef.current?.select();
|
|
244
267
|
};
|
|
245
268
|
|
|
246
|
-
const handleOnBlur = () => {
|
|
269
|
+
const handleOnBlur: React.FocusEventHandler<HTMLInputElement> = (event) => {
|
|
270
|
+
onInputBlur?.(event);
|
|
247
271
|
if (combobox) {
|
|
248
272
|
// Use a timeout to allow click events on the listbox to fire before this check
|
|
249
273
|
setTimeout(() => {
|