react-core-ts 1.0.42 → 1.0.44
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/README.md +50 -0
- package/dist/AutoComplete.d.ts +2 -2
- package/dist/AutoComplete.js +44 -37
- package/dist/AutoComplete.js.map +1 -1
- package/dist/AutoCompleteWithSelectedList.d.ts +4 -0
- package/dist/AutoCompleteWithSelectedList.js +446 -0
- package/dist/AutoCompleteWithSelectedList.js.map +1 -0
- package/dist/ExpandableAutoComplete.js +12 -5
- package/dist/ExpandableAutoComplete.js.map +1 -1
- package/dist/commontypes.d.ts +11 -4
- package/dist/components/DropdownList.js +2 -2
- package/dist/components/DropdownList.js.map +1 -1
- package/dist/components/InputActions.d.ts +1 -0
- package/dist/components/InputActions.js +2 -2
- package/dist/components/InputActions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/styles/components/autocomplete.css +18 -1
- package/dist/styles/components/selectedautocomplete.css +121 -0
- package/dist/styles/global.css +2 -1
- package/dist/utilities/autosuggestions.d.ts +2 -2
- package/dist/utilities/autosuggestions.js +10 -7
- package/dist/utilities/autosuggestions.js.map +1 -1
- package/dist/utilities/filterSuggestions.d.ts +1 -1
- package/dist/utilities/filterSuggestions.js +10 -5
- package/dist/utilities/filterSuggestions.js.map +1 -1
- package/docs/App.tsx +96 -4
- package/docs/index.html +1 -1
- package/package.json +1 -1
- package/src/AutoComplete.tsx +66 -51
- package/src/AutoCompleteWithSelectedList.tsx +677 -0
- package/src/ExpandableAutoComplete.tsx +13 -5
- package/src/commontypes.ts +14 -6
- package/src/components/DropdownList.tsx +3 -3
- package/src/components/InputActions.tsx +3 -1
- package/src/index.html +1 -1
- package/src/index.tsx +1 -0
- package/src/styles/components/autocomplete.css +18 -1
- package/src/styles/components/selectedautocomplete.css +121 -0
- package/src/styles/global.css +2 -1
- package/src/utilities/autosuggestions.ts +18 -12
- package/src/utilities/filterSuggestions.ts +10 -7
package/src/AutoComplete.tsx
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import Tooltip from
|
|
2
|
-
import React, {
|
|
1
|
+
import Tooltip from "./utilities/tooltip";
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react";
|
|
3
10
|
|
|
4
|
-
import { AutoSuggestionInputProps } from
|
|
5
|
-
import { useSuggestions } from
|
|
6
|
-
import { debounce } from
|
|
7
|
-
import { deepEqual } from
|
|
8
|
-
import { filterSuggestions } from
|
|
9
|
-
import { Close, DropArrow, Search, Spinner } from
|
|
11
|
+
import { AutoSuggestionInputProps } from "./commontypes";
|
|
12
|
+
import { useSuggestions } from "./utilities/autosuggestions";
|
|
13
|
+
import { debounce } from "./utilities/debounce";
|
|
14
|
+
import { deepEqual } from "./utilities/deepEqual";
|
|
15
|
+
import { filterSuggestions } from "./utilities/filterSuggestions";
|
|
16
|
+
import { Close, DropArrow, Search, Spinner } from "./utilities/icons";
|
|
10
17
|
|
|
11
18
|
type ValueProps = {
|
|
12
19
|
[key: string]: string;
|
|
@@ -24,14 +31,14 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
24
31
|
fullWidth = false,
|
|
25
32
|
placeholder,
|
|
26
33
|
id,
|
|
27
|
-
type =
|
|
34
|
+
type = "custom_select",
|
|
28
35
|
selectedItems: propsSeelctedItems = [],
|
|
29
36
|
readOnly = false,
|
|
30
37
|
disabled = false,
|
|
31
38
|
value,
|
|
32
39
|
isMultiple = false,
|
|
33
|
-
desc =
|
|
34
|
-
descId =
|
|
40
|
+
desc = "name",
|
|
41
|
+
descId = "id",
|
|
35
42
|
singleSelect,
|
|
36
43
|
className,
|
|
37
44
|
async = false,
|
|
@@ -50,12 +57,12 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
50
57
|
const [isInitialRender, setIsInitialRender] = useState(true);
|
|
51
58
|
|
|
52
59
|
const [inputValue, setInputValue] = useState<string>(value);
|
|
53
|
-
const [searchValue, setSearchValue] = useState<string>(
|
|
60
|
+
const [searchValue, setSearchValue] = useState<string>("");
|
|
54
61
|
const [nextPage, setNextPage] = useState<number | undefined>(1);
|
|
55
62
|
const [dropOpen, setDropOpen] = useState<boolean>(false);
|
|
56
63
|
const [selectedItems, setSelectedItems] = useState<ValueProps[]>([]);
|
|
57
64
|
// API call for suggestions through a custom hook
|
|
58
|
-
const [dropdownPosition, setDropdownPosition] = useState(
|
|
65
|
+
const [dropdownPosition, setDropdownPosition] = useState("bottom");
|
|
59
66
|
const inputRef = useRef(null);
|
|
60
67
|
const dropRef = useRef(null);
|
|
61
68
|
useImperativeHandle(ref, () => inputRef.current);
|
|
@@ -68,19 +75,19 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
68
75
|
const spaceAbove = inputBoxRect.top;
|
|
69
76
|
const spaceBelow = viewportHeight - inputBoxRect.bottom;
|
|
70
77
|
if (spaceAbove > spaceBelow) {
|
|
71
|
-
setDropdownPosition(
|
|
78
|
+
setDropdownPosition("top");
|
|
72
79
|
} else {
|
|
73
|
-
setDropdownPosition(
|
|
80
|
+
setDropdownPosition("bottom");
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
83
|
};
|
|
77
84
|
|
|
78
85
|
useEffect(() => {
|
|
79
|
-
window.addEventListener(
|
|
86
|
+
window.addEventListener("resize", adjustDropdownPosition);
|
|
80
87
|
adjustDropdownPosition();
|
|
81
88
|
|
|
82
89
|
return () => {
|
|
83
|
-
window.removeEventListener(
|
|
90
|
+
window.removeEventListener("resize", adjustDropdownPosition);
|
|
84
91
|
};
|
|
85
92
|
}, [dropOpen]);
|
|
86
93
|
|
|
@@ -101,19 +108,27 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
101
108
|
// Handling the selection of a suggestion
|
|
102
109
|
const handleSuggestionClick = useCallback((suggestion: ValueProps) => {
|
|
103
110
|
if (isMultiple) {
|
|
104
|
-
setSelectedItems((prev) =>
|
|
111
|
+
setSelectedItems((prev) => {
|
|
112
|
+
const isAdded = prev.some(
|
|
113
|
+
(item) => item[descId] === suggestion[descId]
|
|
114
|
+
);
|
|
115
|
+
if (isAdded) {
|
|
116
|
+
return prev.filter((item) => item[descId] !== suggestion[descId]);
|
|
117
|
+
} else {
|
|
118
|
+
return [...prev, suggestion];
|
|
119
|
+
}
|
|
120
|
+
});
|
|
105
121
|
} else {
|
|
106
122
|
setInputValue(suggestion[desc]);
|
|
123
|
+
setSearchValue("");
|
|
124
|
+
onChange(suggestion);
|
|
125
|
+
setDropOpen(false);
|
|
107
126
|
}
|
|
108
|
-
setSearchValue('');
|
|
109
|
-
setInputValue(suggestion[desc]);
|
|
110
|
-
onChange(suggestion);
|
|
111
|
-
setDropOpen(false);
|
|
112
127
|
}, []);
|
|
113
128
|
|
|
114
129
|
// Adding debounce to avoid making API calls on every keystroke
|
|
115
130
|
const handleChangeWithDebounce = debounce((value) => {
|
|
116
|
-
if ((type ===
|
|
131
|
+
if ((type === "auto_complete" || type === "auto_suggestion") && async) {
|
|
117
132
|
handlePickSuggestions(value, 1);
|
|
118
133
|
}
|
|
119
134
|
}, 1000);
|
|
@@ -135,7 +150,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
135
150
|
setInputValue(suggestion[desc]);
|
|
136
151
|
onChange(suggestion);
|
|
137
152
|
} else {
|
|
138
|
-
setInputValue(
|
|
153
|
+
setInputValue("");
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
156
|
};
|
|
@@ -145,7 +160,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
145
160
|
}, [propsSeelctedItems]);
|
|
146
161
|
// Effect to set the input value whenever `value` prop changes
|
|
147
162
|
useEffect(() => {
|
|
148
|
-
setInputValue(value ??
|
|
163
|
+
setInputValue(value ?? "");
|
|
149
164
|
}, [value]);
|
|
150
165
|
|
|
151
166
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -154,8 +169,8 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
154
169
|
setSearchValue(value);
|
|
155
170
|
handleChangeWithDebounce(value);
|
|
156
171
|
if (!value) {
|
|
157
|
-
setInputValue(
|
|
158
|
-
onChange({ [descId]:
|
|
172
|
+
setInputValue("");
|
|
173
|
+
onChange({ [descId]: "", [desc]: "" });
|
|
159
174
|
}
|
|
160
175
|
};
|
|
161
176
|
const handleSuggestionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -173,18 +188,18 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
173
188
|
|
|
174
189
|
const handleClear = () => {
|
|
175
190
|
if (searchValue) {
|
|
176
|
-
setSearchValue(
|
|
191
|
+
setSearchValue("");
|
|
177
192
|
setDropOpen(false);
|
|
178
193
|
} else {
|
|
179
|
-
setInputValue(
|
|
180
|
-
onChange({ [descId]:
|
|
194
|
+
setInputValue("");
|
|
195
|
+
onChange({ [descId]: "", [desc]: "" });
|
|
181
196
|
setDropOpen(false);
|
|
182
197
|
}
|
|
183
198
|
};
|
|
184
199
|
|
|
185
200
|
const generateClassName = useCallback(() => {
|
|
186
201
|
return `qbs-textfield-default ${className} ${
|
|
187
|
-
errors && errors?.message ?
|
|
202
|
+
errors && errors?.message ? "textfield-error" : "textfield"
|
|
188
203
|
}`;
|
|
189
204
|
}, [errors, name]);
|
|
190
205
|
const handleRemoveSelectedItem = (index: number) => {
|
|
@@ -209,12 +224,12 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
209
224
|
!dropdownRef.current.contains(event.target)
|
|
210
225
|
) {
|
|
211
226
|
setDropOpen(false);
|
|
212
|
-
setSearchValue(
|
|
227
|
+
setSearchValue("");
|
|
213
228
|
}
|
|
214
229
|
};
|
|
215
|
-
document.addEventListener(
|
|
230
|
+
document.addEventListener("mousedown", handleClickOutside as any);
|
|
216
231
|
return () => {
|
|
217
|
-
document.removeEventListener(
|
|
232
|
+
document.removeEventListener("mousedown", handleClickOutside as any);
|
|
218
233
|
};
|
|
219
234
|
}, []);
|
|
220
235
|
|
|
@@ -249,24 +264,24 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
249
264
|
};
|
|
250
265
|
|
|
251
266
|
const handleOnClick = () => {
|
|
252
|
-
!disabled && !readOnly ? setDropOpen(true) :
|
|
267
|
+
!disabled && !readOnly ? setDropOpen(true) : "";
|
|
253
268
|
};
|
|
254
269
|
const tooltipContent =
|
|
255
270
|
selectedItems?.length > 1
|
|
256
271
|
? selectedItems
|
|
257
272
|
?.slice(1)
|
|
258
273
|
.map((item) => item[desc])
|
|
259
|
-
.join(
|
|
260
|
-
:
|
|
274
|
+
.join(", ")
|
|
275
|
+
: "";
|
|
261
276
|
|
|
262
277
|
return (
|
|
263
|
-
<div className={fullWidth ?
|
|
278
|
+
<div className={fullWidth ? "fullWidth" : "autoWidth"} ref={dropdownRef}>
|
|
264
279
|
{label && (
|
|
265
280
|
<div
|
|
266
281
|
style={{
|
|
267
282
|
marginBottom: 5,
|
|
268
|
-
display:
|
|
269
|
-
justifyContent:
|
|
283
|
+
display: "flex",
|
|
284
|
+
justifyContent: "space-between",
|
|
270
285
|
}}
|
|
271
286
|
>
|
|
272
287
|
<label className={`labels label-text`}>
|
|
@@ -280,7 +295,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
280
295
|
)}
|
|
281
296
|
{/* Displaying selected items for multi-select */}
|
|
282
297
|
|
|
283
|
-
<div style={{ position:
|
|
298
|
+
<div style={{ position: "relative" }}>
|
|
284
299
|
<div className="selected-items-container ">
|
|
285
300
|
{selectedItems?.length > 0 && (
|
|
286
301
|
<>
|
|
@@ -313,7 +328,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
313
328
|
ref={inputRef}
|
|
314
329
|
type="text"
|
|
315
330
|
value={
|
|
316
|
-
type ===
|
|
331
|
+
type === "auto_suggestion"
|
|
317
332
|
? inputValue
|
|
318
333
|
: searchValue || inputValue
|
|
319
334
|
}
|
|
@@ -322,9 +337,9 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
322
337
|
onFocus={onFocus}
|
|
323
338
|
onClick={() => handleOnClick()}
|
|
324
339
|
className={generateClassName()}
|
|
325
|
-
placeholder={selectedItems?.length > 0 ?
|
|
340
|
+
placeholder={selectedItems?.length > 0 ? "" : placeholder ?? ""}
|
|
326
341
|
readOnly={
|
|
327
|
-
readOnly || type ===
|
|
342
|
+
readOnly || type === "custom_select" || type == "auto_suggestion"
|
|
328
343
|
}
|
|
329
344
|
disabled={disabled}
|
|
330
345
|
data-testid="custom-autocomplete"
|
|
@@ -361,9 +376,9 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
361
376
|
ref={dropRef}
|
|
362
377
|
className={`qbs-autocomplete-suggestions ${dropdownPosition}`}
|
|
363
378
|
>
|
|
364
|
-
{type ==
|
|
379
|
+
{type == "auto_suggestion" && (
|
|
365
380
|
<div
|
|
366
|
-
style={{ position:
|
|
381
|
+
style={{ position: "relative" }}
|
|
367
382
|
className="react-core-ts-search-container"
|
|
368
383
|
>
|
|
369
384
|
<span className="dropdown-search-icon">
|
|
@@ -395,9 +410,9 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
395
410
|
key={idx.toString()}
|
|
396
411
|
className={`qbs-autocomplete-listitem-container ${
|
|
397
412
|
(isMultiple || singleSelect) &&
|
|
398
|
-
|
|
413
|
+
"qbs-autocomplete-checkbox-container"
|
|
399
414
|
} ${
|
|
400
|
-
isSelected(suggestion, selected) ?
|
|
415
|
+
isSelected(suggestion, selected) ? "is-selected" : ""
|
|
401
416
|
}`}
|
|
402
417
|
>
|
|
403
418
|
{(isMultiple || singleSelect) && (
|
|
@@ -427,7 +442,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
427
442
|
<li
|
|
428
443
|
key={idx}
|
|
429
444
|
className={`qbs-autocomplete-suggestions-item ${
|
|
430
|
-
isSelected(suggestion, selected) ?
|
|
445
|
+
isSelected(suggestion, selected) ? "is-selected" : ""
|
|
431
446
|
}`}
|
|
432
447
|
onClick={() => handleSuggestionClick(suggestion)}
|
|
433
448
|
data-testid={suggestion[desc]}
|
|
@@ -440,7 +455,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
440
455
|
<>
|
|
441
456
|
{isLoading ? (
|
|
442
457
|
<div
|
|
443
|
-
style={{ display:
|
|
458
|
+
style={{ display: "flex", justifyContent: "center" }}
|
|
444
459
|
>
|
|
445
460
|
<span>
|
|
446
461
|
<Spinner />
|
|
@@ -451,7 +466,7 @@ const AutoComplete = forwardRef<HTMLInputElement, AutoSuggestionInputProps>(
|
|
|
451
466
|
className="qbs-autocomplete-notfound"
|
|
452
467
|
onClick={handleBlur}
|
|
453
468
|
>
|
|
454
|
-
{notDataMessage ??
|
|
469
|
+
{notDataMessage ?? "No Results Found"}
|
|
455
470
|
</li>
|
|
456
471
|
)}
|
|
457
472
|
</>
|