react-core-ts 2.0.23 → 2.1.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/AutoComplete.js +28 -3
- package/dist/AutoComplete.js.map +1 -1
- package/dist/ReactAutoComplete.js +29 -1
- package/dist/ReactAutoComplete.js.map +1 -1
- package/dist/ReactAutoCompleteDropdown.js +29 -1
- package/dist/ReactAutoCompleteDropdown.js.map +1 -1
- package/dist/ReactAutoCompleteSuggections.d.ts +74 -0
- package/dist/ReactAutoCompleteSuggections.js +379 -0
- package/dist/ReactAutoCompleteSuggections.js.map +1 -0
- package/dist/dropdownFilterTabs.js +162 -95
- package/dist/dropdownFilterTabs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/styles/styles/components/autocomplete.css +744 -0
- package/dist/styles/styles/components/selectedautocomplete.css +221 -0
- package/dist/styles/styles/components/tooltip.css +497 -0
- package/dist/styles/styles/components/treedropdown.css +97 -0
- package/dist/styles/styles/global.css +8 -0
- package/docs/App.tsx +18 -2
- package/package.json +1 -1
- package/src/AutoComplete.tsx +29 -1
- package/src/ReactAutoComplete.tsx +30 -1
- package/src/ReactAutoCompleteDropdown.tsx +30 -1
- package/src/ReactAutoCompleteSuggections.tsx +559 -0
- package/src/dropdownFilterTabs.tsx +130 -47
- package/src/index.tsx +1 -0
|
@@ -144,6 +144,7 @@ const DropdownFilterTabs = forwardRef<
|
|
|
144
144
|
const [isKeyboardOpen, setIsKeyboardOpen] = useState(false);
|
|
145
145
|
const [hasMoreOptionValues, setHasMoreOptionValues] = useState(false);
|
|
146
146
|
const [tabsScrollable, setTabsScrollable] = useState(false);
|
|
147
|
+
const scrollableDivsRef = useRef<NodeListOf<Element> | null>(null);
|
|
147
148
|
|
|
148
149
|
// Use external reset key if provided, otherwise default to 0
|
|
149
150
|
const currentResetKey = externalResetKey !== undefined ? externalResetKey : 0;
|
|
@@ -170,9 +171,16 @@ const DropdownFilterTabs = forwardRef<
|
|
|
170
171
|
setActiveTab(currentTab);
|
|
171
172
|
}, [currentTab]);
|
|
172
173
|
|
|
174
|
+
// Reset focused index when active tab changes
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
setFocusedIndex(0);
|
|
177
|
+
}, [activeTab]);
|
|
178
|
+
|
|
173
179
|
const adjustDropdownPosition = () => {
|
|
174
|
-
|
|
175
|
-
|
|
180
|
+
// Use requestAnimationFrame to ensure DOM is ready
|
|
181
|
+
requestAnimationFrame(() => {
|
|
182
|
+
if (dropdownRef?.current) {
|
|
183
|
+
const inputRect = dropdownRef?.current?.getBoundingClientRect();
|
|
176
184
|
const dropdownPosition = {
|
|
177
185
|
left: inputRect.left + window.scrollX,
|
|
178
186
|
width: inputRect.width,
|
|
@@ -248,14 +256,14 @@ const DropdownFilterTabs = forwardRef<
|
|
|
248
256
|
// setDropdownStyle({
|
|
249
257
|
// ...dropdownPosition,
|
|
250
258
|
// });
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
+
setDropdownStyle((prevStyle) => ({
|
|
260
|
+
...prevStyle,
|
|
261
|
+
transform: `translateY(${dropdownPosition.top}px)`,
|
|
262
|
+
left: desiredLeft,
|
|
263
|
+
width: desiredWidth,
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
});
|
|
259
267
|
};
|
|
260
268
|
|
|
261
269
|
useEffect(() => {
|
|
@@ -291,18 +299,40 @@ const DropdownFilterTabs = forwardRef<
|
|
|
291
299
|
setSelectedItems((prev) => {
|
|
292
300
|
const isAdded =
|
|
293
301
|
prev && prev.length > 0
|
|
294
|
-
? prev.some(
|
|
295
|
-
|
|
302
|
+
? prev.some((item) => {
|
|
303
|
+
const sameId =
|
|
296
304
|
getKeyValue(item, descId, 'id') ===
|
|
297
|
-
getKeyValue(suggestion, descId, 'id')
|
|
298
|
-
|
|
305
|
+
getKeyValue(suggestion, descId, 'id');
|
|
306
|
+
|
|
307
|
+
if (!sameId) return false;
|
|
308
|
+
|
|
309
|
+
// If there is no tab context, treat any same-id item as already added
|
|
310
|
+
if (
|
|
311
|
+
currentTabId === undefined ||
|
|
312
|
+
item?.tabId === undefined
|
|
313
|
+
) {
|
|
314
|
+
return true;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// With tab context, only consider items from the current tab
|
|
318
|
+
return item.tabId === currentTabId;
|
|
319
|
+
})
|
|
299
320
|
: false;
|
|
300
321
|
if (isAdded) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
getKeyValue(
|
|
305
|
-
|
|
322
|
+
// Remove only the item for the current tab (if tabId is used)
|
|
323
|
+
return prev.filter((item) => {
|
|
324
|
+
const sameId =
|
|
325
|
+
getKeyValue(item, descId, 'id') ===
|
|
326
|
+
getKeyValue(suggestion, descId, 'id');
|
|
327
|
+
|
|
328
|
+
if (!sameId) return true;
|
|
329
|
+
|
|
330
|
+
if (currentTabId === undefined || item?.tabId === undefined) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return item.tabId !== currentTabId;
|
|
335
|
+
});
|
|
306
336
|
} else {
|
|
307
337
|
// Include tab ID when adding suggestion
|
|
308
338
|
const suggestionWithTabId = {
|
|
@@ -350,12 +380,23 @@ const DropdownFilterTabs = forwardRef<
|
|
|
350
380
|
};
|
|
351
381
|
setSelectedItems((prev) => [...prev, suggestionWithTabId]);
|
|
352
382
|
} else {
|
|
383
|
+
// When unchecking, only remove the item for the current tab (if tabId is used)
|
|
353
384
|
setSelectedItems((prev) => {
|
|
354
|
-
return prev.filter(
|
|
355
|
-
|
|
356
|
-
getKeyValue(item, descId, 'id')
|
|
357
|
-
getKeyValue(suggestion, descId, 'id')
|
|
358
|
-
|
|
385
|
+
return prev.filter((item) => {
|
|
386
|
+
const sameId =
|
|
387
|
+
getKeyValue(item, descId, 'id') ===
|
|
388
|
+
getKeyValue(suggestion, descId, 'id');
|
|
389
|
+
|
|
390
|
+
if (!sameId) return true;
|
|
391
|
+
|
|
392
|
+
// If there is no tab context, behave as before (remove by id)
|
|
393
|
+
if (currentTabId === undefined || item?.tabId === undefined) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// With tab context, only remove the item that belongs to the current tab
|
|
398
|
+
return item.tabId !== currentTabId;
|
|
399
|
+
});
|
|
359
400
|
});
|
|
360
401
|
}
|
|
361
402
|
} else {
|
|
@@ -519,22 +560,44 @@ const DropdownFilterTabs = forwardRef<
|
|
|
519
560
|
// Capture-phase scroll catches scrolls from any scroll container (scroll doesn't bubble).
|
|
520
561
|
document.addEventListener('scroll', handleScroll as any, true);
|
|
521
562
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
)
|
|
525
|
-
|
|
563
|
+
// Query scrollable divs and store in ref for cleanup
|
|
564
|
+
// Re-query when dropdown opens to catch dynamically added containers
|
|
565
|
+
const queryScrollableDivs = () => {
|
|
566
|
+
return document.querySelectorAll(
|
|
567
|
+
'div[style*="overflow"], .overflow-auto, .overflow-y-auto, .overflow-x-auto'
|
|
568
|
+
);
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// Clean up previous listeners if any
|
|
572
|
+
if (scrollableDivsRef.current) {
|
|
573
|
+
scrollableDivsRef.current.forEach((div) =>
|
|
574
|
+
div.removeEventListener('scroll', handleScroll as any)
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Query and attach listeners to scrollable divs
|
|
579
|
+
scrollableDivsRef.current = queryScrollableDivs();
|
|
580
|
+
scrollableDivsRef.current.forEach((div) =>
|
|
526
581
|
div.addEventListener('scroll', handleScroll as any)
|
|
527
582
|
);
|
|
583
|
+
|
|
528
584
|
if (scrollRef && scrollRef.current && scrollRef.current !== null) {
|
|
529
585
|
scrollRef.current.addEventListener('scroll', handleScroll as any);
|
|
530
586
|
}
|
|
587
|
+
|
|
531
588
|
return () => {
|
|
532
589
|
document.removeEventListener('mousedown', handleClickOutside as any);
|
|
533
590
|
window.removeEventListener('scroll', handleScroll as any);
|
|
534
591
|
document.removeEventListener('scroll', handleScroll as any, true);
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
)
|
|
592
|
+
|
|
593
|
+
// Clean up scrollable divs listeners
|
|
594
|
+
if (scrollableDivsRef.current) {
|
|
595
|
+
scrollableDivsRef.current.forEach((div) =>
|
|
596
|
+
div.removeEventListener('scroll', handleScroll as any)
|
|
597
|
+
);
|
|
598
|
+
scrollableDivsRef.current = null;
|
|
599
|
+
}
|
|
600
|
+
|
|
538
601
|
if (closeOnScrollTimeoutRef.current) {
|
|
539
602
|
window.clearTimeout(closeOnScrollTimeoutRef.current);
|
|
540
603
|
closeOnScrollTimeoutRef.current = null;
|
|
@@ -549,7 +612,10 @@ const DropdownFilterTabs = forwardRef<
|
|
|
549
612
|
}, [dropOpen, typeOnlyFetch, uniqueDropArrowId, onToolClose]);
|
|
550
613
|
|
|
551
614
|
// Filtering suggestions based on type and search value
|
|
552
|
-
|
|
615
|
+
// Use filteredSelectedItems when tabs are present, otherwise use selectedItems
|
|
616
|
+
const selected: any = isMultiple
|
|
617
|
+
? (tab.length > 0 ? filteredSelectedItems : selectedItems)
|
|
618
|
+
: inputValue;
|
|
553
619
|
const filteredData: ValueProps[] = filterSuggestions(
|
|
554
620
|
suggestions,
|
|
555
621
|
searchValue,
|
|
@@ -574,18 +640,22 @@ const DropdownFilterTabs = forwardRef<
|
|
|
574
640
|
prevSelectedItemsRef.current = selectedItems;
|
|
575
641
|
}
|
|
576
642
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
643
|
+
// Use double requestAnimationFrame to ensure DOM updates are complete
|
|
644
|
+
requestAnimationFrame(() => {
|
|
645
|
+
requestAnimationFrame(() => {
|
|
646
|
+
adjustDropdownPosition();
|
|
647
|
+
});
|
|
648
|
+
});
|
|
581
649
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
582
650
|
}, [selectedItems]);
|
|
583
651
|
|
|
584
652
|
useEffect(() => {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
653
|
+
// Use double requestAnimationFrame to ensure DOM updates are complete
|
|
654
|
+
requestAnimationFrame(() => {
|
|
655
|
+
requestAnimationFrame(() => {
|
|
656
|
+
adjustDropdownPosition();
|
|
657
|
+
});
|
|
658
|
+
});
|
|
589
659
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
590
660
|
}, [filteredData]);
|
|
591
661
|
|
|
@@ -648,23 +718,35 @@ const DropdownFilterTabs = forwardRef<
|
|
|
648
718
|
};
|
|
649
719
|
}, [filteredData, dropOpen, isLoading, focusedIndex]);
|
|
650
720
|
|
|
651
|
-
const isSelected = (
|
|
721
|
+
const isSelected = useCallback((
|
|
652
722
|
item: ValueProps,
|
|
653
723
|
selectedItems: ValueProps[] | string
|
|
654
724
|
): boolean => {
|
|
655
725
|
if (Array.isArray(selectedItems)) {
|
|
656
|
-
return selectedItems.some(
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
726
|
+
return selectedItems.some((selectedItem) => {
|
|
727
|
+
// When tabs are present, ensure the selected item belongs to the current tab
|
|
728
|
+
if (tab.length > 0 && currentTabId !== undefined) {
|
|
729
|
+
// Only match if the selectedItem's tabId matches the current tab
|
|
730
|
+
// If selectedItem doesn't have tabId, don't match it (it belongs to no tab or old data)
|
|
731
|
+
if (selectedItem?.tabId === undefined || selectedItem.tabId !== currentTabId) {
|
|
732
|
+
return false;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return (
|
|
737
|
+
getKeyValue(selectedItem, desc, 'name') ===
|
|
738
|
+
getKeyValue(item, desc, 'name') ||
|
|
739
|
+
getKeyValue(selectedItem, descId, 'id') ===
|
|
740
|
+
getKeyValue(item, descId, 'id')
|
|
741
|
+
);
|
|
742
|
+
});
|
|
661
743
|
} else {
|
|
662
744
|
return (
|
|
663
745
|
getKeyValue(item, desc, 'name') === safeToLowerString(selectedItems) ||
|
|
664
746
|
getKeyValue(item, descId, 'id') === safeToLowerString(selectedItems)
|
|
665
747
|
);
|
|
666
748
|
}
|
|
667
|
-
};
|
|
749
|
+
}, [tab, currentTabId, desc, descId]);
|
|
668
750
|
|
|
669
751
|
const handleLoadMore = () => {
|
|
670
752
|
if (paginationEnabled) {
|
|
@@ -716,6 +798,7 @@ const DropdownFilterTabs = forwardRef<
|
|
|
716
798
|
handlePickSuggestions(searchValue, 1, false, activeTabVal);
|
|
717
799
|
}
|
|
718
800
|
setActiveTab(index);
|
|
801
|
+
setFocusedIndex(0); // Reset focused index when switching tabs
|
|
719
802
|
}
|
|
720
803
|
}, [activeTab, clearTabSwitch, handleClearSelected, tabInlineSearch, tab, searchValue, handlePickSuggestions, resetSuggections]);
|
|
721
804
|
|
package/src/index.tsx
CHANGED
|
@@ -10,6 +10,7 @@ export { default as AutoCompleteWithTreeStructure } from './AutoCompleteWithTree
|
|
|
10
10
|
export type { AutoSuggestionInputProps } from './commontypes';
|
|
11
11
|
export { default as ExpandableAutoComplete } from './ExpandableAutoComplete';
|
|
12
12
|
export { default as ModernAutoComplete } from './ReactAutoComplete';
|
|
13
|
+
export { default as ModernAutoCompleteSuggections } from './ReactAutoCompleteSuggections';
|
|
13
14
|
export { default as ModernCheckBox } from './ReactCheckbox';
|
|
14
15
|
export { default as ModernOtpInput } from './ReactOTPInput';
|
|
15
16
|
export { default as ModernRadio } from './ReactRadioButton';
|