react-core-ts 1.4.10 → 1.4.12

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.
Files changed (51) hide show
  1. package/README.md +2 -1
  2. package/dist/AutoComplete.js +3 -3
  3. package/dist/AutoComplete.js.map +1 -1
  4. package/dist/AutoCompleteWithSelectedList.js +83 -21
  5. package/dist/AutoCompleteWithSelectedList.js.map +1 -1
  6. package/dist/AutoCompleteWithTreeStructure.js +4 -4
  7. package/dist/AutoCompleteWithTreeStructure.js.map +1 -1
  8. package/dist/ExpandableAutoComplete.js +6 -4
  9. package/dist/ExpandableAutoComplete.js.map +1 -1
  10. package/dist/ReactAutoComplete.d.ts +1 -0
  11. package/dist/ReactAutoComplete.js +77 -19
  12. package/dist/ReactAutoComplete.js.map +1 -1
  13. package/dist/ReactCheckbox.d.ts +1 -1
  14. package/dist/ReactCheckbox.js +1 -1
  15. package/dist/ReactCheckbox.js.map +1 -1
  16. package/dist/ReactOTPInput.js +3 -3
  17. package/dist/ReactOTPInput.js.map +1 -1
  18. package/dist/ReactRadioButton.js +1 -1
  19. package/dist/ReactRadioButton.js.map +1 -1
  20. package/dist/ReactTextArea.js +1 -1
  21. package/dist/ReactTextArea.js.map +1 -1
  22. package/dist/ReactTextField.js +1 -1
  23. package/dist/ReactTextField.js.map +1 -1
  24. package/dist/commontypes.d.ts +1 -0
  25. package/dist/components/DropdownList.d.ts +3 -0
  26. package/dist/components/DropdownList.js +2 -2
  27. package/dist/components/DropdownList.js.map +1 -1
  28. package/dist/dummyAutoCompleteWithSelectedList.js +2 -2
  29. package/dist/dummyAutoCompleteWithSelectedList.js.map +1 -1
  30. package/dist/styles/components/autocomplete.css +25 -0
  31. package/docs/App.tsx +1 -1
  32. package/package.json +2 -1
  33. package/src/AutoComplete.tsx +3 -0
  34. package/src/AutoCompleteWithSelectedList.tsx +86 -6
  35. package/src/AutoCompleteWithTreeStructure.tsx +10 -11
  36. package/src/ExpandableAutoComplete.tsx +16 -4
  37. package/src/ReactAutoComplete.tsx +88 -8
  38. package/src/ReactCheckbox.tsx +5 -4
  39. package/src/ReactOTPInput.tsx +9 -5
  40. package/src/ReactRadioButton.tsx +2 -1
  41. package/src/ReactTextArea.tsx +1 -1
  42. package/src/ReactTextField.tsx +1 -0
  43. package/src/commontypes.ts +1 -0
  44. package/src/components/DropdownList.tsx +12 -2
  45. package/src/dummyAutoCompleteWithSelectedList.tsx +3 -8
  46. package/src/styles/components/autocomplete.css +25 -0
  47. package/dist/styles/styles/components/autocomplete.css +0 -630
  48. package/dist/styles/styles/components/selectedautocomplete.css +0 -130
  49. package/dist/styles/styles/components/tooltip.css +0 -497
  50. package/dist/styles/styles/components/treedropdown.css +0 -97
  51. package/dist/styles/styles/global.css +0 -8
