react-core-ts 2.1.13 → 2.1.14

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.
@@ -0,0 +1,97 @@
1
+ .qbs-tree-list-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ }
5
+ .qbs-tree-list-container-sub {
6
+ display: flex;
7
+ flex-direction: row;
8
+ align-items: flex-start;
9
+ gap: 7px;
10
+ }
11
+
12
+ .qbs-tree-list-container-sub .no-children {
13
+ margin-left: 1.75rem; /* Corresponds to ml-7 in Tailwind */
14
+ }
15
+ .qbs-tree-list-container-sub-icon {
16
+ margin-top: 0.25rem; /* Corresponds to mt-1 in Tailwind */
17
+ cursor: pointer;
18
+ padding-top: 0.5rem; /* Corresponds to py-2 in Tailwind */
19
+ padding-bottom: 0.5rem;
20
+ transition: transform 0.3s ease; /* Smooth rotation transition */
21
+ color: #003c71;
22
+ }
23
+
24
+ .qbs-tree-list-container-sub-icon.expanded {
25
+ transform: rotate(90deg); /* Corresponds to rotate-90 in Tailwind */
26
+ }
27
+ .qbs-tree-list-container-sub-container {
28
+ display: flex;
29
+ gap: 15px; /* Corresponds to gap-2 in Tailwind */
30
+ padding: 0.5rem; /* Corresponds to p-2 in Tailwind */
31
+ flex-direction: row; /* Corresponds to flex-row in Tailwind */
32
+ width: 100%; /* Corresponds to w-full in Tailwind */
33
+ color: #3d414a;
34
+ }
35
+ .qbs-tree-list-container-sub-container-hideicon {
36
+ display: flex;
37
+ gap: 6px; /* Corresponds to gap-2 in Tailwind */
38
+ padding: 0.5rem; /* Corresponds to p-2 in Tailwind */
39
+ flex-direction: row; /* Corresponds to flex-row in Tailwind */
40
+ width: 100%; /* Corresponds to w-full in Tailwind */
41
+ color: #3d414a;
42
+ }
43
+ .qbs-tree-list-container-sub-container-hideicon:hover {
44
+ color: #003c71;
45
+ background-color: rgba(141, 194, 240, 0.15) !important;
46
+ }
47
+ .qbs-tree-list-container-sub-container:hover {
48
+ color: #003c71;
49
+ background-color: rgba(141, 194, 240, 0.15) !important;
50
+ }
51
+ .qbs-tree-list-container-sub-container.qbs-expanded-child {
52
+ color: #003c71;
53
+ }
54
+ .qbs-tree-list-container-sub-text.qbs-expanded-child {
55
+ color: #003c71;
56
+ }
57
+ .qbs-tree-list-container-sub-text:hover {
58
+ color: #003c71;
59
+ /* background-color: rgba(141, 194, 240, 0.15) !important; */
60
+ }
61
+
62
+ .qbs-tree-list-container-sub-container.checked,
63
+ .qbs-tree-list-container-sub-container-hideicon.checked {
64
+ color: #003c71;
65
+ background-color: rgba(
66
+ 141,
67
+ 194,
68
+ 240,
69
+ 0.15
70
+ ) !important; /* Corresponds to bg-green-200 in Tailwind */
71
+ }
72
+
73
+ .marginLeft {
74
+ margin-left: 28px; /* Corresponds to ml-2 in Tailwind */
75
+ }
76
+ .lightmarginLeft {
77
+ margin-left: 19px; /* Corresponds to ml-2 in Tailwind */
78
+ }
79
+ .qbs-tree-list-container-sub- {
80
+ line-height: 18px; /* Corresponds to leading-[18px] in Tailwind */
81
+ font-size: 0.875rem; /* Corresponds to text-sm in Tailwind (14px) */
82
+ }
83
+ .qbs-tree-list-container-child {
84
+ margin-left: 1rem; /* Corresponds to ml-4 in Tailwind */
85
+ margin-top: 0.5rem; /* Corresponds to mt-2 in Tailwind */
86
+ display: flex; /* Corresponds to flex in Tailwind */
87
+ flex-direction: column; /* Corresponds to flex-col in Tailwind */
88
+ gap: 0.5rem; /* Corresponds to gap-2 in Tailwind */
89
+ }
90
+ .qbs-tree-list-container-sub-text {
91
+ line-height: 18px; /* Corresponds to leading-[18px] in Tailwind */
92
+ font-size: 14px; /* Corresponds to text-sm in Tailwind (14px) */
93
+ font-weight: 500;
94
+ letter-spacing: 0.28px;
95
+ font-family: 'Noto Sans';
96
+ /* color: #3d414a; */
97
+ }
@@ -0,0 +1,8 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @import './components/autocomplete.css';
6
+ @import './components/treedropdown.css';
7
+ @import './components/selectedautocomplete.css';
8
+ @import './components/tooltip.css';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-core-ts",
3
- "version": "2.1.13",
3
+ "version": "2.1.14",
4
4
  "description": "React Components",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,8 @@
