react-core-ts 1.0.10 → 1.0.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.
package/docs/App.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
 
3
- import {AutoComplete, ExpandableAutoComplete} from '../src/index';
3
+ import { AutoComplete, ExpandableAutoComplete } from '../src/index';
4
4
 
5
5
  import '../src/styles/global.css';
6
6
 
@@ -51,6 +51,35 @@ export default function App() {
51
51
  maxWidth: 700,
52
52
  }}
53
53
  >
54
+ <div className="autocomplete-section">
55
+ <h2>Expandable Auto Suggestion</h2>
56
+ <p>
57
+ As you type, suggestions will appear based on your input, aiding
58
+ in quicker and potentially more accurate data entry. This mode
59
+ supports both listed and non-listed input, providing flexibility
60
+ in user input while still offering assistance.
61
+ </p>
62
+ </div>
63
+ <div style={{ width: 300 }}>
64
+ <ExpandableAutoComplete
65
+ label="Auto Suggestion"
66
+ name="sample"
67
+ type="auto_suggestion"
68
+ // async
69
+ desc="name"
70
+ isMultiple
71
+ expandable={true}
72
+ descId="id"
73
+ paginationEnabled={false}
74
+ initialLoad={true}
75
+ itemCount={5}
76
+ // nextBlock={nexBlock}
77
+ placeholder="Auto Suggestion Suggestion Suggestion Suggestion"
78
+ selectedItems={[{ name: 'test', id: '1' }]}
79
+ getData={getData}
80
+ onChange={(e) => console.log(e, 'onchange')}
81
+ />
82
+ </div>
54
83
  <div className="autocomplete-section">
55
84
  <h2>Custom Select</h2>
56
85
  <p>
@@ -231,7 +260,7 @@ export default function App() {
231
260
  initialLoad={true}
232
261
  itemCount={5}
233
262
  // nextBlock={nexBlock}
234
- placeholder="Auto Suggestion"
263
+ placeholder="Auto Suggestion Suggestion Suggestion Suggestion"
235
264
  selectedItems={[{ name: 'test', id: '1' }]}
236
265
  getData={getData}
237
266
  onChange={(e) => console.log(e, 'onchange')}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-core-ts",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "React Components",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,11 +1,5 @@
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';
2
+ import ReactDOM from 'react-dom';
9
3
 
10
4
  import { AutoSuggestionInputProps } from './commontypes';
11
5
  import { useSuggestions } from './utilities/autosuggestions';
@@ -68,23 +62,41 @@ const ExpandableAutoComplete = forwardRef<
68
62
  const [dropOpen, setDropOpen] = useState<boolean>(false);
69
63
  const [selectedItems, setSelectedItems] = useState<ValueProps[]>([]);
70
64
  // API call for suggestions through a custom hook
71
- const [dropdownPosition, setDropdownPosition] = useState('bottom');
72
65
  const inputRef = useRef(null);
73
66
  const dropRef = useRef(null);
74
67
  useImperativeHandle(ref, () => inputRef.current);
68
+ const [dropdownStyle, setDropdownStyle] = useState({
69
+ top: 0,
70
+ left: 0,
71
+ width: 200,
72
+ });
75
73
 
76
74
  const adjustDropdownPosition = () => {
77
- if (inputRef.current && dropRef.current) {
78
- const inputBoxRect = inputRef.current.getBoundingClientRect();
79
- const viewportHeight = window.innerHeight;
80
-
81
- const spaceAbove = inputBoxRect.top;
82
- const spaceBelow = viewportHeight - inputBoxRect.bottom;
83
- if (spaceAbove > spaceBelow) {
84
- setDropdownPosition('top');
75
+ if (dropdownRef.current) {
76
+ const inputRect = dropdownRef.current.getBoundingClientRect();
77
+ const dropdownPosition = {
78
+ left: inputRect.left + window.scrollX,
79
+ width: inputRect.width,
80
+ top: 0,
81
+ };
82
+ // Check if there's enough space below the input for the dropdown
83
+ const spaceBelow = window.innerHeight - inputRect.bottom;
84
+ const dropdownHeight = 275; // Assume a fixed height or calculate based on content
85
+
86
+ if (spaceBelow >= dropdownHeight) {
87
+ dropdownPosition.top = inputRect.bottom + window.scrollY;
85
88
  } else {
86
- setDropdownPosition('bottom');
89
+ dropdownPosition.top =
90
+ inputRect.top +
91
+ window.scrollY -
92
+ dropdownHeight +
93
+ inputRect.height +
94
+ 20;
87
95
  }
96
+
97
+ setDropdownStyle({
98
+ ...dropdownPosition,
99
+ });
88
100
  }
89
101
  };
90
102
 
@@ -97,6 +109,15 @@ const ExpandableAutoComplete = forwardRef<
97
109
  };
98
110
  }, [dropOpen]);
