react-core-ts 2.1.31 → 2.1.33
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 +59 -0
- package/dist/AutoComplete.js +1 -1
- package/dist/AutoComplete.js.map +1 -1
- package/dist/AutoCompleteWithSelectedList.js +1 -1
- package/dist/AutoCompleteWithSelectedList.js.map +1 -1
- package/dist/AutoCompleteWithTabFilter.js +1 -1
- package/dist/AutoCompleteWithTabFilter.js.map +1 -1
- package/dist/AutoCompleteWithTreeStructure.js +1 -1
- package/dist/AutoCompleteWithTreeStructure.js.map +1 -1
- package/dist/ExpandableAutoComplete.js +1 -1
- package/dist/ExpandableAutoComplete.js.map +1 -1
- package/dist/ReactAutoCompleteTableView.d.ts +23 -0
- package/dist/ReactAutoCompleteTableView.js +164 -53
- package/dist/ReactAutoCompleteTableView.js.map +1 -1
- package/dist/dropdownFilterTabs.js +1 -1
- package/dist/dropdownFilterTabs.js.map +1 -1
- package/dist/dummyAutoCompleteWithSelectedList.js +1 -1
- package/dist/dummyAutoCompleteWithSelectedList.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/styles/components/autocomplete.css +69 -0
- package/dist/styles/styles/components/autocomplete.css +69 -0
- package/dist/utilities/autosuggestions.d.ts +3 -1
- package/dist/utilities/autosuggestions.js +16 -12
- package/dist/utilities/autosuggestions.js.map +1 -1
- package/docs/App.tsx +62 -1
- package/package.json +1 -1
- package/src/AutoComplete.tsx +1 -1
- package/src/AutoCompleteWithSelectedList.tsx +1 -1
- package/src/AutoCompleteWithTabFilter.tsx +1 -1
- package/src/AutoCompleteWithTreeStructure.tsx +1 -1
- package/src/ExpandableAutoComplete.tsx +1 -1
- package/src/ReactAutoCompleteTableView.tsx +298 -80
- package/src/dropdownFilterTabs.tsx +1 -1
- package/src/dummyAutoCompleteWithSelectedList.tsx +1 -1
- package/src/index.tsx +5 -0
- package/src/styles/components/autocomplete.css +69 -0
- package/src/utilities/autosuggestions.ts +22 -16
|
@@ -24,6 +24,26 @@ type valueProps = {
|
|
|
24
24
|
param4?: string | number | null;
|
|
25
25
|
from?: number;
|
|
26
26
|
};
|
|
27
|
+
|
|
28
|
+
/** Add new theme ids here when introducing layouts */
|
|
29
|
+
export type DropdownThemeId = 'default' | 'splitDetail';
|
|
30
|
+
|
|
31
|
+
/** Options for `dropdownTheme: 'splitDetail'` (title + subtitle + optional badge pill) */
|
|
32
|
+
export type SplitDetailThemeConfig = {
|
|
33
|
+
subtitleKey?: string;
|
|
34
|
+
badgeKey?: string;
|
|
35
|
+
/** Shown before badge value, e.g. "Acc. No.: " */
|
|
36
|
+
badgePrefix?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Per-theme configuration. Extend this type with new keys when adding themes
|
|
41
|
+
* (e.g. `compact?: CompactThemeConfig`).
|
|
42
|
+
*/
|
|
43
|
+
export type DropdownThemeConfig = {
|
|
44
|
+
splitDetail?: SplitDetailThemeConfig;
|
|
45
|
+
};
|
|
46
|
+
|
|
27
47
|
interface AutoSuggestionInputProps {
|
|
28
48
|
id?: string;
|
|
29
49
|
label?: string;
|
|
@@ -68,6 +88,13 @@ interface AutoSuggestionInputProps {
|
|
|
68
88
|
key: string; // Field name in the suggestion object
|
|
69
89
|
label: string; // Label for the column
|
|
70
90
|
}>; // Column header to display
|
|
91
|
+
dropdownTheme?: DropdownThemeId;
|
|
92
|
+
/** Theme-specific field mapping and options; see `DropdownThemeConfig` */
|
|
93
|
+
dropdownThemeConfig?: DropdownThemeConfig;
|
|
94
|
+
/**
|
|
95
|
+
* When true, typing updates the input only; fetching/opening the list runs from the search control (and Enter), not while typing.
|
|
96
|
+
*/
|
|
97
|
+
searchOnButtonOnly?: boolean;
|
|
71
98
|
}
|
|
72
99
|
|
|
73
100
|
const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
@@ -106,7 +133,16 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
106
133
|
tableView = false,
|
|
107
134
|
additionalColumns = [],
|
|
108
135
|
columnHeader = [],
|
|
136
|
+
dropdownTheme = 'default',
|
|
137
|
+
dropdownThemeConfig,
|
|
138
|
+
searchOnButtonOnly = false,
|
|
109
139
|
}) => {
|
|
140
|
+
const splitDetailOptions = dropdownThemeConfig?.splitDetail;
|
|
141
|
+
const showSearchOnButtonChrome =
|
|
142
|
+
searchOnButtonOnly &&
|
|
143
|
+
(type === 'auto_complete' || type === 'custom_search_select') &&
|
|
144
|
+
!disabled &&
|
|
145
|
+
!readOnly;
|
|
110
146
|
const [inputValue, setInputValue] = useState<any>(value?.name ?? "");
|
|
111
147
|
const [isHovered, setIsHovered] = useState<boolean>(false);
|
|
112
148
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
@@ -199,13 +235,52 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
199
235
|
timerRef.current = 0;
|
|
200
236
|
|
|
201
237
|
setInputValue(value);
|
|
202
|
-
|
|
238
|
+
if (!searchOnButtonOnly) {
|
|
239
|
+
handleValChange(value);
|
|
240
|
+
}
|
|
203
241
|
if (!value) {
|
|
204
242
|
setInputValue('');
|
|
205
243
|
onChange({ id: undefined, name: '', from: 2 });
|
|
206
244
|
}
|
|
207
245
|
};
|
|
208
246
|
|
|
247
|
+
const runSearchFromInput = (value: string) => {
|
|
248
|
+
setDropOpen(true);
|
|
249
|
+
onChange({ id: undefined, name: '', from: 1 });
|
|
250
|
+
if (value.trim() === '' && type === 'auto_complete') {
|
|
251
|
+
setSuggestions([]);
|
|
252
|
+
if (autoFilter) {
|
|
253
|
+
handleDropData('*');
|
|
254
|
+
} else {
|
|
255
|
+
setDropOpen(false);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
handleDropData(value);
|
|
259
|
+
}
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
timerRef.current = 1;
|
|
262
|
+
}, 200);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const handleSearchButtonClick = (e: React.MouseEvent) => {
|
|
266
|
+
e.preventDefault();
|
|
267
|
+
e.stopPropagation();
|
|
268
|
+
if (disabled || readOnly) return;
|
|
269
|
+
timerRef.current = 0;
|
|
270
|
+
const q = inputRef.current?.value ?? inputValue ?? '';
|
|
271
|
+
runSearchFromInput(q);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const handleSearchInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
275
|
+
if (!searchOnButtonOnly || disabled || readOnly) return;
|
|
276
|
+
if (e.key === 'Enter') {
|
|
277
|
+
e.preventDefault();
|
|
278
|
+
timerRef.current = 0;
|
|
279
|
+
const q = inputRef.current?.value ?? inputValue ?? '';
|
|
280
|
+
runSearchFromInput(q);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
209
284
|
const handleValChange = useCallback(
|
|
210
285
|
debounce(
|
|
211
286
|
(value: string) => {
|
|
@@ -289,6 +364,9 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
289
364
|
const onLabelClick = () => {
|
|
290
365
|
if (!isDisabled) {
|
|
291
366
|
inputRef?.current?.focus();
|
|
367
|
+
if (searchOnButtonOnly) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
292
370
|
if (autoFilter && inputValue === '') {
|
|
293
371
|
handleValChange('*');
|
|
294
372
|
} else if (
|
|
@@ -350,6 +428,9 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
350
428
|
}, [autoFocus]);
|
|
351
429
|
const onInputFocus = () => {
|
|
352
430
|
if (!isDisabled) {
|
|
431
|
+
if (searchOnButtonOnly) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
353
434
|
if (autoFilter && inputValue === '') {
|
|
354
435
|
handleValChange('*');
|
|
355
436
|
} else if (
|
|
@@ -385,6 +466,12 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
385
466
|
};
|
|
386
467
|
|
|
387
468
|
const handleOpenDropdown = (e: any) => {
|
|
469
|
+
if (searchOnButtonOnly) {
|
|
470
|
+
if (suggestions && suggestions.length > 0 && !isLoading) {
|
|
471
|
+
setDropOpen((open) => !open);
|
|
472
|
+
}
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
388
475
|
if (!suggestions || suggestions?.length === 0 || refetchData) {
|
|
389
476
|
if (autoDropdown && (inputValue === '' || inputValue.trim() === '')) {
|
|
390
477
|
setSuggestions([]);
|
|
@@ -560,21 +647,50 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
560
647
|
// const getPosition = () => {
|
|
561
648
|
// return 'bottom'
|
|
562
649
|
// }
|
|
650
|
+
const itemMatchesLocalFilter = (item: any): boolean => {
|
|
651
|
+
const baseMatch = checkIncludes(
|
|
652
|
+
item.name,
|
|
653
|
+
inputValue,
|
|
654
|
+
item.param1 ?? '',
|
|
655
|
+
item.param2 ?? '',
|
|
656
|
+
item.param3 ?? '',
|
|
657
|
+
item.param4 ?? ''
|
|
658
|
+
);
|
|
659
|
+
if (
|
|
660
|
+
dropdownTheme !== 'splitDetail' ||
|
|
661
|
+
!splitDetailOptions ||
|
|
662
|
+
!inputValue
|
|
663
|
+
) {
|
|
664
|
+
return baseMatch;
|
|
665
|
+
}
|
|
666
|
+
const q = inputValue.trim().toLowerCase();
|
|
667
|
+
if (!q) return baseMatch;
|
|
668
|
+
|
|
669
|
+
const hay = (v: unknown) =>
|
|
670
|
+
v != null && String(v).toLowerCase().includes(q);
|
|
671
|
+
|
|
672
|
+
if (item.label != null && hay(item.label)) return true;
|
|
673
|
+
if (
|
|
674
|
+
splitDetailOptions.subtitleKey &&
|
|
675
|
+
hay(item[splitDetailOptions.subtitleKey])
|
|
676
|
+
) {
|
|
677
|
+
return true;
|
|
678
|
+
}
|
|
679
|
+
if (
|
|
680
|
+
splitDetailOptions.badgeKey &&
|
|
681
|
+
hay(item[splitDetailOptions.badgeKey])
|
|
682
|
+
) {
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
return baseMatch;
|
|
686
|
+
};
|
|
687
|
+
|
|
563
688
|
const filteredData =
|
|
564
689
|
inputValue !== '*' &&
|
|
565
690
|
inputValue !== '' &&
|
|
566
691
|
type !== 'custom_select' &&
|
|
567
692
|
!noLocalFilter
|
|
568
|
-
? suggestions?.filter((item: valueProps) =>
|
|
569
|
-
checkIncludes(
|
|
570
|
-
item.name,
|
|
571
|
-
inputValue,
|
|
572
|
-
item.param1 ?? '',
|
|
573
|
-
item.param2 ?? '',
|
|
574
|
-
item.param3 ?? '',
|
|
575
|
-
item.param4 ?? ''
|
|
576
|
-
)
|
|
577
|
-
)
|
|
693
|
+
? suggestions?.filter((item: valueProps) => itemMatchesLocalFilter(item))
|
|
578
694
|
: suggestions;
|
|
579
695
|
|
|
580
696
|
const handleError = (data: any) => {
|
|
@@ -770,7 +886,11 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
770
886
|
<div
|
|
771
887
|
ref={dropdownContentRef}
|
|
772
888
|
style={{ ...dropPosition, overflow: 'hidden' }}
|
|
773
|
-
className=
|
|
889
|
+
className={`autocomplete-suggections autocomplete-suggections-tableview absolute bg-white shadow-gray-300 shadow-md border border-grey-light z-50 mt-9${
|
|
890
|
+
dropdownTheme === 'splitDetail'
|
|
891
|
+
? ' autocomplete-suggections--split-detail'
|
|
892
|
+
: ''
|
|
893
|
+
}`}
|
|
774
894
|
>
|
|
775
895
|
<ul
|
|
776
896
|
className={`h-auto overflow-auto w-full ${tableView ? '' : 'py-1.5'}`}
|
|
@@ -779,7 +899,9 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
779
899
|
>
|
|
780
900
|
{filteredData?.length > 0 ? (
|
|
781
901
|
<>
|
|
782
|
-
{
|
|
902
|
+
{dropdownTheme === 'default' &&
|
|
903
|
+
columnHeader &&
|
|
904
|
+
columnHeader.length > 0 && (
|
|
783
905
|
<li className="sticky top-0 auto-suggections-tableview-header z-10 bg-gray-100 border-b border-grey-light">
|
|
784
906
|
<ul className="flex items-stretch w-full list-none p-0 m-0">
|
|
785
907
|
{(() => {
|
|
@@ -861,9 +983,9 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
861
983
|
index === selectedIndex ? 'is-selected' : ''
|
|
862
984
|
} hover:bg-table-hover`
|
|
863
985
|
} cursor-pointer text-xxs qbs-autocomplete-suggections-items ${
|
|
864
|
-
tableView
|
|
865
|
-
?
|
|
866
|
-
:
|
|
986
|
+
dropdownTheme === 'splitDetail' || tableView
|
|
987
|
+
? 'border-b border-grey-light last:border-b-0'
|
|
988
|
+
: 'p-1 ps-3.5 pl-[10px]'
|
|
867
989
|
}`}
|
|
868
990
|
key={suggestion?.id}
|
|
869
991
|
data-testid={suggestion.name}
|
|
@@ -871,70 +993,144 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
871
993
|
tabIndex={index}
|
|
872
994
|
ref={(el) => (itemRefs.current[index] = el)}
|
|
873
995
|
>
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
key={column.key}
|
|
901
|
-
className={`${column.width ? 'flex-shrink-0' : 'flex-1'} min-w-0 px-3 ${tableView ? 'py-2' : ''} ${!isLastBefore ? 'border-r border-grey-light' : ''} break-words flex flex-col`}
|
|
902
|
-
style={column.width ? { width: `${column.width}px` } : undefined}
|
|
903
|
-
>
|
|
904
|
-
<span className="block whitespace-normal">
|
|
905
|
-
{suggestion?.[column.key]}
|
|
906
|
-
</span>
|
|
907
|
-
</li>
|
|
908
|
-
) : null;
|
|
909
|
-
})}
|
|
910
|
-
|
|
911
|
-
{/* First column (label/name) */}
|
|
912
|
-
<li className={`flex-1 min-w-0 px-3 ${tableView ? 'py-2' : ''} ${hasColumnsAfter ? 'border-r border-grey-light' : ''} break-words flex flex-col`}>
|
|
913
|
-
<span className="block whitespace-normal">
|
|
914
|
-
{suggestion?.label ? suggestion?.label : suggestion.name}
|
|
996
|
+
{dropdownTheme === 'splitDetail' ? (
|
|
997
|
+
<div className="qbs-split-detail-row">
|
|
998
|
+
<div className="qbs-split-detail-main">
|
|
999
|
+
<div className="qbs-split-detail-title">
|
|
1000
|
+
{suggestion?.label ? suggestion?.label : suggestion.name}
|
|
1001
|
+
</div>
|
|
1002
|
+
{splitDetailOptions?.subtitleKey &&
|
|
1003
|
+
suggestion?.[splitDetailOptions.subtitleKey] != null &&
|
|
1004
|
+
String(
|
|
1005
|
+
suggestion[splitDetailOptions.subtitleKey]
|
|
1006
|
+
).trim() !== '' && (
|
|
1007
|
+
<div className="qbs-split-detail-subtitle">
|
|
1008
|
+
{String(
|
|
1009
|
+
suggestion[splitDetailOptions.subtitleKey]
|
|
1010
|
+
)}
|
|
1011
|
+
</div>
|
|
1012
|
+
)}
|
|
1013
|
+
</div>
|
|
1014
|
+
{splitDetailOptions?.badgeKey &&
|
|
1015
|
+
suggestion?.[splitDetailOptions.badgeKey] != null &&
|
|
1016
|
+
String(suggestion[splitDetailOptions.badgeKey]).trim() !==
|
|
1017
|
+
'' && (
|
|
1018
|
+
<div className="qbs-split-detail-badge-wrap">
|
|
1019
|
+
<span className="qbs-split-detail-badge">
|
|
1020
|
+
{splitDetailOptions.badgePrefix ?? ''}
|
|
1021
|
+
{String(suggestion[splitDetailOptions.badgeKey])}
|
|
915
1022
|
</span>
|
|
916
|
-
</
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1023
|
+
</div>
|
|
1024
|
+
)}
|
|
1025
|
+
</div>
|
|
1026
|
+
) : (
|
|
1027
|
+
<ul className="flex items-stretch w-full list-none p-0 m-0">
|
|
1028
|
+
{(() => {
|
|
1029
|
+
// Sort columns by order if specified, otherwise maintain array order
|
|
1030
|
+
const sortedColumns = additionalColumns
|
|
1031
|
+
? [...additionalColumns].sort((a, b) => {
|
|
1032
|
+
const orderA =
|
|
1033
|
+
a.order !== undefined ? a.order : Infinity;
|
|
1034
|
+
const orderB =
|
|
1035
|
+
b.order !== undefined ? b.order : Infinity;
|
|
1036
|
+
return orderA - orderB;
|
|
1037
|
+
})
|
|
1038
|
+
: [];
|
|
1039
|
+
|
|
1040
|
+
// Separate columns before first column (order < 0) and after (order >= 0 or undefined)
|
|
1041
|
+
const columnsBefore = sortedColumns.filter(
|
|
1042
|
+
(col) => col.order !== undefined && col.order < 0
|
|
1043
|
+
);
|
|
1044
|
+
const columnsAfter = sortedColumns.filter(
|
|
1045
|
+
(col) =>
|
|
1046
|
+
col.order === undefined || col.order >= 0
|
|
1047
|
+
);
|
|
1048
|
+
|
|
1049
|
+
// Determine if first column needs a separator
|
|
1050
|
+
const hasColumnsAfter = columnsAfter.length > 0;
|
|
1051
|
+
|
|
1052
|
+
return (
|
|
1053
|
+
<>
|
|
1054
|
+
{/* Columns before first column */}
|
|
1055
|
+
{columnsBefore.map((column, colIndex) => {
|
|
1056
|
+
const hasValue = suggestion?.[column.key];
|
|
1057
|
+
const isLastBefore = false;
|
|
1058
|
+
return hasValue ? (
|
|
1059
|
+
<li
|
|
1060
|
+
key={column.key}
|
|
1061
|
+
className={`${
|
|
1062
|
+
column.width ? 'flex-shrink-0' : 'flex-1'
|
|
1063
|
+
} min-w-0 px-3 ${
|
|
1064
|
+
tableView ? 'py-2' : ''
|
|
1065
|
+
} ${
|
|
1066
|
+
!isLastBefore
|
|
1067
|
+
? 'border-r border-grey-light'
|
|
1068
|
+
: ''
|
|
1069
|
+
} break-words flex flex-col`}
|
|
1070
|
+
style={
|
|
1071
|
+
column.width
|
|
1072
|
+
? { width: `${column.width}px` }
|
|
1073
|
+
: undefined
|
|
1074
|
+
}
|
|
1075
|
+
>
|
|
1076
|
+
<span className="block whitespace-normal">
|
|
1077
|
+
{suggestion?.[column.key]}
|
|
1078
|
+
</span>
|
|
1079
|
+
</li>
|
|
1080
|
+
) : null;
|
|
1081
|
+
})}
|
|
1082
|
+
|
|
1083
|
+
{/* First column (label/name) */}
|
|
1084
|
+
<li
|
|
1085
|
+
className={`flex-1 min-w-0 px-3 ${
|
|
1086
|
+
tableView ? 'py-2' : ''
|
|
1087
|
+
} ${
|
|
1088
|
+
hasColumnsAfter
|
|
1089
|
+
? 'border-r border-grey-light'
|
|
1090
|
+
: ''
|
|
1091
|
+
} break-words flex flex-col`}
|
|
1092
|
+
>
|
|
1093
|
+
<span className="block whitespace-normal">
|
|
1094
|
+
{suggestion?.label
|
|
1095
|
+
? suggestion?.label
|
|
1096
|
+
: suggestion.name}
|
|
1097
|
+
</span>
|
|
1098
|
+
</li>
|
|
1099
|
+
|
|
1100
|
+
{/* Columns after first column */}
|
|
1101
|
+
{columnsAfter.map((column, colIndex) => {
|
|
1102
|
+
const hasValue = suggestion?.[column.key];
|
|
1103
|
+
const isLastColumn =
|
|
1104
|
+
colIndex === columnsAfter.length - 1;
|
|
1105
|
+
return hasValue ? (
|
|
1106
|
+
<li
|
|
1107
|
+
key={column.key}
|
|
1108
|
+
className={`${
|
|
1109
|
+
column.width ? 'flex-shrink-0' : 'flex-1'
|
|
1110
|
+
} min-w-0 px-3 ${
|
|
1111
|
+
tableView ? 'py-2' : ''
|
|
1112
|
+
} ${
|
|
1113
|
+
!isLastColumn
|
|
1114
|
+
? 'border-r border-grey-light'
|
|
1115
|
+
: ''
|
|
1116
|
+
} break-words flex flex-col`}
|
|
1117
|
+
style={
|
|
1118
|
+
column.width
|
|
1119
|
+
? { width: `${column.width}px` }
|
|
1120
|
+
: undefined
|
|
1121
|
+
}
|
|
1122
|
+
>
|
|
1123
|
+
<span className="block whitespace-normal">
|
|
1124
|
+
{suggestion?.[column.key]}
|
|
1125
|
+
</span>
|
|
1126
|
+
</li>
|
|
1127
|
+
) : null;
|
|
1128
|
+
})}
|
|
1129
|
+
</>
|
|
1130
|
+
);
|
|
1131
|
+
})()}
|
|
1132
|
+
</ul>
|
|
1133
|
+
)}
|
|
938
1134
|
</li>
|
|
939
1135
|
))}
|
|
940
1136
|
</>
|
|
@@ -1185,10 +1381,13 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
1185
1381
|
: placeholder ?? '--Select--'
|
|
1186
1382
|
}
|
|
1187
1383
|
onFocus={onInputFocus}
|
|
1384
|
+
onKeyDown={handleSearchInputKeyDown}
|
|
1188
1385
|
onClick={(e) => {
|
|
1189
1386
|
if (type === 'custom_select') {
|
|
1190
1387
|
setDropOpen(!dropOpen);
|
|
1191
1388
|
handleOpen(e);
|
|
1389
|
+
} else if (searchOnButtonOnly) {
|
|
1390
|
+
return;
|
|
1192
1391
|
} else {
|
|
1193
1392
|
if (dropOpen || filteredData?.length > 0)
|
|
1194
1393
|
setDropOpen(!dropOpen);
|
|
@@ -1226,7 +1425,26 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
|
|
|
1226
1425
|
<CustomIcons name="close" type="large-m" />
|
|
1227
1426
|
</button>
|
|
1228
1427
|
)}
|
|
1229
|
-
{
|
|
1428
|
+
{showSearchOnButtonChrome && (
|
|
1429
|
+
<button
|
|
1430
|
+
type="button"
|
|
1431
|
+
aria-label={isLoading ? 'Loading' : 'Search'}
|
|
1432
|
+
aria-busy={isLoading}
|
|
1433
|
+
data-testid="autocomplete-search-button"
|
|
1434
|
+
onClick={handleSearchButtonClick}
|
|
1435
|
+
disabled={isLoading}
|
|
1436
|
+
className="text-table-bodyColor text-[#667085] focus-visible:outline-slate-100 p-0.5 inline-flex items-center justify-center min-w-[28px] min-h-[28px] disabled:opacity-70"
|
|
1437
|
+
>
|
|
1438
|
+
{isLoading ? (
|
|
1439
|
+
<span className="inline-flex items-center justify-center [&_svg]:mr-0 [&_svg]:h-5 [&_svg]:w-5">
|
|
1440
|
+
<Spinner />
|
|
1441
|
+
</span>
|
|
1442
|
+
) : (
|
|
1443
|
+
<CustomIcons name="search" type="medium" />
|
|
1444
|
+
)}
|
|
1445
|
+
</button>
|
|
1446
|
+
)}
|
|
1447
|
+
{isLoading && !showSearchOnButtonChrome && <Spinner />}
|
|
1230
1448
|
{(type !== 'auto_complete' || autoDropdown) &&
|
|
1231
1449
|
!disabled &&
|
|
1232
1450
|
!readOnly && (
|
package/src/index.tsx
CHANGED
|
@@ -21,3 +21,8 @@ export { default as ExpandableToolTip } from './utilities/expandableTootltip';
|
|
|
21
21
|
export { default as ToolTip } from './utilities/tooltip';
|
|
22
22
|
export { default as ModernAutoCompleteDropdown } from './ReactAutoCompleteDropdown';
|
|
23
23
|
export { default as ModernAutoCompleteTableView } from './ReactAutoCompleteTableView';
|
|
24
|
+
export type {
|
|
25
|
+
DropdownThemeConfig,
|
|
26
|
+
DropdownThemeId,
|
|
27
|
+
SplitDetailThemeConfig,
|
|
28
|
+
} from './ReactAutoCompleteTableView';
|
|
@@ -748,6 +748,75 @@ span.dropdown-search-icon {
|
|
|
748
748
|
flex: 0 1 auto;
|
|
749
749
|
}
|
|
750
750
|
|
|
751
|
+
/* Split-detail dropdown theme (bank-style row: title + subtitle | badge) */
|
|
752
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-row {
|
|
753
|
+
display: flex;
|
|
754
|
+
align-items: center;
|
|
755
|
+
gap: 12px;
|
|
756
|
+
width: 100%;
|
|
757
|
+
padding: 10px 12px;
|
|
758
|
+
box-sizing: border-box;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-main {
|
|
762
|
+
flex: 1;
|
|
763
|
+
min-width: 0;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-title {
|
|
767
|
+
font-size: 14px;
|
|
768
|
+
font-weight: 600;
|
|
769
|
+
color: #101828;
|
|
770
|
+
line-height: 1.35;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-subtitle {
|
|
774
|
+
margin-top: 4px;
|
|
775
|
+
font-size: 12px;
|
|
776
|
+
font-weight: 400;
|
|
777
|
+
color: #667085;
|
|
778
|
+
line-height: 1.45;
|
|
779
|
+
white-space: normal;
|
|
780
|
+
word-break: break-word;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-badge-wrap {
|
|
784
|
+
flex-shrink: 0;
|
|
785
|
+
align-self: center;
|
|
786
|
+
max-width: 45%;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.autocomplete-suggections--split-detail .qbs-split-detail-badge {
|
|
790
|
+
display: inline-block;
|
|
791
|
+
padding: 6px 10px;
|
|
792
|
+
font-size: 12px;
|
|
793
|
+
font-weight: 600;
|
|
794
|
+
line-height: 1.3;
|
|
795
|
+
color: #194185;
|
|
796
|
+
background: #d1e9ff;
|
|
797
|
+
border: 1px solid #b2ddff;
|
|
798
|
+
border-radius: 6px;
|
|
799
|
+
white-space: normal;
|
|
800
|
+
word-break: break-word;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.autocomplete-suggections--split-detail
|
|
804
|
+
.qbs-autocomplete-suggections-items.bg-blue-navy
|
|
805
|
+
.qbs-split-detail-title,
|
|
806
|
+
.autocomplete-suggections--split-detail
|
|
807
|
+
.qbs-autocomplete-suggections-items.bg-blue-navy
|
|
808
|
+
.qbs-split-detail-subtitle {
|
|
809
|
+
color: #fff;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
.autocomplete-suggections--split-detail
|
|
813
|
+
.qbs-autocomplete-suggections-items.bg-blue-navy
|
|
814
|
+
.qbs-split-detail-badge {
|
|
815
|
+
color: #194185;
|
|
816
|
+
background: #eff8ff;
|
|
817
|
+
border-color: #b2ddff;
|
|
818
|
+
}
|
|
819
|
+
|
|
751
820
|
/* TextField Inner Search Button */
|
|
752
821
|
.inner-search-button {
|
|
753
822
|
background: #f8f8f8;
|