8
8
  "start": "webpack serve --open --mode development",
9
9
  "build": "tsc && cp -R src/styles dist/styles",
10
10
  "test": "jest",
11
- "prepublishOnly": "npm run build"
11
+ "prepublishOnly": "npm run build",
12
+ "prepare": "npm run build"
12
13
  },
13
14
  "repository": {
14
15
  "type": "git",
@@ -1034,7 +1034,8 @@ const AutoCompleteWithTabFilter = forwardRef<
1034
1034
  });
1035
1035
  }
1036
1036
 
1037
- // Don't clear here - clearing happens in handleApplyTabFilter after data is sent
1037
+ // Clear tabSelectedItems after applying filter and data is loaded
1038
+ onToolTabChange?.([]);
1038
1039
  setShowToolsTab(false);
1039
1040
  // Reset moreOptionTab component
1040
1041
  setMoreOptionResetKey(prev => prev + 1);
@@ -1055,21 +1056,12 @@ const AutoCompleteWithTabFilter = forwardRef<
1055
1056
  setAllDataLoaded(false);
1056
1057
  }, [showToolsTab]);
1057
1058
 
1058
- const handleApplyTabFilter = useCallback((data?: { selectedItems?: ValueProps[], moreOptionValues?: any }) => {
1059
- // Call onToolTabChange with selected items data when Apply is clicked
1060
- if (data?.selectedItems !== undefined) {
1061
- onToolTabChange?.(data.selectedItems);
1062
- // Clear tabSelectedItems after data is sent
1063
- // Use setTimeout to ensure the data is sent first
1064
- setTimeout(() => {
1065
- onToolTabChange?.([]);
1066
- }, 0);
1067
- }
1059
+ const handleApplyTabFilter = useCallback((moreOptionValues?: any) => {
1068
1060
  // Set flag to trigger effect when data loads
1069
1061
  setApplyTabFilter(true);
1070
1062
  handlePickSuggestions(searchValue ? searchValue : '*', 1);
1071
1063
  // Note: onMoreOptionChange is called when values change in the component, not here
1072
- }, [searchValue, handlePickSuggestions, onToolTabChange]);
1064
+ }, [searchValue, handlePickSuggestions]);
1073
1065
 
1074
1066
  useEffect(() => {
1075
1067
  const allSelected =
@@ -125,6 +125,7 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
125
125
  left: 0,
126
126
  bottom: 0,
127
127
  right: 0,
128
+ maxHeight: '60vh',
128
129
  });
