react-core-ts 2.0.4 → 2.0.6
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/ReactAutoComplete.d.ts +4 -4
- package/dist/ReactAutoComplete.js +122 -102
- package/dist/ReactAutoComplete.js.map +1 -1
- package/package.json +1 -1
- package/src/ReactAutoComplete.tsx +149 -129
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useRef, useState } from
|
|
2
|
-
import { FieldErrors } from
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { FieldErrors } from 'react-hook-form';
|
|
3
3
|
|
|
4
|
-
import CustomIcons from
|
|
5
|
-
import Spinner from
|
|
6
|
-
import Portal from
|
|
7
|
-
import { debounce } from
|
|
8
|
-
import { applyPositionClass } from
|
|
9
|
-
import { DropArrow } from
|
|
4
|
+
import CustomIcons from './components/customIcons';
|
|
5
|
+
import Spinner from './components/loader/Spinner';
|
|
6
|
+
import Portal from './components/portal';
|
|
7
|
+
import { debounce } from './utilities/debounce';
|
|
8
|
+
import { applyPositionClass } from './utilities/getPosition';
|
|
9
|
+
import { DropArrow } from './utilities/icons';
|
|
10
10
|
|
|
11
11
|
type valueProps = {
|
|
12
12
|
id?: string | number;
|
|
@@ -31,7 +31,7 @@ interface AutoSuggestionInputProps {
|
|
|
31
31
|
value?: valueProps;
|
|
32
32
|
onChange: (value?: valueProps) => void;
|
|
33
33
|
data?: any[];
|
|
34
|
-
type?:
|
|
34
|
+
type?: 'custom_select' | 'auto_complete' | 'custom_search_select';
|
|
35
35
|
placeholder?: string;
|
|
36
36
|
getData?: ((key?: string) => Promise<any>) | ((key?: string) => any);
|
|
37
37
|
errors?: FieldErrors;
|
|
@@ -51,7 +51,7 @@ interface AutoSuggestionInputProps {
|
|
|
51
51
|
width?: number;
|
|
52
52
|
labelTitle?: string;
|
|
53
53
|
isModern?: boolean;
|
|
54
|
-
size?:
|
|
54
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xxs';
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
@@ -64,13 +64,13 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
64
64
|
required = false,
|
|
65
65
|
autoFocus,
|
|
66
66
|
name,
|
|
67
|
-
shortCode =
|
|
68
|
-
labelCode =
|
|
67
|
+
shortCode = '',
|
|
68
|
+
labelCode = '',
|
|
69
69
|
fullWidth,
|
|
70
70
|
placeholder,
|
|
71
71
|
id,
|
|
72
72
|
className: propsClassName,
|
|
73
|
-
type =
|
|
73
|
+
type = 'custom_select',
|
|
74
74
|
readOnly,
|
|
75
75
|
disabled = false,
|
|
76
76
|
value,
|
|
@@ -86,9 +86,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
86
86
|
fromPrefix,
|
|
87
87
|
labelTitle,
|
|
88
88
|
isModern = true,
|
|
89
|
-
size =
|
|
89
|
+
size = 'md',
|
|
90
90
|
}) => {
|
|
91
|
-
const [inputValue, setInputValue] = useState<any>(value?.name ??
|
|
91
|
+
const [inputValue, setInputValue] = useState<any>(value?.name ?? '');
|
|
92
92
|
const [isHovered, setIsHovered] = useState<boolean>(false);
|
|
93
93
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
94
94
|
const [dropOpen, setDropOpen] = useState<boolean>(false);
|
|
@@ -126,8 +126,8 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
126
126
|
) => {
|
|
127
127
|
return substring &&
|
|
128
128
|
mainString &&
|
|
129
|
-
typeof mainString ===
|
|
130
|
-
typeof subString ===
|
|
129
|
+
typeof mainString === 'string' &&
|
|
130
|
+
typeof subString === 'string'
|
|
131
131
|
? mainString
|
|
132
132
|
.toString()
|
|
133
133
|
.toLowerCase()
|
|
@@ -142,23 +142,23 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
142
142
|
return (
|
|
143
143
|
checkIncludesIfExists(mainString, subString) ||
|
|
144
144
|
(!!checkParams &&
|
|
145
|
-
((checkArrayContains(checkParams,
|
|
145
|
+
((checkArrayContains(checkParams, 'param1') &&
|
|
146
146
|
checkIncludesIfExists(param1, subString)) ||
|
|
147
|
-
(checkArrayContains(checkParams,
|
|
147
|
+
(checkArrayContains(checkParams, 'param2') &&
|
|
148
148
|
checkIncludesIfExists(param2, subString)) ||
|
|
149
|
-
(checkArrayContains(checkParams,
|
|
149
|
+
(checkArrayContains(checkParams, 'param3') &&
|
|
150
150
|
checkIncludesIfExists(param3, subString)) ||
|
|
151
|
-
(checkArrayContains(checkParams,
|
|
151
|
+
(checkArrayContains(checkParams, 'param4') &&
|
|
152
152
|
checkIncludesIfExists(param4, subString))))
|
|
153
153
|
);
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
const getHeight = () => {
|
|
157
157
|
switch (size) {
|
|
158
|
-
case
|
|
159
|
-
return
|
|
158
|
+
case 'sm':
|
|
159
|
+
return ' h-[34px] ';
|
|
160
160
|
default:
|
|
161
|
-
return
|
|
161
|
+
return ' ';
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
164
|
|
|
@@ -169,8 +169,8 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
169
169
|
setInputValue(value);
|
|
170
170
|
handleValChange(value);
|
|
171
171
|
if (!value) {
|
|
172
|
-
setInputValue(
|
|
173
|
-
onChange({ id: undefined, name:
|
|
172
|
+
setInputValue('');
|
|
173
|
+
onChange({ id: undefined, name: '', from: 2 });
|
|
174
174
|
}
|
|
175
175
|
};
|
|
176
176
|
|
|
@@ -178,11 +178,11 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
178
178
|
debounce(
|
|
179
179
|
(value: string) => {
|
|
180
180
|
setDropOpen(true);
|
|
181
|
-
onChange({ id: undefined, name:
|
|
182
|
-
if (value.trim() ===
|
|
181
|
+
onChange({ id: undefined, name: '', from: 1 });
|
|
182
|
+
if (value.trim() === '' && type === 'auto_complete') {
|
|
183
183
|
setSuggestions([]);
|
|
184
184
|
if (autoFilter) {
|
|
185
|
-
handleDropData(
|
|
185
|
+
handleDropData('*');
|
|
186
186
|
} else {
|
|
187
187
|
setDropOpen(false);
|
|
188
188
|
}
|
|
@@ -198,11 +198,11 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
198
198
|
[]
|
|
199
199
|
);
|
|
200
200
|
const handleDropData = (value?: string) => {
|
|
201
|
-
if (type ===
|
|
201
|
+
if (type === 'auto_complete') {
|
|
202
202
|
if (isStaticList) {
|
|
203
203
|
loadStaticData();
|
|
204
204
|
const filteredData =
|
|
205
|
-
value && value !==
|
|
205
|
+
value && value !== '*'
|
|
206
206
|
? data?.filter((item) =>
|
|
207
207
|
checkIncludes(
|
|
208
208
|
item.name,
|
|
@@ -216,13 +216,13 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
216
216
|
setSuggestions(filteredData);
|
|
217
217
|
} else handlePickSuggestions(value);
|
|
218
218
|
} else if (
|
|
219
|
-
(type ===
|
|
219
|
+
(type === 'custom_select' || type === 'custom_search_select') &&
|
|
220
220
|
(!data || data?.length === 0)
|
|
221
221
|
) {
|
|
222
222
|
handlePickSuggestions();
|
|
223
|
-
} else if (type ===
|
|
223
|
+
} else if (type === 'custom_search_select' && data && data?.length > 0) {
|
|
224
224
|
const filteredData =
|
|
225
|
-
value && value !==
|
|
225
|
+
value && value !== '*'
|
|
226
226
|
? data.filter((item) =>
|
|
227
227
|
checkIncludes(
|
|
228
228
|
item.name,
|
|
@@ -252,10 +252,10 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
252
252
|
const onLabelClick = () => {
|
|
253
253
|
if (!isDisabled) {
|
|
254
254
|
inputRef?.current?.focus();
|
|
255
|
-
if (autoFilter && inputValue ===
|
|
256
|
-
handleValChange(
|
|
255
|
+
if (autoFilter && inputValue === '') {
|
|
256
|
+
handleValChange('*');
|
|
257
257
|
} else if (
|
|
258
|
-
(type ===
|
|
258
|
+
(type === 'custom_select' || type === 'custom_search_select') &&
|
|
259
259
|
data &&
|
|
260
260
|
data?.length > 0
|
|
261
261
|
) {
|
|
@@ -265,9 +265,17 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
265
265
|
}
|
|
266
266
|
};
|
|
267
267
|
const handleClickOutside = (event: MouseEvent) => {
|
|
268
|
+
const target = event.target as Node;
|
|
269
|
+
const dropButton = document.getElementById('autocomplete-drop-icon');
|
|
270
|
+
const closeButton = document.getElementById('autocomplete-close-icon');
|
|
271
|
+
|
|
268
272
|
if (
|
|
269
273
|
dropdownref.current &&
|
|
270
|
-
!dropdownref.current.contains(
|
|
274
|
+
!dropdownref.current.contains(target) &&
|
|
275
|
+
target !== dropButton &&
|
|
276
|
+
!dropButton?.contains(target) &&
|
|
277
|
+
target !== closeButton &&
|
|
278
|
+
!closeButton?.contains(target)
|
|
271
279
|
) {
|
|
272
280
|
setDropOpen(false);
|
|
273
281
|
}
|
|
@@ -282,8 +290,8 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
282
290
|
if (getData) {
|
|
283
291
|
try {
|
|
284
292
|
setIsLoading(true);
|
|
285
|
-
handlePickSuggestions(
|
|
286
|
-
const fetchedSuggestions = await getData?.(
|
|
293
|
+
handlePickSuggestions('*');
|
|
294
|
+
const fetchedSuggestions = await getData?.('*');
|
|
287
295
|
fetchedSuggestions?.forEach((element: any) => {
|
|
288
296
|
data?.push(element);
|
|
289
297
|
});
|
|
@@ -295,9 +303,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
295
303
|
}
|
|
296
304
|
};
|
|
297
305
|
useEffect(() => {
|
|
298
|
-
document.addEventListener(
|
|
306
|
+
document.addEventListener('click', handleClickOutside);
|
|
299
307
|
return () => {
|
|
300
|
-
document.removeEventListener(
|
|
308
|
+
document.removeEventListener('click', handleClickOutside);
|
|
301
309
|
};
|
|
302
310
|
}, []);
|
|
303
311
|
|
|
@@ -308,10 +316,10 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
308
316
|
}, [autoFocus]);
|
|
309
317
|
const onInputFocus = () => {
|
|
310
318
|
if (!isDisabled) {
|
|
311
|
-
if (autoFilter && inputValue ===
|
|
312
|
-
handleValChange(
|
|
319
|
+
if (autoFilter && inputValue === '') {
|
|
320
|
+
handleValChange('*');
|
|
313
321
|
} else if (
|
|
314
|
-
(type ===
|
|
322
|
+
(type === 'custom_select' || type === 'custom_search_select') &&
|
|
315
323
|
data &&
|
|
316
324
|
data?.length > 0
|
|
317
325
|
) {
|
|
@@ -330,15 +338,22 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
330
338
|
name: suggestion.name,
|
|
331
339
|
...(suggestion?.label ? { label: suggestion?.label } : {}),
|
|
332
340
|
});
|
|
333
|
-
if (type !==
|
|
341
|
+
if (type !== 'custom_select') setInputValue(suggestion.name);
|
|
334
342
|
setDropOpen(false);
|
|
335
343
|
setSelectedIndex(index);
|
|
336
344
|
};
|
|
337
345
|
const handleOpen = (e: any) => {
|
|
338
|
-
if (
|
|
339
|
-
|
|
346
|
+
if (e) {
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
e.stopPropagation();
|
|
349
|
+
}
|
|
350
|
+
if (!suggestions || suggestions?.length === 0) {
|
|
351
|
+
handleDropData();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (!isLoading) {
|
|
340
355
|
setDropOpen(!dropOpen);
|
|
341
|
-
setInputValue(
|
|
356
|
+
if (type !== 'custom_select') setInputValue('');
|
|
342
357
|
}
|
|
343
358
|
};
|
|
344
359
|
|
|
@@ -349,28 +364,28 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
349
364
|
useEffect(() => {
|
|
350
365
|
if (!insideOpen) {
|
|
351
366
|
setSelectedIndex(0);
|
|
352
|
-
window.addEventListener(
|
|
367
|
+
window.addEventListener('scroll', handleScroll);
|
|
353
368
|
|
|
354
|
-
const mainElement = document.querySelector(
|
|
355
|
-
mainElement?.addEventListener(
|
|
369
|
+
const mainElement = document.querySelector('main');
|
|
370
|
+
mainElement?.addEventListener('scroll', handleScroll);
|
|
356
371
|
|
|
357
372
|
const gridElements = document.querySelectorAll(
|
|
358
|
-
|
|
373
|
+
'.k-grid-content, .overflow-auto, .overflow-y-auto, .overflow-x-auto'
|
|
359
374
|
);
|
|
360
375
|
gridElements.forEach((gridElement: any) => {
|
|
361
|
-
gridElement.addEventListener(
|
|
376
|
+
gridElement.addEventListener('scroll', handleScroll);
|
|
362
377
|
});
|
|
363
378
|
|
|
364
|
-
window.addEventListener(
|
|
379
|
+
window.addEventListener('resize', getDropPosition);
|
|
365
380
|
getDropPosition();
|
|
366
381
|
return () => {
|
|
367
|
-
window.removeEventListener(
|
|
368
|
-
const mainElement = document.querySelector(
|
|
369
|
-
mainElement?.removeEventListener(
|
|
370
|
-
window.addEventListener(
|
|
371
|
-
const gridElements = document.querySelectorAll(
|
|
382
|
+
window.removeEventListener('scroll', handleScroll);
|
|
383
|
+
const mainElement = document.querySelector('main');
|
|
384
|
+
mainElement?.removeEventListener('scroll', handleScroll);
|
|
385
|
+
window.addEventListener('resize', getDropPosition);
|
|
386
|
+
const gridElements = document.querySelectorAll('.k-grid-content');
|
|
372
387
|
gridElements.forEach((gridElement: any) => {
|
|
373
|
-
gridElement.removeEventListener(
|
|
388
|
+
gridElement.removeEventListener('scroll', handleScroll);
|
|
374
389
|
});
|
|
375
390
|
};
|
|
376
391
|
}
|
|
@@ -378,13 +393,13 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
378
393
|
|
|
379
394
|
const handleClear = () => {
|
|
380
395
|
setDropOpen(false);
|
|
381
|
-
setInputValue(
|
|
382
|
-
onChange({ id: undefined, name:
|
|
396
|
+
setInputValue('');
|
|
397
|
+
onChange({ id: undefined, name: '', from: 3 });
|
|
383
398
|
onLabelClick();
|
|
384
399
|
};
|
|
385
400
|
|
|
386
401
|
useEffect(() => {
|
|
387
|
-
setInputValue(value?.name ??
|
|
402
|
+
setInputValue(value?.name ?? '');
|
|
388
403
|
}, [value?.name]);
|
|
389
404
|
|
|
390
405
|
useEffect(() => {
|
|
@@ -392,7 +407,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
392
407
|
}, [data]);
|
|
393
408
|
|
|
394
409
|
const getErrors = (err: any) => {
|
|
395
|
-
let errMsg =
|
|
410
|
+
let errMsg = '';
|
|
396
411
|
if (err.message) {
|
|
397
412
|
errMsg = err?.message;
|
|
398
413
|
} else if (err?.id?.message) {
|
|
@@ -403,61 +418,61 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
403
418
|
return errMsg;
|
|
404
419
|
};
|
|
405
420
|
const generateClassName = (
|
|
406
|
-
type:
|
|
421
|
+
type: 'input' | 'label' | 'message' | 'adorement'
|
|
407
422
|
): string => {
|
|
408
423
|
let className = propsClassName;
|
|
409
424
|
switch (type) {
|
|
410
|
-
case
|
|
425
|
+
case 'input':
|
|
411
426
|
className += ` block text-common text-input-text font-normal px-3.5 w-full text-sm text-gray-900 bg-transparent border appearance-none peer h-10 rounded-[4px] disabled:text-input-disabled bg-white disabled:bg-disabled ${
|
|
412
427
|
label && isModern
|
|
413
|
-
?
|
|
414
|
-
:
|
|
428
|
+
? 'placeholder-transparent'
|
|
429
|
+
: 'focus:placeholder-grey-secondary placeholder-input-label'
|
|
415
430
|
} focus:placeholder-grey-secondary`;
|
|
416
431
|
|
|
417
432
|
if (errors && errors[name]) {
|
|
418
433
|
className +=
|
|
419
|
-
|
|
434
|
+
' border-[#FDA29B] focus:border-error-[#FDA29B] focus:ring-[#FDA29B] focus:ring-3 focus:outline-[#FDA29B] input-outline';
|
|
420
435
|
} else {
|
|
421
436
|
className +=
|
|
422
|
-
|
|
437
|
+
' text-grey-dark border-input-light focus:border-blue-navy focus:outline-none focus:ring-0';
|
|
423
438
|
}
|
|
424
439
|
|
|
425
440
|
className += getHeight();
|
|
426
441
|
|
|
427
442
|
break;
|
|
428
|
-
case
|
|
443
|
+
case 'label':
|
|
429
444
|
className += ` flex modern-input-label-truncate peer-focus:modern-input-peer-focus-label-size
|
|
430
445
|
${
|
|
431
446
|
isDisabled
|
|
432
|
-
?
|
|
433
|
-
:
|
|
447
|
+
? 'cursor-pointer'
|
|
448
|
+
: 'cursor-text peer-focus:cursor-pointer'
|
|
434
449
|
} ${
|
|
435
450
|
isDisabled && !checkIsEmptyField()
|
|
436
|
-
?
|
|
451
|
+
? 'disabled-input-label-bg'
|
|
437
452
|
: !isDisabled || !checkIsEmptyField()
|
|
438
|
-
?
|
|
439
|
-
:
|
|
453
|
+
? 'active-input-label-bg'
|
|
454
|
+
: ''
|
|
440
455
|
} absolute duration-300 transform -translate-y-4 top-2 z-1 origin-[0] px-0 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:top-1/2 peer-focus:top-2 peer-focus:-translate-y-4 start-[14px] rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto ${
|
|
441
456
|
isDisabled
|
|
442
|
-
?
|
|
443
|
-
:
|
|
457
|
+
? 'cursor-pointer'
|
|
458
|
+
: 'cursor-text peer-focus:cursor-pointer'
|
|
444
459
|
}
|
|
445
460
|
${
|
|
446
461
|
checkIsEmptyField()
|
|
447
|
-
?
|
|
448
|
-
:
|
|
462
|
+
? 'modern-input-label-size'
|
|
463
|
+
: 'modern-input-peer-focus-label-size'
|
|
449
464
|
}`;
|
|
450
465
|
if (errors && errors[name]) {
|
|
451
|
-
className +=
|
|
466
|
+
className += ' text-error-light ';
|
|
452
467
|
} else {
|
|
453
|
-
className +=
|
|
468
|
+
className += ' text-grey-dark peer-focus:text-blue-navy';
|
|
454
469
|
}
|
|
455
470
|
break;
|
|
456
|
-
case
|
|
457
|
-
className =
|
|
471
|
+
case 'message':
|
|
472
|
+
className = ' text-error-icon ';
|
|
458
473
|
break;
|
|
459
|
-
case
|
|
460
|
-
className +=
|
|
474
|
+
case 'adorement':
|
|
475
|
+
className += ' absolute right-0 adorement gap-1 flex items-center ';
|
|
461
476
|
break;
|
|
462
477
|
default:
|
|
463
478
|
break;
|
|
@@ -482,30 +497,30 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
482
497
|
// return 'bottom'
|
|
483
498
|
// }
|
|
484
499
|
const filteredData =
|
|
485
|
-
inputValue !==
|
|
486
|
-
inputValue !==
|
|
487
|
-
type !==
|
|
500
|
+
inputValue !== '*' &&
|
|
501
|
+
inputValue !== '' &&
|
|
502
|
+
type !== 'custom_select' &&
|
|
488
503
|
!noLocalFilter
|
|
489
504
|
? suggestions?.filter((item: valueProps) =>
|
|
490
505
|
checkIncludes(
|
|
491
506
|
item.name,
|
|
492
507
|
inputValue,
|
|
493
|
-
item.param1 ??
|
|
494
|
-
item.param2 ??
|
|
495
|
-
item.param3 ??
|
|
496
|
-
item.param4 ??
|
|
508
|
+
item.param1 ?? '',
|
|
509
|
+
item.param2 ?? '',
|
|
510
|
+
item.param3 ?? '',
|
|
511
|
+
item.param4 ?? ''
|
|
497
512
|
)
|
|
498
513
|
)
|
|
499
514
|
: suggestions;
|
|
500
515
|
|
|
501
516
|
const handleError = (data: any) => {
|
|
502
517
|
if (
|
|
503
|
-
getErrors(data[name]) ===
|
|
504
|
-
getErrors(data[name]) ===
|
|
518
|
+
getErrors(data[name]) === 'required' ||
|
|
519
|
+
getErrors(data[name]) === 'Required'
|
|
505
520
|
) {
|
|
506
521
|
return `${label ?? labelTitle} is ${getErrors(data[name])}`;
|
|
507
522
|
} else {
|
|
508
|
-
return getErrors(data[name]) ??
|
|
523
|
+
return getErrors(data[name]) ?? '';
|
|
509
524
|
}
|
|
510
525
|
};
|
|
511
526
|
|
|
@@ -558,15 +573,15 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
558
573
|
if (!dropOpen) return;
|
|
559
574
|
|
|
560
575
|
const nextIndex =
|
|
561
|
-
e.key ===
|
|
576
|
+
e.key === 'ArrowDown'
|
|
562
577
|
? (selectedIndex + 1) % filteredData.length
|
|
563
|
-
: e.key ===
|
|
578
|
+
: e.key === 'ArrowUp'
|
|
564
579
|
? (selectedIndex - 1 + filteredData.length) % filteredData.length
|
|
565
580
|
: selectedIndex;
|
|
566
581
|
|
|
567
582
|
switch (e.key) {
|
|
568
|
-
case
|
|
569
|
-
case
|
|
583
|
+
case 'ArrowDown':
|
|
584
|
+
case 'ArrowUp':
|
|
570
585
|
e.preventDefault();
|
|
571
586
|
|
|
572
587
|
// Update index first
|
|
@@ -593,12 +608,12 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
593
608
|
});
|
|
594
609
|
break;
|
|
595
610
|
|
|
596
|
-
case
|
|
611
|
+
case 'Enter':
|
|
597
612
|
e.preventDefault();
|
|
598
613
|
handleSuggestionClick(filteredData[selectedIndex], selectedIndex);
|
|
599
614
|
break;
|
|
600
615
|
|
|
601
|
-
case
|
|
616
|
+
case 'Escape':
|
|
602
617
|
e.preventDefault();
|
|
603
618
|
setDropOpen(false);
|
|
604
619
|
break;
|
|
@@ -609,9 +624,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
609
624
|
};
|
|
610
625
|
|
|
611
626
|
if (filteredData?.length > 0 && !isLoading) {
|
|
612
|
-
window.addEventListener(
|
|
627
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
613
628
|
return () => {
|
|
614
|
-
window.removeEventListener(
|
|
629
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
615
630
|
};
|
|
616
631
|
}
|
|
617
632
|
}, [
|
|
@@ -640,9 +655,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
640
655
|
<li
|
|
641
656
|
className={`${
|
|
642
657
|
value?.id === suggestion?.id
|
|
643
|
-
?
|
|
658
|
+
? 'bg-blue-navy text-white'
|
|
644
659
|
: `${
|
|
645
|
-
index === selectedIndex ?
|
|
660
|
+
index === selectedIndex ? 'is-selected' : ''
|
|
646
661
|
} hover:bg-table-hover`
|
|
647
662
|
} cursor-pointer p-1 text-xxs ps-3.5 pl-[10px] qbs-autocomplete-suggections-items`}
|
|
648
663
|
key={suggestion?.id}
|
|
@@ -707,7 +722,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
707
722
|
useEffect(() => {
|
|
708
723
|
const shouldShowClose =
|
|
709
724
|
value?.name &&
|
|
710
|
-
(value?.id || String(value?.id) ===
|
|
725
|
+
(value?.id || String(value?.id) === '0') &&
|
|
711
726
|
!disabled &&
|
|
712
727
|
!readOnly &&
|
|
713
728
|
isClose;
|
|
@@ -721,7 +736,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
721
736
|
if (inputRef.current) {
|
|
722
737
|
const { scrollWidth, clientWidth, value } = inputRef.current;
|
|
723
738
|
// Check for overflow only when there's content
|
|
724
|
-
if (value.trim() !==
|
|
739
|
+
if (value.trim() !== '') {
|
|
725
740
|
setShowTooltip(scrollWidth > clientWidth + 2);
|
|
726
741
|
} else {
|
|
727
742
|
setShowTooltip(false); // No tooltip for empty input
|
|
@@ -730,13 +745,13 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
730
745
|
};
|
|
731
746
|
|
|
732
747
|
if (inputRef.current) {
|
|
733
|
-
inputRef.current.addEventListener(
|
|
748
|
+
inputRef.current.addEventListener('input', checkOverflow);
|
|
734
749
|
checkOverflow(); // Initial check
|
|
735
750
|
}
|
|
736
751
|
|
|
737
752
|
return () => {
|
|
738
753
|
if (inputRef.current) {
|
|
739
|
-
inputRef.current.removeEventListener(
|
|
754
|
+
inputRef.current.removeEventListener('input', checkOverflow);
|
|
740
755
|
}
|
|
741
756
|
};
|
|
742
757
|
}, [inputValue]);
|
|
@@ -754,7 +769,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
754
769
|
id={
|
|
755
770
|
id ? `autocomplete-container-${id}` : `autocomplete-container-${name}`
|
|
756
771
|
}
|
|
757
|
-
className={` flex-grow ${fullWidth ?
|
|
772
|
+
className={` flex-grow ${fullWidth ? 'w-full' : 'w-auto'}`}
|
|
758
773
|
ref={dropdownref}
|
|
759
774
|
>
|
|
760
775
|
{label && !isModern && (
|
|
@@ -774,7 +789,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
774
789
|
)}
|
|
775
790
|
|
|
776
791
|
<div
|
|
777
|
-
className={`flex relative ${fullWidth ?
|
|
792
|
+
className={`flex relative ${fullWidth ? 'w-full' : 'w-auto'}`}
|
|
778
793
|
style={{ width: width }}
|
|
779
794
|
>
|
|
780
795
|
<div
|
|
@@ -784,8 +799,8 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
784
799
|
>
|
|
785
800
|
<input
|
|
786
801
|
type="text"
|
|
787
|
-
readOnly={readOnly ?? type ===
|
|
788
|
-
value={inputValue ? inputValue :
|
|
802
|
+
readOnly={readOnly ?? type === 'custom_select'}
|
|
803
|
+
value={inputValue ? inputValue : ''}
|
|
789
804
|
onBlur={handleClearInputValue}
|
|
790
805
|
autoComplete="off"
|
|
791
806
|
disabled={disabled}
|
|
@@ -808,21 +823,27 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
808
823
|
}
|
|
809
824
|
: {}),
|
|
810
825
|
}}
|
|
811
|
-
className={` ${generateClassName(
|
|
826
|
+
className={` ${generateClassName('input')}`}
|
|
812
827
|
onChange={handleChange}
|
|
813
828
|
placeholder={
|
|
814
|
-
type ===
|
|
829
|
+
type === 'auto_complete'
|
|
815
830
|
? placeholder && isCustomPlaceholder
|
|
816
831
|
? placeholder
|
|
817
|
-
:
|
|
818
|
-
: placeholder ??
|
|
832
|
+
: 'Type to search'
|
|
833
|
+
: placeholder ?? '--Select--'
|
|
819
834
|
}
|
|
820
835
|
onFocus={onInputFocus}
|
|
821
836
|
onClick={(e) => {
|
|
822
|
-
if (type ===
|
|
823
|
-
|
|
824
|
-
|
|
837
|
+
if (type === 'custom_select') {
|
|
838
|
+
e.stopPropagation();
|
|
839
|
+
if (!suggestions || suggestions?.length === 0) {
|
|
840
|
+
handleDropData();
|
|
841
|
+
}
|
|
842
|
+
if (!isLoading) {
|
|
843
|
+
setDropOpen(!dropOpen);
|
|
844
|
+
}
|
|
825
845
|
} else {
|
|
846
|
+
e.stopPropagation();
|
|
826
847
|
setDropOpen(!dropOpen);
|
|
827
848
|
}
|
|
828
849
|
}}
|
|
@@ -831,9 +852,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
831
852
|
<label
|
|
832
853
|
htmlFor={id}
|
|
833
854
|
onClick={() => onLabelClick()}
|
|
834
|
-
className={generateClassName(
|
|
855
|
+
className={generateClassName('label')}
|
|
835
856
|
>
|
|
836
|
-
{label ? <span className="truncate">{label}</span> :
|
|
857
|
+
{label ? <span className="truncate">{label}</span> : ''}
|
|
837
858
|
{required ? <span className="text-error"> *</span> : <></>}
|
|
838
859
|
</label>
|
|
839
860
|
)}
|
|
@@ -842,9 +863,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
842
863
|
<div
|
|
843
864
|
ref={adorementRef}
|
|
844
865
|
className={`${generateClassName(
|
|
845
|
-
|
|
866
|
+
'adorement'
|
|
846
867
|
)} qbs-autocomplete-adorement custom-dorpdown-adorement mr-[1px] ${
|
|
847
|
-
isLoading ?
|
|
868
|
+
isLoading ? 'bg-white' : ''
|
|
848
869
|
}`}
|
|
849
870
|
>
|
|
850
871
|
{showClose && (
|
|
@@ -859,11 +880,10 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
859
880
|
</button>
|
|
860
881
|
)}
|
|
861
882
|
{isLoading && <Spinner />}
|
|
862
|
-
{type !==
|
|
883
|
+
{type !== 'auto_complete' && !disabled && !readOnly && (
|
|
863
884
|
<button
|
|
864
885
|
disabled={disabled ?? readOnly}
|
|
865
886
|
onClick={(e) => handleOpen(e)}
|
|
866
|
-
onBlur={handleClose}
|
|
867
887
|
className=" text-[#667085] focus-visible:outline-slate-100"
|
|
868
888
|
data-testid="drop-arrow"
|
|
869
889
|
type="button"
|
|
@@ -883,7 +903,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
|
|
|
883
903
|
{errors && errors[name] && (
|
|
884
904
|
<div
|
|
885
905
|
className={` text-error-label relative cursor-pointer ${generateClassName(
|
|
886
|
-
|
|
906
|
+
'message'
|
|
887
907
|
)}`}
|
|
888
908
|
onMouseEnter={() => setIsHovered(true)}
|
|
889
909
|
onMouseLeave={() => setIsHovered(false)}
|