react-core-ts 2.1.3 → 2.1.5

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.
@@ -59,6 +59,7 @@ type ModernAutoCompleteSuggectionsProps = {
59
59
  desc?: string;
60
60
  /** Field name that contains the unique identifier (default: 'id'). */
61
61
  descId?: string;
62
+ showWarningIcon?: boolean;
62
63
  };
63
64
 
64
65
  /**
@@ -115,8 +116,10 @@ const ModernAutoCompleteSuggections: React.FC<
115
116
  labelTitle,
116
117
  desc = 'name',
117
118
  descId = 'id',
119
+ showWarningIcon = true,
118
120
  }) => {
119
121
  const [inputValue, setInputValue] = useState(value ?? '');
122
+ const [debouncedInputValue, setDebouncedInputValue] = useState('');
120
123
  const [items, setItems] = useState<SuggestionItem[]>(data ?? []);
121
124
  const [isLoading, setIsLoading] = useState(false);
122
125
  const [showDropdown, setShowDropdown] = useState(false);
@@ -152,13 +155,26 @@ const ModernAutoCompleteSuggections: React.FC<
152
155
  }
153
156
  }, [data]);
154
157
 
155
- // Load from getData only when user types some text (no initial preload)
158
+ // Debounce inputValue so we don't call API on every keystroke
159
+ useEffect(() => {
160
+ if (!hasTyped) return;
161
+ const handle = window.setTimeout(() => {
162
+ setDebouncedInputValue(inputValue);
163
+ }, 500); // 500ms debounce
164
+
165
+ return () => {
166
+ window.clearTimeout(handle);
167
+ };
168
+ }, [inputValue, hasTyped]);
169
+
170
+ // Load from getData only when user types some text (no initial preload),
171
+ // and only after debounce delay.
156
172
  useEffect(() => {
157
173
  // Do not call API until the user has actually typed at least once
158
174
  if (!hasTyped) return;
159
175
 
160
176
  let cancelled = false;
161
- const query = inputValue.trim();
177
+ const query = debouncedInputValue.trim();
162
178
  if (!getDataRef.current || query === '') {
163
179
  // Clear items when input is cleared so dropdown also clears
164
180
  if (!cancelled) {
@@ -189,7 +205,14 @@ const ModernAutoCompleteSuggections: React.FC<
189
205
  return () => {
190
206
  cancelled = true;
191
207
  };
192
- }, [inputValue, hasTyped, data]);
208
+ }, [debouncedInputValue, data]);
209
+
210
+ // Notify parent via onChange when debounced value changes
211
+ useEffect(() => {
212
+ if (!hasTyped) return;
213
+ if (!onChange) return;
214
+ onChange(debouncedInputValue);
215
+ }, [debouncedInputValue, onChange]);
193
216
 
194
217
  // Group by desc field and compute counts
195
218
  const grouped = useMemo(() => {
@@ -232,7 +255,14 @@ const ModernAutoCompleteSuggections: React.FC<
232
255
  return grouped.filter((g) => g.name.toLowerCase().includes(term));
233
256
  }, [grouped, inputValue, hasTyped]);
234
257
 
235
- // Update dropdown visibility based on visible items
258
+ const effectiveVisible = useMemo(() => {
259
+ if (!hasTyped && items.length > 0) {
260
+ return grouped;
261
+ }
262
+ return visible;
263
+ }, [hasTyped, items.length, grouped, visible]);
264
+
265
+ // Update dropdown visibility based on visible items from typing
236
266
  useEffect(() => {
237
267
  setShowDropdown(visible.length > 0);
238
268
  }, [visible.length]);
@@ -317,7 +347,7 @@ const ModernAutoCompleteSuggections: React.FC<
317
347
  };
318
348
 
319
349
  const generateClassName = (
320
- type: 'input' | 'label' | 'message' | 'adorement'
350
+ type: 'input' | 'label' | 'message' | 'adorement' | 'warning'
321
351
  ): string => {
322
352
  let className = propsClassName || '';
323
353
  switch (type) {
@@ -370,6 +400,9 @@ const ModernAutoCompleteSuggections: React.FC<
370
400
  case 'message':
371
401
  className = ' text-error-icon ';
372
402
  break;
403
+ case 'warning':
404
+ className = ' text-warning-icon ';
405
+ break;
373
406
  case 'adorement':
374
407
  className += ' absolute right-0 adorement gap-1 flex items-center ';
375
408
  break;
@@ -464,11 +497,16 @@ const ModernAutoCompleteSuggections: React.FC<
464
497
  value={inputValue ? inputValue : ''}
465
498
  ref={inputRef}
466
499
  disabled={disabled}
500
+ onFocus={() => {
501
+ // show suggestions when the field gains focus.
502
+ if (!disabled && effectiveVisible.length > 0) {
503
+ setShowDropdown(true);
504
+ }
505
+ }}
467
506
  onChange={(e) => {
468
507
  const val = e.target.value;
469
508
  setInputValue(val);
470
509
  setHasTyped(true);
471
- onChange?.(val);
472
510
  }}
473
511
  onBlur={() => {}}
474
512
  placeholder={placeholder}
@@ -510,16 +548,26 @@ const ModernAutoCompleteSuggections: React.FC<
510
548
  <CustomIcons name="alert" type="medium" />
511
549
  </div>
512
550
  )}
551
+
552
+ {showWarningIcon && effectiveVisible.length > 0 && (
553
+ <div
554
+ className={`text-warning-label relative mr-1 ${generateClassName(
555
+ 'warning'
556
+ )}`}
557
+ >
558
+ <CustomIcons name="alert" type="medium" />
559
+ </div>
560
+ )}
513
561
  </div>
514
562
  </div>
515
563
  </div>
516
564
  </div>
517
- {showDropdown && visible.length > 0 && (
565
+ {showDropdown && effectiveVisible.length > 0 && (
518
566
  <>
519
567
  {insideOpen ? (
520
568
  <div className="suggection-list">
521
569
  <div className="bg-white border border-grey-light shadow-gray-300 shadow-md rounded-sm max-h-40 overflow-auto text-[11px] text-gray-700 px-3.5 py-1.5">
522
- {visible.map((g) => (
570
+ {effectiveVisible.map((g) => (
523
571
  <SuggestionItem
524
572
  key={g.name}
525
573
  name={g.name}
@@ -536,12 +584,12 @@ const ModernAutoCompleteSuggections: React.FC<
536
584
  style={dropPosition}
537
585
  >
538
586
  <div className="h-auto max-h-40 overflow-auto w-full py-1.5">
539
- {visible.map((g) => (
587
+ {effectiveVisible.map((g) => (
540
588
  <div key={g.name} className="px-3.5 text-[11px] text-gray-700">
541
589
  <SuggestionItem
542
590
  name={g.name}
543
591
  count={g.count}
544
- showCount={g.count > -1}
592
+ showCount={g.count > 0}
545
593
  />
546
594
  </div>
547
595
  ))}