@@ -25,7 +25,7 @@ interface AutoSuggestionInputProps {
25
25
  className?: string;
26
26
  autoFocus?: boolean;
27
27
  required?: boolean;
28
-
28
+ shortCode?: string
29
29
  hideClear?: boolean;
30
30
  value?: valueProps;
31
31
  onChange: (value?: valueProps) => void;
@@ -62,6 +62,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
62
62
  required = false,
63
63
  autoFocus,
64
64
  name,
65
+ shortCode = '',
65
66
  fullWidth,
66
67
  placeholder,
67
68
  id,
@@ -98,6 +99,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
98
99
  const dropdownref = useRef<HTMLDivElement>(null);
99
100
  const dropBtnRef = useRef<HTMLButtonElement>(null);
100
101
  const timerRef = useRef<number>(0); // To fix the no results found issue on second type
102
+ const [selectedIndex, setSelectedIndex] = useState(0);
103
+ const itemRefs = useRef<(HTMLLIElement | null)[]>([]);
104
+ const scrollContainerRef = useRef<HTMLUListElement | null>(null);
101
105
  const [dropPosition, setDropPosition] = useState<any>({
102
106
  top: 0,
103
107
  left: 0,
@@ -306,7 +310,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
306
310
  useEffect(() => {
307
311
  setIsDisabled(disabled);
308
312
  }, [disabled]);
309
- const handleSuggestionClick = (suggestion: valueProps) => {
313
+ const handleSuggestionClick = (suggestion: valueProps, index: number) => {
310
314
  onChange({
311
315
  ...suggestion,
312
316
  id: suggestion?.id,
@@ -315,6 +319,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
315
319
  });
316
320
  if (type !== 'custom_select') setInputValue(suggestion.name);
317
321
  setDropOpen(false);
322
+ setSelectedIndex(index);
318
323
  };
319
324
  const handleOpen = (e: any) => {
320
325
  if (!suggestions || suggestions?.length === 0) handleDropData();
@@ -330,6 +335,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
330
335
 
331
336
  useEffect(() => {
332
337
  if (!insideOpen) {
338
+ setSelectedIndex(0);
333
339
  window.addEventListener('scroll', handleScroll);
334
340
 
335
341
  const mainElement = document.querySelector('main');
@@ -357,6 +363,53 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
357
363
  }
358
364
  }, [dropOpen]);
359
365
 
366
+ // Handle keyboard navigation
367
+ const handleKeyDown = (e: any) => {
368
+ if (!dropOpen) return;
369
+
370
+ const atBottom = selectedIndex === filteredData.length - 1;
371
+ const atTop = selectedIndex === 0;
372
+
373
+ switch (e.key) {
374
+ case "ArrowDown":
375
+ e.preventDefault();
376
+ if (itemRefs.current && scrollContainerRef.current) {
377
+ if (!atBottom) {
378
+ scrollContainerRef.current.scrollTop += itemRefs.current[selectedIndex]?.offsetHeight || 50;
379
+ } else {
380
+ scrollContainerRef.current.scrollTop = 0;
381
+ }
382
+ }
383
+ setSelectedIndex((prev) => (prev + 1) % filteredData?.length);
384
+ break;
385
+
386
+ case "ArrowUp":
387
+ e.preventDefault();
388
+ if (itemRefs.current && scrollContainerRef.current) {
389
+ if (!atTop) {
390
+ scrollContainerRef.current.scrollTop -= itemRefs.current[selectedIndex]?.offsetHeight || 50;
391
+ } else {
392
+ scrollContainerRef.current.scrollTop = 0;
393
+ }
394
+ }
395
+ setSelectedIndex((prev) => (prev - 1 + filteredData?.length) % filteredData?.length);
396
+ break;
397
+
398
+ case "Enter":
399
+ e.preventDefault();
400
+ handleSuggestionClick(filteredData[selectedIndex], selectedIndex);
401
+ break;
402
+
403
+ case "Escape":
404
+ e.preventDefault();
405
+ setDropOpen(false);
406
+ break;
407
+
408
+ default:
409
+ break;
410
+ }
411
+ };
412
+
360
413
  const handleClear = () => {
361
414
  setDropOpen(false);
362
415
  setInputValue('');
@@ -461,7 +514,10 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
461
514
  // return 'bottom'
462
515
  // }
463
516
  const filteredData =
464
- inputValue !== '*' && inputValue !== '' && type !== 'custom_select' && !noLocalFilter
517
+ inputValue !== '*' &&
518
+ inputValue !== '' &&
519
+ type !== 'custom_select' &&
520
+ !noLocalFilter
465
521
  ? suggestions?.filter((item: valueProps) =>
466
522
  checkIncludes(
467
523
  item.name,
@@ -527,6 +583,12 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
527
583
  return () => clearTimeout(timer);
528
584
  } else {
529
585
  setShowNoResults(false);
586
+ if(filteredData?.length > 0 && !isLoading) {
587
+ window.addEventListener("keydown", handleKeyDown);
588
+ return(() => {
589
+ window.removeEventListener("keydown", handleKeyDown);
590
+ })
591
+ }
530
592
  }
531
593
  }, [inputValue, filteredData, isLoading, timerRef.current]);
532
594
 
@@ -536,6 +598,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
536
598
  <ul
537
599
  className="autocomplete-suggections absolute h-auto max-h-40 overflow-auto w-full bg-white shadow-gray-300 shadow-md border border-grey-light py-1.5 z-50 mt-9"
538
600
  style={dropPosition}
601
+ ref={scrollContainerRef}
539
602
  >
540
603
  {filteredData?.length > 0 ? (
541
604
  <>
@@ -545,12 +608,18 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
545
608
  value?.id === suggestion?.id
546
609
  ? 'bg-blue-navy text-white'
547
610
  : 'hover:bg-table-hover'
548
- } cursor-pointer p-1 text-xxs ps-3.5 pl-[10px]`}
611
+ } ${index === selectedIndex ? "is-selected" : ""} cursor-pointer p-1 text-xxs ps-3.5 pl-[10px] qbs-autocomplete-suggections-items`}
549
612
  key={suggestion?.id}
550
613
  data-testid={suggestion.name}
551
- onClick={() => handleSuggestionClick(suggestion)}
614
+ onClick={() => handleSuggestionClick(suggestion, index)}
615
+ tabIndex={index}
616
+ ref={(el) => (itemRefs.current[index] = el)}
552
617
  >
553
- {suggestion?.label ? suggestion?.label : suggestion.name}
618
+ <span>
619
+ {suggestion?.label ? suggestion?.label : suggestion.name}
620
+ </span>
621
+
622
+ {shortCode && suggestion?.[shortCode] && <span className='short-code'>{suggestion?.[shortCode]}</span>}
554
623
  </li>
555
624
  ))}
556
625
  </>
@@ -636,6 +705,9 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
636
705
 
637
706
  return (
638
707
  <div
708
+ id={
709
+ id ? `autocomplete-container-${id}` : `autocomplete-container-${name}`
710
+ }
639
711
  className={` flex-grow ${fullWidth ? 'w-full' : 'w-auto'}`}
640
712
  ref={dropdownref}
641
713
  >
@@ -665,13 +737,16 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
665
737
  onMouseLeave={() => handleMouseLeave()}
666
738
  >
667
739
  <input
668
- id={id}
669
740
  type="text"
670
741
  readOnly={readOnly ?? type === 'custom_select'}
671
742
  value={inputValue ? inputValue : ''}
672
743
  onBlur={handleClearInputValue}
744
+ autoComplete="off"
673
745
  disabled={disabled}
674
746
  ref={inputRef}
747
+ id={
748
+ id ? `custom-autocomplete-${id}` : `custom-autocomplete-${name}`
749
+ }
675
750
  data-testid="custom-autocomplete"
676
751
  // onBlur={() => {
677
752
  // setInputValue("")
@@ -732,6 +807,7 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
732
807
  className=" text-table-bodyColor text-[#667085]"
733
808
  aria-label="close"
734
809
  type="button"
810
+ id="autocomplete-close-icon"
735
811
  >
736
812
  <CustomIcons name="close" type="large-m" />
737
813
  </button>
@@ -745,12 +821,16 @@ const ModernAutoComplete: React.FC<AutoSuggestionInputProps> = ({
745
821
  className=" text-[#667085] focus-visible:outline-slate-100"
746
822
  data-testid="drop-arrow"
747
823
  type="button"
824
+ id="autocomplete-drop-icon"
748
825
  ref={dropBtnRef}
749
826
  >
750
827
  {!dropOpen ? (
751
828
  <DropArrow uniqueDropArrowId="drop-arrow-icon" />
752
829
  ) : (
753
- <DropArrow className="rotate-180" uniqueDropArrowId="drop-arrow-icon" />
830
+ <DropArrow
831
+ className="rotate-180"
832
+ uniqueDropArrowId="drop-arrow-icon"
833
+ />
754
834
  )}
755
835
  </button>
756
836
  )}
@@ -1,6 +1,6 @@
1
- import { CheckboxProps } from './commontypes'
2
1
  import React from 'react'
3
2
 
3
+ import { CheckboxProps } from './commontypes'
4
4
  import CustomIcons from './components/customIcons'
5
5
 
6
6
  const Checkbox: React.FC<CheckboxProps> = ({
@@ -32,7 +32,7 @@ const Checkbox: React.FC<CheckboxProps> = ({
32
32
  return (
33
33
  <div
34
34
  className={`text-common font-normal text-grey-secondary flex items-center justify-start gap-2.5 ${
35
- disabled ? " opacity-70" : ""
35
+ disabled ? ' opacity-70' : ''
36
36
  } `}
37
37
  >
38
38
  <div>
@@ -41,9 +41,10 @@ const Checkbox: React.FC<CheckboxProps> = ({
41
41
  type="checkbox"
42
42
  disabled={disabled}
43
43
  name={name}
44
+ autoComplete="off"
44
45
  className="border-none outline-none invisible "
45
46
  data-testid="app-common-checkbox"
46
- id={id}
47
+ id={id ? `input-check-${id}` : `input-check-${name}`}
47
48
  value={value}
48
49
  checked={checked}
49
50
  onChange={handleChange}
@@ -51,7 +52,7 @@ const Checkbox: React.FC<CheckboxProps> = ({
51
52
 
52
53
  <div
53
54
  className={`absolute top-[2px] left-0 text-text-primary ${propsClassName} ${
54
- disabled ? "cursor-not-allowed" : "cursor-pointer"
55
+ disabled ? 'cursor-not-allowed' : 'cursor-pointer'
55
56
  }`}
56
57
  >
57
58
  {checked ? (
@@ -146,23 +146,27 @@ const OTPInput: React.FC<OTPInputProps> = ({
146
146
  </div>
147
147
  )}
148
148
  <div className="flex flex-col w-fit">
149
- <div className="flex gap-x-5 ">
149
+ <div
150
+ className="flex gap-x-5 "
151
+ id={id ? `input-otp-${id}` : `input-otp-${name}`}
152
+ >
150
153
  {Array(BoxLength)
151
- .fill("")
154
+ .fill('')
152
155
  .map((_, index) => (
153
156
  <input
154
157
  key={index}
155
158
  name={name}
156
159
  id={id}
157
160
  type="text"
161
+ autoComplete="off"
158
162
  value={otp[index]}
159
163
  onChange={(e) => handleChange(e, index)}
160
164
  onKeyDown={(e) => handleKeyDown(e, index)}
161
165
  onPaste={handlePaste}
162
166
  ref={(el) => (inputRefs.current[index] = el)}
163
167
  maxLength={1}
164
- onFocus={(e) => (e.target.style.borderColor = "#667085")}
165
- onBlur={(e) => (e.target.style.borderColor = "#D0D5DD")}
168
+ onFocus={(e) => (e.target.style.borderColor = '#667085')}
169
+ onBlur={(e) => (e.target.style.borderColor = '#D0D5DD')}
166
170
  className="w-[54px] h-10 text-center text-lg border border-[#D0D5DD] focus:border-[#667085] transition-colors duration-200 outline-none rounded-sm"
167
171
  />
168
172
  ))}
@@ -171,7 +175,7 @@ const OTPInput: React.FC<OTPInputProps> = ({
171
175
  <p className="text-common text-[#475467]">Didn't receive a code? </p>
172
176
  <span
173
177
  className={`text-common text-[#003C71] ml-2 ${
174
- !isTimerCompleted ? "cursor-not-allowed" : "cursor-pointer"
178
+ !isTimerCompleted ? 'cursor-not-allowed' : 'cursor-pointer'
175
179
  }`}
176
180
  onClick={handleResend}
177
181
  >
@@ -36,13 +36,14 @@ const Radio: React.FC<RadioProps> = ({
36
36
  >
37
37
  <input
38
38
  type="radio"
39
+ autoComplete="off"
39
40
  checked={checked}
40
41
  disabled={disabled}
42
+ id={id ? `input-button-${id}` : `input-button-${name}`}
41
43
  ref={radioRef}
42
44
  name={name}
43
45
  data-testid="app-common-radio"
44
46
  value={value}
45
- id={id}
46
47
  onChange={onChange}
47
48
  />
48
49
  <span className="radio"></span>
@@ -187,7 +187,7 @@ const ModernTextArea: React.FC<TextAreaProps> = ({
187
187
  <div className={`flex relative ${fullwidth ? 'w-full' : 'w-auto'}`}>
188
188
  <div className="relative w-full">
189
189
  <textarea
190
- id={id}
190
+ id={id ? `input-textarea-${id}` : `input-textarea-${name}`}
191
191
  ref={inputRef}
192
192
  disabled={isDisabled}
193
193
  data-testid="textarea"
@@ -294,6 +294,7 @@ const TextField: React.FC<TextFieldProps> = ({
294
294
  type={type}
295
295
  // id={frmid+id}
296
296
  ref={inputRef}
297
+ id={id ? `input-${id}` : `input-${name}`}
297
298
  disabled={isDisabled}
298
299
  // step={step}
299
300
  min={min}
@@ -77,6 +77,7 @@ export interface AutoSuggestionInputProps {
77
77
  filterKey?: any;
78
78
  filterValue?: any;
79
79
  };
80
+ shortCode?: string
80
81
  }
81
82
  export interface IconsProps {
82
83
  name: any;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
 
3
3
  type ValueProps = {
4
4
  idx: number;
@@ -11,6 +11,9 @@ type ValueProps = {
11
11
  singleSelect?: boolean;
12
12
  desc: string;
13
13
  hideCheckbox?: boolean;
14
+ shortCode?: string
15
+ focusedIndex?: number
16
+ setItemRef?: (index: number, ref: HTMLDivElement | null) => void
14
17
  };
15
18
  const DropdownList: React.FC<ValueProps> = ({
16
19
  idx,
@@ -23,13 +26,19 @@ const DropdownList: React.FC<ValueProps> = ({
23
26
  singleSelect,
24
27
  desc,
25
28
  hideCheckbox = false,
29
+ shortCode = '',
30
+ focusedIndex = 0,
31
+ setItemRef
26
32
  }) => {
33
+
27
34
  return (
28
35
  <div
29
36
  key={idx.toString()}
37
+ ref={(el) => setItemRef?.(idx, el)} // Properly store each ref
30
38
  className={`qbs-autocomplete-listitem-container ${
31
39
  (isMultiple || singleSelect) && 'qbs-autocomplete-checkbox-container'
32
- } ${isSelected(suggestion, selected) ? 'is-selected' : ''}`}
40
+ } ${isSelected(suggestion, selected) ? 'is-selected' : ''} ${idx === focusedIndex ? "is-selected" : ""}`}
41
+ tabIndex={idx}
33
42
  >
34
43
  {(isMultiple || singleSelect) && !hideCheckbox && (
35
44
  <div className="qbs-autocomplete-checkbox">
@@ -65,6 +74,7 @@ const DropdownList: React.FC<ValueProps> = ({
65
74
  >
66
75
  {suggestion[desc]}
67
76
  </div>
77
+ {shortCode && suggestion?.[shortCode] && <div className='short-code'>{suggestion?.[shortCode]}</div>}
68
78
  </div>
69
79
  );
70
80
  };
@@ -1,11 +1,4 @@
1
- import React, {
2
- forwardRef,
3
- useCallback,
4
- useEffect,
5
- useImperativeHandle,
6
- useRef,
7
- useState,
8
- } from 'react';
1
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
9
2
  import ReactDOM from 'react-dom';
10
3
 
11
4
  import { AutoSuggestionInputProps, TabPops, ValueProps } from './commontypes';
@@ -568,6 +561,7 @@ const AutoCompleteWithSelectedList = forwardRef<
568
561
  >
569
562
  <input
570
563
  id={id}
564
+ autoComplete="off"
571
565
  ref={inputRef}
572
566
  type="text"
573
567
  value={
@@ -642,6 +636,7 @@ const AutoCompleteWithSelectedList = forwardRef<
642
636
  onChange={handleSuggestionChange}
643
637
  value={searchValue}
644
638
  placeholder="Search"
639
+ autoComplete="off"
645
640
  ref={inputSearchRef}
646
641
  />
647
642
  </div>
@@ -463,6 +463,8 @@ span.dropdown-search-icon {
463
463
  padding: 6px 8px;
464
464
  display: flex;
465
465
  align-items: flex-start;
466
+ outline: none;
467
+ box-shadow: none;
466
468
  }
467
469
 
468
470
  .qbs-autocomplete-checkbox-container .qbs-autocomplete-suggestions-item {
@@ -628,3 +630,26 @@ span.dropdown-search-icon {
628
630
  margin-left: -5px;
629
631
  border-color: transparent transparent #000 transparent;
630
632
  }
633
+
634
+ .autocomplete-suggections .qbs-autocomplete-suggections-items {
635
+ display: flex;
636
+ justify-content: space-between;
637
+ align-items: center;
638
+ cursor: pointer;
639
+ outline: none;
640
+ box-shadow: none;
641
+ }
642
+
643
+ .qbs-autocomplete-suggections-items.is-selected {
644
+ background-color: #f1f5f9;
645
+ }
646
+
647
+ .autocomplete-suggections .qbs-autocomplete-suggections-items .short-code,
648
+ .qbs-autocomplete-listitem-container .short-code{
649
+ font-size: 12px;
650
+ background: #f0f0f0;
651
+ padding: 4px 8px;
652
+ border: 1px solid #ccc;
653
+ border-radius: 4px;
654
+ white-space: nowrap;
655
+ }