99
111
 
112
+ useEffect(() => {
113
+ window.addEventListener('resize', adjustDropdownPosition);
114
+ adjustDropdownPosition();
115
+
116
+ return () => {
117
+ window.removeEventListener('resize', adjustDropdownPosition);
118
+ };
119
+ }, []);
120
+
100
121
  const { suggestions, isLoading, handlePickSuggestions } = useSuggestions(
101
122
  getData,
102
123
  data,
@@ -275,7 +296,6 @@ const ExpandableAutoComplete = forwardRef<
275
296
  .map((item) => item[desc])
276
297
  .join(', ')
277
298
  : '';
278
-
279
299
  return (
280
300
  <div className={fullWidth ? 'fullWidth' : 'autoWidth'} ref={dropdownRef}>
281
301
  {label && (
@@ -412,31 +432,34 @@ const ExpandableAutoComplete = forwardRef<
412
432
  {/* Displaying Loading Spinner */}
413
433
 
414
434
  {/* Suggestions Dropdown */}
415
- {dropOpen && (
416
- <ul
417
- ref={dropRef}
418
- className={`qbs-autocomplete-suggestions ${dropdownPosition}`}
419
- >
420
- {type == 'auto_suggestion' && !expandable && (
421
- <div
422
- style={{ position: 'relative' }}
423
- className="react-core-ts-search-container"
424
- >
425
- <span className="dropdown-search-icon">
426
- <Search />
427
- </span>
428
- <input
429
- className="dropdown-search-input"
430
- onChange={handleSuggestionChange}
431
- value={searchValue}
432
- placeholder="Search"
433
- />
434
- </div>
435
- )}
436
435
 
437
- <div className="qbs-autocomplete-suggestions-sub">
438
- {/* Displaying Suggestions or Not Found Message */}
439
- {/* {isLoading && (
436
+ {dropOpen &&
437
+ ReactDOM.createPortal(
438
+ <ul
439
+ ref={dropRef}
440
+ style={{ ...dropdownStyle, minHeight: 192 }}
441
+ className={`qbs-autocomplete-suggestions`}
442
+ >
443
+ {type == 'auto_suggestion' && !expandable && (
444
+ <div
445
+ style={{ position: 'relative' }}
446
+ className="react-core-ts-search-container"
447
+ >
448
+ <span className="dropdown-search-icon">
449
+ <Search />
450
+ </span>
451
+ <input
452
+ className="dropdown-search-input"
453
+ onChange={handleSuggestionChange}
454
+ value={searchValue}
455
+ placeholder="Search"
456
+ />
457
+ </div>
458
+ )}
459
+
460
+ <div className="qbs-autocomplete-suggestions-sub">
461
+ {/* Displaying Suggestions or Not Found Message */}
462
+ {/* {isLoading && (
440
463
  <div style={{ display: 'flex', justifyContent: 'center' }}>
441
464
  <span>
442
465
  <Spinner />
@@ -445,87 +468,90 @@ const ExpandableAutoComplete = forwardRef<
445
468
 
446
469
  {/* )} */}
447
470
 
448
- {filteredData?.length > 0 ? (
449
- filteredData.map((suggestion: ValueProps, idx: number) => (
450
- <div
451
- key={idx.toString()}
452
- className={`qbs-autocomplete-listitem-container ${
453
- (isMultiple || singleSelect) &&
454
- 'qbs-autocomplete-checkbox-container'
455
- } ${
456
- isSelected(suggestion, selected) ? 'is-selected' : ''
457
- }`}
458
- >
459
- {(isMultiple || singleSelect) && (
460
- <div className="qbs-autocomplete-checkbox">
461
- <input
462
- onChange={(e) => handleMultiSelect(e, suggestion)}
463
- type="checkbox"
464
- checked={isSelected(suggestion, selected)}
465
- id={`qbs-checkbox-${idx.toString()}`}
466
- />
467
- <label htmlFor={`qbs-checkbox-${idx.toString()}`}>
468
- <svg
469
- width="8"
470
- height="6"
471
- viewBox="0 0 8 6"
472
- fill="none"
473
- xmlns="http://www.w3.org/2000/svg"
474
- >
475
- <path
476
- d="M0 3.21739L2.89883 6L8 1.06994L6.89494 0L2.89883 3.86768L1.09728 2.14745L0 3.21739Z"
477
- fill="white"
478
- />
479
- </svg>
480
- </label>
481
- </div>
482
- )}
483
- <li
484
- key={idx}
485
- className={`qbs-autocomplete-suggestions-item ${
471
+ {filteredData?.length > 0 ? (
472
+ filteredData.map((suggestion: ValueProps, idx: number) => (
473
+ <div
474
+ key={idx.toString()}
475
+ className={`qbs-autocomplete-listitem-container ${
476
+ (isMultiple || singleSelect) &&
477
+ 'qbs-autocomplete-checkbox-container'
478
+ } ${
486
479
  isSelected(suggestion, selected) ? 'is-selected' : ''
487
480
  }`}
488
- onClick={() => handleSuggestionClick(suggestion)}
489
- data-testid={suggestion[desc]}
490
481
  >
491
- {suggestion[desc]}
492
- </li>
493
- </div>
494
- ))
495
- ) : (
496
- <>
497
- {isLoading ? (
482
+ {(isMultiple || singleSelect) && (
483
+ <div className="qbs-autocomplete-checkbox">
484
+ <input
485
+ onChange={(e) => handleMultiSelect(e, suggestion)}
486
+ type="checkbox"
487
+ checked={isSelected(suggestion, selected)}
488
+ id={`qbs-checkbox-${idx.toString()}`}
489
+ />
490
+ <label htmlFor={`qbs-checkbox-${idx.toString()}`}>
491
+ <svg
492
+ width="8"
493
+ height="6"
494
+ viewBox="0 0 8 6"
495
+ fill="none"
496
+ xmlns="http://www.w3.org/2000/svg"
497
+ >
498
+ <path
499
+ d="M0 3.21739L2.89883 6L8 1.06994L6.89494 0L2.89883 3.86768L1.09728 2.14745L0 3.21739Z"
500
+ fill="white"
501
+ />
502
+ </svg>
503
+ </label>
504
+ </div>
505
+ )}
506
+ <li
507
+ key={idx}
508
+ className={`qbs-autocomplete-suggestions-item ${
509
+ isSelected(suggestion, selected)
510
+ ? 'is-selected'
511
+ : ''
512
+ }`}
513
+ onClick={() => handleSuggestionClick(suggestion)}
514
+ data-testid={suggestion[desc]}
515
+ >
516
+ {suggestion[desc]}
517
+ </li>
518
+ </div>
519
+ ))
520
+ ) : (
521
+ <>
522
+ {isLoading ? (
523
+ <div
524
+ style={{ display: 'flex', justifyContent: 'center' }}
525
+ >
526
+ <span>
527
+ <Spinner />
528
+ </span>
529
+ </div>
530
+ ) : (
531
+ <li
532
+ className="qbs-autocomplete-notfound"
533
+ onClick={handleBlur}
534
+ >
535
+ {notDataMessage ?? 'No Results Found'}
536
+ </li>
537
+ )}
538
+ </>
539
+ )}
540
+ {paginationEnabled &&
541
+ nextBlock !== 0 &&
542
+ nextBlock !== undefined &&
543
+ filteredData?.length > 0 && (
498
544
  <div
499
- style={{ display: 'flex', justifyContent: 'center' }}
545
+ className="loadMoreSection"
546
+ onClick={() => handleLoadMore()}
500
547
  >
501
- <span>
502
- <Spinner />
503
- </span>
548
+ <p style={{ margin: 2 }}>Load More</p>
504
549
  </div>
505
- ) : (
506
- <li
507
- className="qbs-autocomplete-notfound"
508
- onClick={handleBlur}
509
- >
510
- {notDataMessage ?? 'No Results Found'}
511
- </li>
512
550
  )}
513
- </>
514
- )}
515
- {paginationEnabled &&
516
- nextBlock !== 0 &&
517
- nextBlock !== undefined &&
518
- filteredData?.length > 0 && (
519
- <div
520
- className="loadMoreSection"
521
- onClick={() => handleLoadMore()}
522
- >
523
- <p style={{ margin: 2 }}>Load More</p>
524
- </div>
525
- )}
526
- </div>
527
- </ul>
528
- )}
551
+ </div>
552
+ </ul>,
553
+ document.body
554
+ )}
529
555
  </div>
530
556
 
531
557
  {/* Displaying Validation Error */}
package/src/index.tsx CHANGED
@@ -3,7 +3,7 @@ import './styles/global.css';
3
3
  export { default as AutoComplete } from './AutoComplete';
4
4
  export { default as CustomAutoComplete } from './AutoComplete';
5
5
  export { default as ExpandableAutoComplete } from './ExpandableAutoComplete';
6
-
6
+ export { default as ExpandableToolTip } from './utilities/expandableTootltip';
7
7
  export { default as ToolTip } from './utilities/tooltip';
8
8
  export { deepEqual } from './utilities/deepEqual';
9
9
  export type { AutoSuggestionInputProps } from './commontypes';
@@ -205,7 +205,7 @@ body * {
205
205
  overflow: hidden;
206
206
  }
207
207
  .qbs-expandable-container .qbs-textfield-expandable::after {
208
- content: attr(data-value) " ";
208
+ content: attr(data-value) ' ';
209
209
  visibility: hidden;
210
210
  white-space: pre;
211
211
  grid-area: 1 / 2;
@@ -218,7 +218,7 @@ body * {
218
218
  }
219
219
  .qbs-expandable-container .qbs-textfield-expandable input {
220
220
  opacity: 1;
221
- width: 100%;
221
+ width: auto;
222
222
  grid-area: 1 / 2;
223
223
  min-width: 10px;
224
224
  border: 0px;
@@ -522,7 +522,8 @@ span.dropdown-search-icon {
522
522
  cursor: pointer;
523
523
  }
524
524
 
525
- .qbs-table-tooltip .tooltiptext, .tooltiptext {
525
+ .qbs-table-tooltip .tooltiptext,
526
+ .tooltiptext {
526
527
  visibility: hidden;
527
528
  background-color: #000;
528
529
  color: #fff;
@@ -556,21 +557,24 @@ span.dropdown-search-icon {
556
557
  opacity: 1;
557
558
  }
558
559
 
559
- .qbs-table-tooltip .tooltiptext::after, .tooltiptext::after {
560
- content: "";
560
+ .qbs-table-tooltip .tooltiptext::after,
561
+ .tooltiptext::after {
562
+ content: '';
561
563
  position: absolute;
562
564
  border-width: 5px;
563
565
  border-style: solid;
564
566
  }
565
567
 
566
- .qbs-table-tooltip.up .tooltiptext::after, .up.tooltiptext::after {
568
+ .qbs-table-tooltip.up .tooltiptext::after,
569
+ .up.tooltiptext::after {
567
570
  top: 100%;
568
571
  left: 50%;
569
572
  margin-left: -5px;
570
573
  border-color: #000 transparent transparent transparent;
571
574
  }
572
575
 
573
- .qbs-table-tooltip.down .tooltiptext::after, .down.tooltiptext::after {
576
+ .qbs-table-tooltip.down .tooltiptext::after,
577
+ .down.tooltiptext::after {
574
578
  bottom: 100%;
575
579
  left: 50%;
576
580
  margin-left: -5px;
@@ -1,8 +1,8 @@
1
- import React, { useState, useRef, useLayoutEffect, useEffect } from "react";
2
- import ReactDOM from "react-dom";
1
+ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import ReactDOM from 'react-dom';
3
3
 
4
4
  const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
5
- const [dropdownPosition, setDropdownPosition] = useState("bottom-position");
5
+ const [dropdownPosition, setDropdownPosition] = useState('bottom-position');
6
6
  const dropRef = useRef(null);
7
7
  const menuButtonRef = useRef<HTMLDivElement>(null);
8
8
  const [visible, setVisible] = useState(false);
@@ -20,16 +20,16 @@ const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
20
20
  const spaceBelow = viewportHeight - inputBoxRect.bottom;
21
21
  if (spaceAbove > spaceBelow) {
22
22
  if (spaceAbove > 90 && spaceBelow < 120) {
23
- return "top-position";
23
+ return 'top-position';
24
24
  } else {
25
- return "bottom-position";
25
+ return 'bottom-position';
26
26
  }
27
27
  } else {
28
28
  const diff: number = spaceBelow - spaceAbove;
29
29
  if (spaceAbove > 90 && spaceBelow > 90 && diff < 90) {
30
- return "top-position";
30
+ return 'top-position';
31
31
  } else {
32
- return "bottom-position";
32
+ return 'bottom-position';
33
33
  }
34
34
  }
35
35
  }
@@ -44,7 +44,7 @@ const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
44
44
  let left = rect.left + window.scrollX;
45
45
  const height = rect.height;
46
46
  const width = dropRef?.current?.offsetWidth;
47
- if (dropPosition === "bottom-position") {
47
+ if (dropPosition === 'bottom-position') {
48
48
  top = top + height / 2 - 5;
49
49
  } else {
50
50
  top = top - height * 2 + 15;
@@ -77,7 +77,7 @@ const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
77
77
  : prevStyle.left + boxWidth / 2 - tooltipWidth / 2,
78
78
  width: tooltipWidth,
79
79
  top:
80
- dropdownPosition === "bottom-position"
80
+ dropdownPosition === 'bottom-position'
81
81
  ? prevStyle.top
82
82
  : prevStyle.top - tooltipHeight,
83
83
  }));
@@ -88,10 +88,10 @@ const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
88
88
  updateTooltipPosition();
89
89
  }
90
90
 
91
- window.addEventListener("resize", updateTooltipPosition);
91
+ window.addEventListener('resize', updateTooltipPosition);
92
92
 
93
93
  return () => {
94
- window.removeEventListener("resize", updateTooltipPosition);
94
+ window.removeEventListener('resize', updateTooltipPosition);
95
95
  };
96
96
  }, [visible, dropdownPosition]);
97
97
 
@@ -102,47 +102,45 @@ const ExpandableToolTip: React.FC<any> = ({ title, children, enabled }) => {
102
102
  }
103
103
  };
104
104
 
105
- document.addEventListener("mousedown", handleClickOutside);
105
+ document.addEventListener('mousedown', handleClickOutside);
106
106
  return () => {
107
- document.removeEventListener("mousedown", handleClickOutside);
107
+ document.removeEventListener('mousedown', handleClickOutside);
108
108
  };
109
109
  }, []);
110
110
 
111
111
  return (
112
- <>
113
- <div
114
- onMouseEnter={handleMouseEnter}
115
- onMouseLeave={handleMouseLeave}
116
- ref={menuButtonRef}
117
- style={{ display: "flex" }}
118
- >
119
- {children}
112
+ <div
113
+ onMouseEnter={handleMouseEnter}
114
+ onMouseLeave={handleMouseLeave}
115
+ ref={menuButtonRef}
116
+ style={{ display: 'flex' }}
117
+ >
118
+ {children}
120
119
 
121
- {visible &&
122
- enabled &&
123
- tooltipStyle &&
124
- ReactDOM.createPortal(
125
- <span
126
- ref={(node) => (dropRef.current = node)}
127
- className={`tooltiptext ${
128
- dropdownPosition == "bottom-position" ? "down" : "up"
129
- }`}
130
- style={{
131
- top: tooltipStyle.top,
132
- left: tooltipStyle.left,
133
- opacity: 1,
134
- width: tooltipStyle.width,
135
- minWidth: "60px",
136
- maxWidth: "200px",
137
- visibility: "visible",
138
- }}
139
- >
140
- {title}
141
- </span>,
142
- document.body
143
- )}
144
- </div>
145
- </>
120
+ {visible &&
121
+ enabled &&
122
+ tooltipStyle &&
123
+ ReactDOM.createPortal(
124
+ <span
125
+ ref={(node) => (dropRef.current = node)}
126
+ className={`tooltiptext ${
127
+ dropdownPosition == 'bottom-position' ? 'down' : 'up'
128
+ }`}
129
+ style={{
130
+ top: tooltipStyle.top,
131
+ left: tooltipStyle.left,
132
+ opacity: 1,
133
+ width: tooltipStyle.width,
134
+ minWidth: '60px',
135
+ maxWidth: '200px',
136
+ visibility: 'visible',
137
+ }}
138
+ >
139
+ {title}
140
+ </span>,
141
+ document.body
142
+ )}
143
+ </div>
146
144
  );
147
145
  };
148
146