129
130
  const checkIncludes = (
130
131
  mainString: string,
@@ -552,19 +553,25 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
552
553
 
553
554
  const getDropPosition = (): any => {
554
555
  if (!insideOpen && inputRef?.current) {
555
- const dropdownHeight = 200; // Assume the height of the dropdown is 200px, adjust as needed
556
+ const minDropdownHeight = 200;
557
+ const padding = 24; // gap + margin so dropdown doesn't touch viewport edge
556
558
  const isMobile = window.innerWidth < 768; // Mobile breakpoint
557
559
 
558
560
  const inputRect = inputRef.current.getBoundingClientRect();
559
- const spaceBelow =
560
- window.innerHeight - (inputRect.bottom + window.scrollY);
561
- const spaceAbove = inputRect.top + window.scrollY;
561
+ const maxHeightLimit = window.innerHeight * 0.6;
562
+ const spaceBelow = Math.max(0, window.innerHeight - inputRect.bottom - padding);
563
+ const spaceAbove = Math.max(0, inputRect.top - padding);
564
+ const availableSpace = Math.max(spaceAbove, spaceBelow);
565
+ const maxHeightPx = Math.min(Math.max(minDropdownHeight, availableSpace), maxHeightLimit);
562
566
 
563
- let top;
564
- let bottom;
565
- if (spaceBelow < dropdownHeight && spaceAbove > dropdownHeight) {
566
- bottom = spaceBelow + 43;
567
+ let top: number | undefined;
568
+ let bottom: number | undefined;
569
+ // Open above if there's more space above, or if there's not enough space below
570
+ if (spaceAbove > spaceBelow || (spaceBelow < minDropdownHeight && spaceAbove >= minDropdownHeight)) {
571
+ // Open above: position above input
572
+ bottom = window.innerHeight - inputRect.top + window.scrollY + 2;
567
573
  } else {
574
+ // Open below: position below input
568
575
  top = inputRect.top + window.scrollY + inputRect.height + 2;
569
576
  }
570
577
 
@@ -626,6 +633,7 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
626
633
  top,
627
634
  bottom,
628
635
  width,
636
+ maxHeight: `${maxHeightPx}px`,
629
637
  });
630
638
  }
631
639
 
@@ -723,13 +731,13 @@ const ReactAutoCompleteTableView: React.FC<AutoSuggestionInputProps> = ({
723
731
  return (
724
732
  (filteredData?.length > 0 || showNoResults) && (
725
733
  <div
726
- style={{ ...dropPosition, maxHeight: '60vh' }}
734
+ style={{ ...dropPosition, overflow: 'hidden' }}
727
735
  className="autocomplete-suggections autocomplete-suggections-tableview absolute bg-white shadow-gray-300 shadow-md border border-grey-light z-50 mt-9"
728
736
  >
729
737
  <ul
730
738
  className={`h-auto overflow-auto w-full ${tableView ? '' : 'py-1.5'}`}
731
739
  ref={scrollContainerRef}
732
- style={{ maxHeight: 'calc(60vh - 2rem)' }}
740
+ style={{ maxHeight: dropPosition.maxHeight ? `calc(${dropPosition.maxHeight} - 2rem)` : undefined }}
733
741
  >
734
742
  {filteredData?.length > 0 ? (
735
743
  <>
@@ -635,11 +635,8 @@ const DropdownFilterTabs = forwardRef<
635
635
  setIsInitialRender(false);
636
636
  } else {
637
637
  // Only call onChange if selectedItems actually changed
638
- // Skip onChange if applyTabFilter is provided (onChange will be called on Apply button click)
639
638
  if (!deepEqual(selectedItems, prevSelectedItemsRef.current)) {
640
- if (!applyTabFilter) {
641
- onChange(selectedItems);
642
- }
639
+ onChange(selectedItems);
643
640
  prevSelectedItemsRef.current = selectedItems;
644
641
  }
645
642
  }
@@ -650,7 +647,7 @@ const DropdownFilterTabs = forwardRef<
650
647
  });
651
648
  });
652
649
  // eslint-disable-next-line react-hooks/exhaustive-deps
653
- }, [selectedItems, applyTabFilter]);
650
+ }, [selectedItems]);
654
651
 
655
652
  useEffect(() => {
656
653
  // Use double requestAnimationFrame to ensure DOM updates are complete
@@ -992,19 +989,7 @@ const DropdownFilterTabs = forwardRef<
992
989
  setDropOpen(false);
993
990
  setSearchValue('');
994
991
  resetSuggections?.();
995
- // Extract selectedItems if it's included in values (from moreOptionTab), otherwise use state
996
- const itemsToPass = values?.selectedItems || selectedItems;
997
- // Extract moreOptionValues (exclude selectedItems from values if present)
998
- const { selectedItems: _, ...moreOptionValues } = values || {};
999
- const moreOpts = Object.keys(moreOptionValues).length > 0 ? moreOptionValues : values;
1000
- // When Apply button is used (moreOptionTab), notify parent of moreOption values
1001
- if (moreOpts !== undefined && moreOpts !== null) {
1002
- onMoreOptionChange?.(moreOpts);
1003
- }
1004
- // Pass all selected items from all tabs to applyTabFilter
1005
- applyTabFilter?.({ selectedItems: itemsToPass, moreOptionValues: moreOpts });
1006
- // Clear all selected items after applying
1007
- setSelectedItems([]);
992
+ applyTabFilter?.(values);
1008
993
  };
1009
994
 
1010
995
  useEffect(() => {
@@ -1063,19 +1048,13 @@ const DropdownFilterTabs = forwardRef<
1063
1048
  >
1064
1049
  {React.isValidElement(moreOptionTab)
1065
1050
  ? React.cloneElement(moreOptionTab as React.ReactElement<any>, {
1066
- onApply: (values?: any) => {
1067
- // Include selected tab values along with moreOption values
1068
- handleApplySelected({
1069
- ...values,
1070
- selectedItems: selectedItems
1071
- });
1072
- },
1051
+ onApply: (values?: any) => handleApplySelected(values),
1073
1052
  onValueChange: (values?: any) => {
1074
- // Only update local state for UI (e.g. Apply button visibility)
1075
- // onMoreOptionChange is called only when Apply button is clicked
1053
+ // Check if values exist and update state
1076
1054
  const hasValues = values !== undefined && values !== null &&
1077
1055
  (typeof values === 'object' ? Object.keys(values).length > 0 : true);
1078
1056
  setHasMoreOptionValues(hasValues);
1057
+ onMoreOptionChange?.(values);
1079
1058
  },
1080
1059
  } as any)
1081
1060
  : moreOptionTab}