react-core-ts 2.1.9 → 2.1.11

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.9",
3
+ "version": "2.1.11",
4
4
  "description": "React Components",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -3,6 +3,8 @@ import React, {
3
3
  useCallback,
4
4
  useEffect,
5
5
  useImperativeHandle,
6
+ useLayoutEffect,
7
+ useMemo,
6
8
  useRef,
7
9
  useState,
8
10
  } from 'react';
@@ -73,6 +75,7 @@ const ExpandableAutoComplete = forwardRef<
73
75
  ) => {
74
76
  const dropdownRef = useRef<HTMLDivElement>(null);
75
77
  const expandableContainerRef = useRef<HTMLDivElement>(null);
78
+ const isExpandableSingleLineRef = useRef(true);
76
79
  const [isExpandableSingleLine, setIsExpandableSingleLine] = useState(true);
77
80
  // State Hooks Section
78
81
  const [isInitialRender, setIsInitialRender] = useState(true);
@@ -126,8 +129,15 @@ const ExpandableAutoComplete = forwardRef<
126
129
  inputRect.top + window.scrollY - dropdownHeight + 73;
127
130
  }
128
131
 
129
- setDropdownStyle({
130
- ...dropdownPosition,
132
+ setDropdownStyle((prev) => {
133
+ if (
134
+ prev.top === dropdownPosition.top &&
135
+ prev.left === dropdownPosition.left &&
136
+ prev.width === dropdownPosition.width
137
+ ) {
138
+ return prev;
139
+ }
140
+ return dropdownPosition;
131
141
  });
132
142
  }
133
143
  };
@@ -322,8 +332,23 @@ const ExpandableAutoComplete = forwardRef<
322
332
  }, []);
323
333
 
324
334
  // Filtering suggestions based on type and search value
325
- const selected: any = isMultiple ? selectedItems : inputValue;
326
- const filteredData: ValueProps[] = filterSuggestions(
335
+ const selected: any = useMemo(
336
+ () => (isMultiple ? selectedItems : inputValue),
337
+ [isMultiple, selectedItems, inputValue]
338
+ );
339
+ const filteredData: ValueProps[] = useMemo(() => {
340
+ return filterSuggestions(
341
+ suggestions,
342
+ searchValue,
343
+ type,
344
+ desc,
345
+ selected,
346
+ async,
347
+ isTreeDropdown,
348
+ true,
349
+ matchFromStart
350
+ );
351
+ }, [
327
352
  suggestions,
328
353
  searchValue,
329
354
  type,
@@ -331,18 +356,26 @@ const ExpandableAutoComplete = forwardRef<
331
356
  selected,
332
357
  async,
333
358
  isTreeDropdown,
334
- true,
335
- matchFromStart
336
- );
359
+ matchFromStart,
360
+ ]);
337
361
 
338
362
  useEffect(() => {
363
+ if (!dropOpen) {
364
+ return;
365
+ }
339
366
  window.addEventListener('resize', adjustDropdownPosition);
340
367
  adjustDropdownPosition();
341
368
 
342
369
  return () => {
343
370
  window.removeEventListener('resize', adjustDropdownPosition);
344
371
  };
345
- }, [dropOpen, selectedItems, filteredData]);
372
+ }, [
373
+ dropOpen,
374
+ selectedItems?.length,
375
+ filteredData?.length,
376
+ enableSelectAll,
377
+ isMultiple,
378
+ ]);
346
379
 
347
380
  useEffect(() => {
348
381
  // Handle keyboard navigation
@@ -517,30 +550,62 @@ const ExpandableAutoComplete = forwardRef<
517
550
  setSelectAll(allSelected);
518
551
  }, [filteredData, selectedItems, descId]);
519
552
 
520
- const isExpandableSingleLineRef = useRef(true);
521
- useEffect(() => {
553
+ // Track previous values to prevent unnecessary checks
554
+ const prevSelectedItemsLengthRef = useRef(selectedItems?.length ?? 0);
555
+ const prevSearchValueRef = useRef(searchValue);
556
+ const prevExpandableRef = useRef(expandable);
557
+
558
+ // Check single line status only when content actually changes
559
+ useLayoutEffect(() => {
522
560
  const el = expandableContainerRef.current;
523
- if (!el || !expandable) return;
524
-
525
- const checkSingleLine = () => {
526
- const lineHeight = parseInt(
527
- getComputedStyle(el).lineHeight || '20',
528
- 10
529
- ) || 20;
530
- const padding = 5 * 2;
531
- const singleLineMax = lineHeight + padding + 4;
532
- const isSingle = el.scrollHeight <= singleLineMax;
561
+ const currentLength = selectedItems?.length ?? 0;
562
+
563
+ // Only check if dependencies actually changed
564
+ const lengthChanged = prevSelectedItemsLengthRef.current !== currentLength;
565
+ const searchChanged = prevSearchValueRef.current !== searchValue;
566
+ const expandableChanged = prevExpandableRef.current !== expandable;
567
+
568
+ if (!lengthChanged && !searchChanged && !expandableChanged) {
569
+ return; // Skip if nothing changed
570
+ }
571
+
572
+ // Update refs
573
+ prevSelectedItemsLengthRef.current = currentLength;
574
+ prevSearchValueRef.current = searchValue;
575
+ prevExpandableRef.current = expandable;
576
+
577
+ if (!el || !expandable) {
578
+ if (isExpandableSingleLineRef.current !== true) {
579
+ isExpandableSingleLineRef.current = true;
580
+ setIsExpandableSingleLine(true);
581
+ }
582
+ return;
583
+ }
584
+
585
+ // Use requestAnimationFrame to check after DOM updates
586
+ requestAnimationFrame(() => {
587
+ if (!el) return;
588
+
589
+ const computedStyle = getComputedStyle(el);
590
+ const paddingTop = parseFloat(computedStyle.paddingTop) || 5;
591
+ const paddingBottom = parseFloat(computedStyle.paddingBottom) || 5;
592
+ const borderTop = parseFloat(computedStyle.borderTopWidth) || 0;
593
+ const borderBottom = parseFloat(computedStyle.borderBottomWidth) || 0;
594
+ const lineHeight = parseFloat(computedStyle.lineHeight) || 20;
595
+
596
+ const singleLineThreshold = paddingTop + paddingBottom + borderTop + borderBottom + lineHeight + 20;
597
+ const isSingle = el.scrollHeight <= singleLineThreshold;
598
+
599
+ console.log(singleLineThreshold, 'singleLineThreshold')
600
+ console.log(el.scrollHeight, 'el.scrollHeight')
601
+ console.log(isSingle, 'isSingle')
602
+ // Only update if value changed
533
603
  if (isExpandableSingleLineRef.current !== isSingle) {
534
604
  isExpandableSingleLineRef.current = isSingle;
535
605
  setIsExpandableSingleLine(isSingle);
536
606
  }
537
- };
538
-
539
- checkSingleLine();
540
- const observer = new ResizeObserver(checkSingleLine);
541
- observer.observe(el);
542
- return () => observer.disconnect();
543
- }, [expandable, selectedItems, searchValue]);
607
+ });
608
+ }, [expandable, selectedItems?.length, searchValue]);
544
609
 
545
610
  return (
546
611
  <div