react-core-ts 1.8.8 → 1.9.0
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/ExpandableAutoComplete.js +74 -28
- package/dist/ExpandableAutoComplete.js.map +1 -1
- package/dist/commontypes.d.ts +1 -0
- package/dist/components/InputActions.d.ts +2 -1
- package/dist/components/InputActions.js +3 -2
- package/dist/components/InputActions.js.map +1 -1
- package/dist/styles/components/selectedautocomplete.css +3 -0
- package/package.json +1 -1
- package/src/ExpandableAutoComplete.tsx +150 -53
- package/src/commontypes.ts +1 -0
- package/src/components/InputActions.tsx +30 -27
- package/src/styles/components/selectedautocomplete.css +3 -0
- package/dist/styles/styles/components/autocomplete.css +0 -688
- package/dist/styles/styles/components/selectedautocomplete.css +0 -130
- package/dist/styles/styles/components/tooltip.css +0 -497
- package/dist/styles/styles/components/treedropdown.css +0 -97
- package/dist/styles/styles/global.css +0 -8
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from 'react';
|
|
2
9
|
import ReactDOM from 'react-dom';
|
|
3
10
|
|
|
4
11
|
import { AutoSuggestionInputProps } from './commontypes';
|
|
@@ -9,7 +16,7 @@ import { debounce } from './utilities/debounce';
|
|
|
9
16
|
import { deepEqual } from './utilities/deepEqual';
|
|
10
17
|
import { default as Tooltip } from './utilities/expandableTootltip';
|
|
11
18
|
import { filterSuggestions } from './utilities/filterSuggestions';
|
|
12
|
-
import { Search, Spinner } from './utilities/icons';
|
|
19
|
+
import { AllDropArrow, Search, Spinner } from './utilities/icons';
|
|
13
20
|
|
|
14
21
|
type ValueProps = {
|
|
15
22
|
[key: string]: string;
|
|
@@ -54,7 +61,9 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
54
61
|
scrollRef,
|
|
55
62
|
isTreeDropdown = false,
|
|
56
63
|
shortCode = '',
|
|
57
|
-
labelCode = ''
|
|
64
|
+
labelCode = '',
|
|
65
|
+
typeOnlyFetch = false,
|
|
66
|
+
autoDropdown = false,
|
|
58
67
|
},
|
|
59
68
|
ref
|
|
60
69
|
) => {
|
|
@@ -70,9 +79,13 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
70
79
|
const [focusedIndex, setFocusedIndex] = useState(0);
|
|
71
80
|
const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
|
|
72
81
|
const itemsRef = useRef<HTMLDivElement>(null);
|
|
82
|
+
const dropBtnRef = useRef<HTMLButtonElement>(null);
|
|
83
|
+
const [refetchData, setRefetchData] = useState(false);
|
|
84
|
+
|
|
73
85
|
// API call for suggestions through a custom hook
|
|
74
86
|
const inputRef = useRef(null);
|
|
75
87
|
const dropRef = useRef(null);
|
|
88
|
+
const typeRef = useRef(0);
|
|
76
89
|
useImperativeHandle(ref, () => inputRef.current);
|
|
77
90
|
const [dropdownStyle, setDropdownStyle] = useState({
|
|
78
91
|
top: 0,
|
|
@@ -126,39 +139,51 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
126
139
|
inputValue,
|
|
127
140
|
isMultiple,
|
|
128
141
|
setNextPage,
|
|
129
|
-
selectedItems
|
|
142
|
+
selectedItems,
|
|
143
|
+
typeOnlyFetch
|
|
130
144
|
// nextBlock
|
|
131
145
|
);
|
|
132
146
|
|
|
133
147
|
// Handling the selection of a suggestion
|
|
134
|
-
const handleSuggestionClick = useCallback(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
148
|
+
const handleSuggestionClick = useCallback(
|
|
149
|
+
(suggestion: ValueProps, idx: number) => {
|
|
150
|
+
if (isMultiple) {
|
|
151
|
+
setFocusedIndex(idx);
|
|
152
|
+
setSelectedItems((prev) => {
|
|
153
|
+
const isAdded = prev.some(
|
|
154
|
+
(item) => item[descId] === suggestion[descId]
|
|
155
|
+
);
|
|
156
|
+
if (isAdded) {
|
|
157
|
+
return prev.filter((item) => item[descId] !== suggestion[descId]);
|
|
158
|
+
} else {
|
|
159
|
+
return [...prev, suggestion];
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
} else {
|
|
163
|
+
setFocusedIndex(idx);
|
|
164
|
+
setInputValue(suggestion[desc]);
|
|
165
|
+
setSearchValue('');
|
|
166
|
+
onChange(suggestion);
|
|
167
|
+
setDropOpen(false);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
[]
|
|
171
|
+
);
|
|
155
172
|
|
|
156
173
|
// Adding debounce to avoid making API calls on every keystroke
|
|
157
|
-
const
|
|
174
|
+
const debouncedUpdate = useCallback(
|
|
175
|
+
debounce((value: string) => {
|
|
176
|
+
handlePickSuggestions(value, 1, false);
|
|
177
|
+
typeRef.current = 0;
|
|
178
|
+
}, 500),
|
|
179
|
+
[]
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const handleChangeWithDebounce = (value: string) => {
|
|
158
183
|
if ((type === 'auto_complete' || type === 'auto_suggestion') && async) {
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
}
|
|
184
|
+
debouncedUpdate(value);
|
|
185
|
+
} else typeRef.current = 0;
|
|
186
|
+
};
|
|
162
187
|
|
|
163
188
|
const handleMultiSelect = (e: any, suggestion: ValueProps) => {
|
|
164
189
|
const { checked } = e.target;
|
|
@@ -194,9 +219,10 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
194
219
|
const { value } = e.target;
|
|
195
220
|
setDropOpen(true);
|
|
196
221
|
setSearchValue(value);
|
|
222
|
+
typeRef.current = 1;
|
|
197
223
|
handleChangeWithDebounce(value);
|
|
198
224
|
if (!value) {
|
|
199
|
-
setInputValue('');
|
|
225
|
+
if (!typeOnlyFetch) setInputValue('');
|
|
200
226
|
// onChange({ [descId]: '', [desc]: '' });
|
|
201
227
|
}
|
|
202
228
|
};
|
|
@@ -253,7 +279,7 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
253
279
|
) {
|
|
254
280
|
setTimeout(() => {
|
|
255
281
|
setDropOpen(false);
|
|
256
|
-
setSearchValue('');
|
|
282
|
+
if (!typeOnlyFetch) setSearchValue('');
|
|
257
283
|
}, 200);
|
|
258
284
|
}
|
|
259
285
|
};
|
|
@@ -297,7 +323,6 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
297
323
|
);
|
|
298
324
|
|
|
299
325
|
useEffect(() => {
|
|
300
|
-
|
|
301
326
|
// Handle keyboard navigation
|
|
302
327
|
const handleKeyDown = (e: any) => {
|
|
303
328
|
if (!dropOpen) return;
|
|
@@ -305,49 +330,53 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
305
330
|
const atBottom = focusedIndex === filteredData.length - 1;
|
|
306
331
|
const atTop = focusedIndex === 0;
|
|
307
332
|
switch (e.key) {
|
|
308
|
-
case
|
|
333
|
+
case 'ArrowDown':
|
|
309
334
|
e.preventDefault();
|
|
310
335
|
if (itemsRef.current) {
|
|
311
336
|
if (!atBottom) {
|
|
312
|
-
|
|
337
|
+
itemsRef.current.scrollTop +=
|
|
338
|
+
itemRefs.current[focusedIndex]?.offsetHeight || 50;
|
|
313
339
|
} else {
|
|
314
|
-
|
|
340
|
+
itemsRef.current.scrollTop = 0;
|
|
315
341
|
}
|
|
316
342
|
}
|
|
317
343
|
setFocusedIndex((prev) => (prev + 1) % filteredData?.length);
|
|
318
344
|
break;
|
|
319
|
-
|
|
320
|
-
case
|
|
345
|
+
|
|
346
|
+
case 'ArrowUp':
|
|
321
347
|
e.preventDefault();
|
|
322
348
|
if (itemsRef.current) {
|
|
323
349
|
if (!atTop) {
|
|
324
|
-
|
|
350
|
+
itemsRef.current.scrollTop -=
|
|
351
|
+
itemRefs.current[focusedIndex]?.offsetHeight || 50;
|
|
325
352
|
} else {
|
|
326
|
-
|
|
353
|
+
itemsRef.current.scrollTop = 0;
|
|
327
354
|
}
|
|
328
355
|
}
|
|
329
|
-
setFocusedIndex(
|
|
356
|
+
setFocusedIndex(
|
|
357
|
+
(prev) => (prev - 1 + filteredData?.length) % filteredData?.length
|
|
358
|
+
);
|
|
330
359
|
break;
|
|
331
|
-
|
|
332
|
-
case
|
|
360
|
+
|
|
361
|
+
case 'Enter':
|
|
333
362
|
e.preventDefault();
|
|
334
|
-
handleSuggestionClick(filteredData[focusedIndex], focusedIndex)
|
|
363
|
+
handleSuggestionClick(filteredData[focusedIndex], focusedIndex);
|
|
335
364
|
break;
|
|
336
|
-
|
|
337
|
-
case
|
|
365
|
+
|
|
366
|
+
case 'Escape':
|
|
338
367
|
e.preventDefault();
|
|
339
368
|
setDropOpen(false);
|
|
340
369
|
break;
|
|
341
|
-
|
|
370
|
+
|
|
342
371
|
default:
|
|
343
372
|
break;
|
|
344
373
|
}
|
|
345
374
|
};
|
|
346
|
-
|
|
347
|
-
window.addEventListener(
|
|
348
|
-
|
|
375
|
+
|
|
376
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
377
|
+
|
|
349
378
|
return () => {
|
|
350
|
-
window.removeEventListener(
|
|
379
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
351
380
|
};
|
|
352
381
|
}, [filteredData, dropOpen, isLoading, focusedIndex]);
|
|
353
382
|
|
|
@@ -402,6 +431,38 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
402
431
|
else onChange({ [descId]: '', [desc]: '' });
|
|
403
432
|
};
|
|
404
433
|
|
|
434
|
+
const handleSelectAll = () => {
|
|
435
|
+
if (isMultiple) {
|
|
436
|
+
filteredData.map((suggestion: ValueProps) =>
|
|
437
|
+
setSelectedItems((prev) => {
|
|
438
|
+
const isAdded = prev.some(
|
|
439
|
+
(item) => item[descId] === suggestion[descId]
|
|
440
|
+
);
|
|
441
|
+
if (isAdded) {
|
|
442
|
+
return prev;
|
|
443
|
+
} else {
|
|
444
|
+
return [...prev, suggestion];
|
|
445
|
+
}
|
|
446
|
+
})
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const handleOpenDropdown = (e: any) => {
|
|
452
|
+
if (!suggestions || suggestions?.length === 0 || refetchData) {
|
|
453
|
+
if (autoDropdown && (inputValue === '' || inputValue.trim() === '')) {
|
|
454
|
+
handlePickSuggestions('a', 1);
|
|
455
|
+
setRefetchData(false);
|
|
456
|
+
} else if (!refetchData && inputValue !== '') {
|
|
457
|
+
handlePickSuggestions(inputValue, 1);
|
|
458
|
+
setRefetchData(true);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (!isLoading) {
|
|
462
|
+
setDropOpen(!dropOpen);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
405
466
|
return (
|
|
406
467
|
<div
|
|
407
468
|
id={id ? `expandable-container-${id}` : `expandable-container-${name}`}
|
|
@@ -513,10 +574,30 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
513
574
|
/>
|
|
514
575
|
</div>
|
|
515
576
|
|
|
577
|
+
<>
|
|
578
|
+
{autoDropdown && !disabled && !readOnly && (
|
|
579
|
+
<button
|
|
580
|
+
disabled={disabled ?? readOnly}
|
|
581
|
+
onClick={(e) => handleOpenDropdown(e)}
|
|
582
|
+
className=" text-[#667085] focus-visible:outline-slate-100 absolute right-2"
|
|
583
|
+
data-testid="drop-arrow"
|
|
584
|
+
type="button"
|
|
585
|
+
id="autocomplete-drop-icon"
|
|
586
|
+
ref={dropBtnRef}
|
|
587
|
+
>
|
|
588
|
+
<AllDropArrow
|
|
589
|
+
type={!dropOpen ? 'down' : 'up'}
|
|
590
|
+
uniqueId="all-dropdow-arrow-icon"
|
|
591
|
+
className="all-dropdow-arrow-icon"
|
|
592
|
+
/>
|
|
593
|
+
</button>
|
|
594
|
+
)}
|
|
595
|
+
</>
|
|
596
|
+
|
|
516
597
|
{selectedItems?.length > 1 && (
|
|
517
598
|
<div
|
|
518
599
|
id="expandable-clear-all"
|
|
519
|
-
className={`qbs-clear-link qbs-text-right qbs-cursor-pointer qbs-text-xs absolute right-2 bottom-
|
|
600
|
+
className={`qbs-clear-link qbs-text-right qbs-cursor-pointer qbs-text-xs absolute right-2 qbs-bottom-0`}
|
|
520
601
|
onClick={handleClearSelected}
|
|
521
602
|
>
|
|
522
603
|
Clear all
|
|
@@ -536,6 +617,7 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
536
617
|
expandable={expandable}
|
|
537
618
|
handleClear={handleClear}
|
|
538
619
|
uniqueDropArrowId="drop-arrow-expanded-list-icon"
|
|
620
|
+
autoDropdown={autoDropdown}
|
|
539
621
|
/>
|
|
540
622
|
{/* Displaying Loading Spinner */}
|
|
541
623
|
|
|
@@ -571,7 +653,10 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
571
653
|
</div>
|
|
572
654
|
)}
|
|
573
655
|
|
|
574
|
-
<div
|
|
656
|
+
<div
|
|
657
|
+
className={`qbs-autocomplete-suggestions-sub `}
|
|
658
|
+
ref={itemsRef}
|
|
659
|
+
>
|
|
575
660
|
{filteredData?.length > 0 ? (
|
|
576
661
|
filteredData.map((suggestion: ValueProps, idx: number) => (
|
|
577
662
|
<DropdownList
|
|
@@ -610,7 +695,10 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
610
695
|
className="qbs-autocomplete-notfound"
|
|
611
696
|
onClick={handleBlur}
|
|
612
697
|
>
|
|
613
|
-
{notDataMessage ??
|
|
698
|
+
{notDataMessage ??
|
|
699
|
+
(searchValue === '' || typeRef.current === 1)
|
|
700
|
+
? 'Start typing to see suggestions'
|
|
701
|
+
: 'No Results Found'}
|
|
614
702
|
</li>
|
|
615
703
|
)}
|
|
616
704
|
</>
|
|
@@ -627,6 +715,15 @@ const ExpandableAutoComplete = forwardRef<
|
|
|
627
715
|
</div>
|
|
628
716
|
)}
|
|
629
717
|
</div>
|
|
718
|
+
{filteredData?.length > 0 && (
|
|
719
|
+
<div
|
|
720
|
+
id="select-all"
|
|
721
|
+
className={`qbs-select-all-link qbs-text-right qbs-cursor-pointer qbs-text-xs absolute right-2 bottom-1`}
|
|
722
|
+
onClick={handleSelectAll}
|
|
723
|
+
>
|
|
724
|
+
Select all
|
|
725
|
+
</div>
|
|
726
|
+
)}
|
|
630
727
|
</ul>,
|
|
631
728
|
document.body
|
|
632
729
|
)}
|
package/src/commontypes.ts
CHANGED
|
@@ -81,6 +81,7 @@ export interface AutoSuggestionInputProps {
|
|
|
81
81
|
labelCode?: string,
|
|
82
82
|
tabInlineSearch?: boolean // tab dropdown search
|
|
83
83
|
matchFromStart?: boolean // match data's from the starting position
|
|
84
|
+
autoDropdown?: boolean;
|
|
84
85
|
}
|
|
85
86
|
export interface IconsProps {
|
|
86
87
|
name: any;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { Close, DropArrow } from
|
|
3
|
+
import { Close, DropArrow } from '../utilities/icons';
|
|
4
4
|
|
|
5
5
|
type ValueProps = {
|
|
6
6
|
inputValue: string;
|
|
@@ -16,6 +16,7 @@ type ValueProps = {
|
|
|
16
16
|
error?: boolean;
|
|
17
17
|
viewMode?: boolean;
|
|
18
18
|
uniqueDropArrowId?: string;
|
|
19
|
+
autoDropdown?: boolean;
|
|
19
20
|
};
|
|
20
21
|
const InputActions: React.FC<ValueProps> = ({
|
|
21
22
|
inputValue,
|
|
@@ -31,6 +32,7 @@ const InputActions: React.FC<ValueProps> = ({
|
|
|
31
32
|
error,
|
|
32
33
|
viewMode,
|
|
33
34
|
uniqueDropArrowId,
|
|
35
|
+
autoDropdown = false,
|
|
34
36
|
}) => {
|
|
35
37
|
return (
|
|
36
38
|
<div
|
|
@@ -54,31 +56,32 @@ const InputActions: React.FC<ValueProps> = ({
|
|
|
54
56
|
<Close />
|
|
55
57
|
</button>
|
|
56
58
|
)}
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
59
|
+
{!autoDropdown &&
|
|
60
|
+
(dropOpen ? (
|
|
61
|
+
<button
|
|
62
|
+
type="button"
|
|
63
|
+
onClick={(e) => handleDropClose(e)}
|
|
64
|
+
className="icon-button text-[#667085] "
|
|
65
|
+
aria-label="toggle"
|
|
66
|
+
name="toggle"
|
|
67
|
+
>
|
|
68
|
+
<DropArrow
|
|
69
|
+
className={`icon-button-rotate`}
|
|
70
|
+
uniqueId={uniqueDropArrowId}
|
|
71
|
+
/>
|
|
72
|
+
</button>
|
|
73
|
+
) : (
|
|
74
|
+
<button
|
|
75
|
+
disabled={(disabled || readOnly) && !viewMode}
|
|
76
|
+
type="button"
|
|
77
|
+
className="icon-button text-[#667085] "
|
|
78
|
+
onClick={(e) => handleDropOpen(e)}
|
|
79
|
+
aria-label="toggle"
|
|
80
|
+
name="toggle"
|
|
81
|
+
>
|
|
82
|
+
<DropArrow uniqueId={uniqueDropArrowId} />
|
|
83
|
+
</button>
|
|
84
|
+
))}
|
|
82
85
|
</div>
|
|
83
86
|
);
|
|
84
87
|
};
|