funda-ui 4.7.545 → 4.7.560

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.
@@ -3995,6 +3995,9 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
3995
3995
  setTimeout(function () {
3996
3996
  popwinPosInit();
3997
3997
  popwinFilterItems(val);
3998
+
3999
+ // Fix popup position after fetch loading completes
4000
+ fixPopupPositionAfterFetch();
3998
4001
  }, 0);
3999
4002
  setFetchLoading(false);
4000
4003
  });
@@ -4594,13 +4597,14 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4594
4597
  if (listContentRef.current === null) return;
4595
4598
  var _btnSelectAll = listContentRef.current.querySelector('.custom-select-multi__control-option-item--select-all');
4596
4599
  var _noDataDiv = listContentRef.current.querySelector('.custom-select-multi__control-option-item--nomatch');
4597
- var emptyFieldsCheck = [].slice.call(listContentRef.current.querySelectorAll('.custom-select-multi__control-option-item')).every(function (node) {
4600
+ var _items = [].slice.call(listContentRef.current.querySelectorAll('.custom-select-multi__control-option-item'));
4601
+ var itemsDoNotExist = _items.every(function (node) {
4598
4602
  if (!node.classList.contains('hide')) {
4599
4603
  return false;
4600
4604
  }
4601
4605
  return true;
4602
4606
  });
4603
- if (emptyFieldsCheck) {
4607
+ if (itemsDoNotExist) {
4604
4608
  _noDataDiv.classList.remove('hide');
4605
4609
  if (_btnSelectAll !== null) _btnSelectAll.classList.add('hide');
4606
4610
  } else {
@@ -4618,6 +4622,25 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
4618
4622
  //
4619
4623
  if (selectInputRef.current) selectInputRef.current.value = '';
4620
4624
  }
4625
+ function fixPopupPositionAfterFetch() {
4626
+ if (listContentRef.current === null || !isOpen) return;
4627
+
4628
+ // Get the current position data
4629
+ var currentPos = listContentRef.current.dataset.pos;
4630
+ if (currentPos === 'top') {
4631
+ // Recalculate position for upward popup to fix offset issues
4632
+ var _modalRef = document.querySelector("#custom-select__options-wrapper-".concat(idRes));
4633
+ if (_modalRef && rootRef.current && selectInputRef.current) {
4634
+ var _getAbsolutePositionO3 = (0,getElementProperty.getAbsolutePositionOfStage)(rootRef.current),
4635
+ x = _getAbsolutePositionO3.x;
4636
+ var _getAbsolutePositionO4 = (0,getElementProperty.getAbsolutePositionOfStage)(selectInputRef.current),
4637
+ y = _getAbsolutePositionO4.y;
4638
+ _modalRef.style.left = x + 'px';
4639
+ var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
4640
+ _modalRef.style.top = topPosition + 'px';
4641
+ }
4642
+ }
4643
+ }
4621
4644
  function cancel() {
4622
4645
  // hide list
4623
4646
  setIsOpen(false);
@@ -5468,6 +5491,15 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
5468
5491
  }
5469
5492
  }
5470
5493
 
5494
+ // Select all detection functions in the input box (for "Single selection")
5495
+ function checkUserInputboxIsAllSelected(e) {
5496
+ var input = e.target;
5497
+ if (input && typeof input.selectionStart === 'number' && typeof input.selectionEnd === 'number') {
5498
+ setUserInputboxIsAllSelected(input.selectionStart === 0 && input.selectionEnd === input.value.length && input.value.length > 0);
5499
+ } else {
5500
+ setUserInputboxIsAllSelected(false);
5501
+ }
5502
+ }
5471
5503
  (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function () {
5472
5504
  // Call a function when the component has been rendered completely
5473
5505
  //--------------
@@ -5619,15 +5651,6 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
5619
5651
  };
5620
5652
  }, [orginalData]); // Avoid the issue that `setOptionsData(orginalData)` sets the original value to empty on the first entry
5621
5653
 
5622
- // Select all detection functions in the input box (for "Single selection")
5623
- function checkUserInputboxIsAllSelected(e) {
5624
- var input = e.target;
5625
- if (input && typeof input.selectionStart === 'number' && typeof input.selectionEnd === 'number') {
5626
- setUserInputboxIsAllSelected(input.selectionStart === 0 && input.selectionEnd === input.value.length && input.value.length > 0);
5627
- } else {
5628
- setUserInputboxIsAllSelected(false);
5629
- }
5630
- }
5631
5654
  return /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement((external_root_React_commonjs2_react_commonjs_react_amd_react_default()).Fragment, null, label ? /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement((external_root_React_commonjs2_react_commonjs_react_amd_react_default()).Fragment, null, /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement("div", {
5632
5655
  className: "custom-select__label"
5633
5656
  }, typeof label === 'string' ? /*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().createElement("label", {
@@ -5828,6 +5851,9 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
5828
5851
  setTimeout(function () {
5829
5852
  popwinPosInit();
5830
5853
  popwinFilterItems(controlTempValue);
5854
+
5855
+ // Fix popup position after fetch loading completes
5856
+ fixPopupPositionAfterFetch();
5831
5857
  }, 0);
5832
5858
  });
5833
5859
  }
@@ -5953,6 +5979,9 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
5953
5979
  setTimeout(function () {
5954
5980
  popwinPosInit();
5955
5981
  popwinFilterItems(controlTempValue);
5982
+
5983
+ // Fix popup position after fetch loading completes
5984
+ fixPopupPositionAfterFetch();
5956
5985
  }, 0);
5957
5986
  });
5958
5987
  }
@@ -2,13 +2,12 @@ import React, { useState, useRef, useEffect } from 'react';
2
2
 
3
3
  import Item from './AccordionItem';
4
4
 
5
- import animateStyles from 'funda-utils/dist/cjs/anim';
6
5
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
7
6
 
8
-
9
7
  // Adapt the easing parameters of TweenMax
10
8
  export enum EasingList {
11
9
  linear = 'linear',
10
+ ease = 'ease',
12
11
  easeIn = 'ease-in',
13
12
  easeOut = 'ease-out',
14
13
  easeInOut = 'ease-in-out'
@@ -18,6 +17,7 @@ export enum EasingList {
18
17
  export type AccordionOptionChangeFnType = (element: HTMLDivElement, index: number) => void;
19
18
 
20
19
 
20
+
21
21
  export type AccordionProps = {
22
22
  wrapperClassName?: string;
23
23
  /** The index of the item to be displayed by default. Set to -1 to display none, or an array of indices to display multiple items */
@@ -46,7 +46,7 @@ const Accordion = (props: AccordionProps) => {
46
46
  defaultActiveIndex,
47
47
  defaultActiveAll = false,
48
48
  duration,
49
- easing,
49
+ easing = 'ease',
50
50
  alternateCollapse = true,
51
51
  arrowOnly = false,
52
52
  onChange,
@@ -56,17 +56,16 @@ const Accordion = (props: AccordionProps) => {
56
56
  const animSpeed = duration || 200;
57
57
  const easeType: string = typeof alternateCollapse === 'undefined' ? EasingList['linear'] : EasingList[easing as never];
58
58
  const rootRef = useRef<any>(null);
59
- const animPlaceholderRef = useRef<HTMLDivElement>(null);
60
- const [animOK, setAnimOK] = useState<boolean>(false);
61
- const [heightObserver, setHeightObserver] = useState<number>(-1);
59
+ const [heightObserver, setHeightObserver] = useState<number[]>([]);
62
60
  const [expandedItems, setExpandedItems] = useState<Set<number>>(new Set()); // Keep track of all expanded items
63
61
  const animationInProgress = useRef<boolean>(false);
62
+ const initExpanded = useRef<boolean>(false);
63
+
64
64
 
65
65
 
66
66
  function handleClickItem(e: React.MouseEvent) {
67
67
  if (animationInProgress.current) return;
68
68
  if ((e.target as any).closest('.custom-accordion-header') === null) return;
69
- if (animOK) return;
70
69
 
71
70
  animationInProgress.current = true;
72
71
 
@@ -74,34 +73,10 @@ const Accordion = (props: AccordionProps) => {
74
73
  const curIndex: number = parseInt(reactDomEl.dataset.index);
75
74
  const reactDomWrapperEl: HTMLElement = rootRef.current;
76
75
  const $li = reactDomWrapperEl.querySelectorAll('.custom-accordion-item');
77
- const $allContent = reactDomWrapperEl.querySelectorAll('.custom-accordion-content__wrapper');
78
- const $curContent = reactDomEl.querySelector('.custom-accordion-content__wrapper');
79
76
 
80
77
  if (reactDomEl.getAttribute('aria-expanded') === 'false' || reactDomEl.getAttribute('aria-expanded') === null) {
81
- setAnimOK(true);
82
- setTimeout(() => {
83
- setAnimOK(false);
84
- }, animSpeed);
85
-
86
78
  if (alternateCollapse) {
87
- // Hide other all sibling content
88
- Array.prototype.forEach.call($allContent, (node) => {
89
- if (node.clientHeight > 0) {
90
- animateStyles(node, {
91
- startHeight: node.scrollHeight,
92
- endHeight: 0,
93
- speed: animSpeed
94
- } as never, easeType, () => {
95
- animationInProgress.current = false;
96
- });
97
- }
98
- });
99
-
100
- // Update all items to collapsed state
101
- Array.prototype.forEach.call($li, (node) => {
102
- node.setAttribute('aria-expanded', 'false');
103
- });
104
-
79
+
105
80
  // Update expanded items state
106
81
  setExpandedItems(new Set([curIndex]));
107
82
  } else {
@@ -109,82 +84,71 @@ const Accordion = (props: AccordionProps) => {
109
84
  setExpandedItems(prev => new Set([...(prev as never), curIndex]));
110
85
  }
111
86
 
112
- reactDomEl.setAttribute('aria-expanded', 'true');
113
-
114
-
115
- animateStyles($curContent, {
116
- startHeight: 0,
117
- endHeight: $curContent.scrollHeight,
118
- speed: animSpeed
119
- } as never, easeType, () => {
120
- setHeightObserver(curIndex);
121
- animationInProgress.current = false;
122
- });
123
87
  } else {
124
- reactDomEl.setAttribute('aria-expanded', 'false');
125
-
88
+
126
89
  // Remove current item from expanded items
127
90
  setExpandedItems(prev => {
128
91
  const newSet = new Set(prev);
129
92
  newSet.delete(curIndex);
130
93
  return newSet;
131
94
  });
132
-
133
- animateStyles($curContent, {
134
- startHeight: $curContent.scrollHeight,
135
- endHeight: 0,
136
- speed: animSpeed
137
- } as never, easeType, () => {
138
- animationInProgress.current = false;
139
- });
140
95
  }
141
96
 
97
+ // Reset animation flag after transition duration
98
+ setTimeout(() => {
99
+ animationInProgress.current = false;
100
+ }, animSpeed);
101
+
142
102
  onChange?.(reactDomEl, curIndex);
143
103
  }
144
104
 
145
105
 
146
- // Initialize expanded items based on defaultActiveIndex or defaultActiveAll
106
+ //Initialize expanded items based on defaultActiveIndex or defaultActiveAll
147
107
  useEffect(() => {
148
- if (defaultActiveAll && children && rootRef.current && animPlaceholderRef.current) {
108
+
109
+ // Skip the default height initialization to prevent re-initialization.
110
+ // This method is useful when you want to manually control when the accordion should
111
+ // skip the automatic height initialization process, especially useful when `children` change frequently.
112
+ if (initExpanded.current === true) return;
113
+
114
+ if (defaultActiveAll && children && rootRef.current) {
149
115
  const allIndices = Array.from({ length: (children as any[]).length }, (_, i) => i);
150
116
  setExpandedItems(new Set(allIndices));
117
+ // Set heightObserver for all items to enable height monitoring
118
+ setHeightObserver(allIndices);
151
119
 
152
- // Actually expand all items without animation
153
- const $allItems = rootRef.current.querySelectorAll('.custom-accordion-item');
154
- Array.prototype.forEach.call($allItems, (node, index) => {
155
- const $curContent = node.querySelector('.custom-accordion-content__wrapper');
156
- if ($curContent) {
157
- // !!! Don't use the .custom-accordion-contentwrapper height directly, it may be more than a dozen pixels
158
- $curContent.style.height = `${node.querySelector('.custom-accordion-content__wrapper > .custom-accordion-content').scrollHeight}px`;
159
- }
160
- });
161
-
162
-
163
- animateStyles(animPlaceholderRef.current as HTMLDivElement, {
164
- startHeight: 0,
165
- endHeight: 10,
166
- speed: animSpeed
167
- } as never, easeType, () => {
168
- setTimeout(() => {
169
-
170
- }, animSpeed);
171
- });
172
-
173
-
120
+ //
121
+ initExpanded.current = true;
174
122
  } else if (defaultActiveIndex !== undefined) {
175
123
  const initialExpanded = new Set<number>();
124
+ const observerIndices: number[] = [];
125
+
176
126
  if (Array.isArray(defaultActiveIndex)) {
177
- defaultActiveIndex.forEach(index => initialExpanded.add(index));
127
+ defaultActiveIndex.forEach(index => {
128
+ initialExpanded.add(index);
129
+ observerIndices.push(index);
130
+ });
178
131
  } else if (typeof defaultActiveIndex === 'number') {
179
132
  initialExpanded.add(defaultActiveIndex);
133
+ observerIndices.push(defaultActiveIndex);
180
134
  }
135
+
181
136
  setExpandedItems(initialExpanded);
137
+ // Set heightObserver for default active items to enable height monitoring
138
+ if (observerIndices.length > 0) {
139
+ setHeightObserver(observerIndices);
140
+ }
141
+
142
+ //
143
+ initExpanded.current = true;
144
+
182
145
  }
146
+
183
147
  }, [defaultActiveIndex, defaultActiveAll, children]);
184
148
 
149
+
185
150
  return (
186
151
  <>
187
- <div className="custom-accordion-anim-placeholder" style={{display: 'none'}} ref={animPlaceholderRef}></div>
188
152
  <div className={combinedCls(
189
153
  'custom-accordion-item',
190
154
  clsWrite(wrapperClassName, 'accordion')
@@ -204,6 +168,7 @@ const Accordion = (props: AccordionProps) => {
204
168
  index={i}
205
169
  defaultActiveAll={defaultActiveAll}
206
170
  animSpeed={animSpeed}
171
+ easing={easeType}
207
172
  arrowOnly={arrowOnly}
208
173
  heightObserver={heightObserver}
209
174
  activeItem={_defaultActive}
@@ -4,11 +4,11 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
4
4
 
5
5
 
6
6
  export type AccordionItemProps = {
7
- heightObserver?: number;
7
+ heightObserver?: number[];
8
8
  index?: number;
9
9
  arrowOnly?: boolean;
10
10
  animSpeed?: number;
11
- easeType?: string;
11
+ easing?: string;
12
12
  /** Class of items */
13
13
  itemClassName?: string;
14
14
  itemContentWrapperClassName?: string;
@@ -41,7 +41,7 @@ const AccordionItem = (props: AccordionItemProps) => {
41
41
  heightObserver,
42
42
  index,
43
43
  animSpeed,
44
- easeType,
44
+ easing,
45
45
  arrowOnly,
46
46
  itemClassName,
47
47
  itemContentWrapperClassName,
@@ -83,6 +83,19 @@ const AccordionItem = (props: AccordionItemProps) => {
83
83
  onToggleEv?.(e);
84
84
  };
85
85
 
86
+
87
+ // Generate CSS transition style
88
+ const getTransitionStyle = () => {
89
+ const transitionDuration = `${animSpeed}ms`;
90
+ const transitionTiming = easing;
91
+
92
+ return {
93
+ transition: `max-height ${transitionDuration} ${transitionTiming}`,
94
+ overflow: 'hidden'
95
+ };
96
+ };
97
+
98
+
86
99
  useEffect(() => {
87
100
  if (triggerRef.current && typeof onItemCollapse === 'function') {
88
101
  if (isFirstRender.current) {
@@ -91,7 +104,7 @@ const AccordionItem = (props: AccordionItemProps) => {
91
104
  }
92
105
  onItemCollapse(triggerRef.current, iconRef.current as HTMLElement, isExpanded);
93
106
  }
94
- }, [isExpanded, onItemCollapse]);
107
+ }, [isExpanded]);
95
108
 
96
109
  useEffect(() => {
97
110
  if (contentWrapperRef.current && !initialHeightSet.current) {
@@ -101,47 +114,55 @@ const AccordionItem = (props: AccordionItemProps) => {
101
114
  setInternalExpanded(shouldBeExpanded);
102
115
  }
103
116
 
104
- // Set initial height when activeItem is true
117
+ // Set initial maxHeight when activeItem is true
105
118
  if (shouldBeExpanded && contentRef.current) {
106
119
  const contentHeight = contentRef.current.offsetHeight;
107
- contentWrapperRef.current.style.height = `${contentHeight}px`;
120
+ contentWrapperRef.current.style.maxHeight = `${contentHeight}px`;
108
121
  }
109
122
  }
110
123
  }, [activeItem, controlledExpanded]);
111
124
 
112
125
  useEffect(() => {
126
+ if (!heightObserver || !Array.isArray(heightObserver) || !heightObserver.includes(index as number)) return;
113
127
 
114
- if (parseFloat(heightObserver as never) !== index) return;
115
-
116
- // When the content height changes dynamically, change the height of the wrapper
128
+ // When the content height changes dynamically, change the maxHeight of the wrapper
117
129
  if (contentRef.current && contentWrapperRef.current) {
118
130
  const _contentPadding = window.getComputedStyle(contentRef.current as HTMLDivElement).getPropertyValue('padding-bottom');
119
131
 
120
132
  observer.current = new ResizeObserver(entries => {
121
-
122
133
  if (!Array.isArray(entries) || !entries.length) {
123
134
  return;
124
135
  }
125
136
 
126
137
  entries.forEach(entry => {
127
- if (contentWrapperRef.current !== null) (contentWrapperRef.current as HTMLDivElement).style.height = entry.contentRect.bottom + parseFloat(_contentPadding) + 'px';
138
+ if (contentWrapperRef.current !== null && isExpanded) {
139
+ (contentWrapperRef.current as HTMLDivElement).style.maxHeight = entry.contentRect.bottom + parseFloat(_contentPadding) + 'px';
140
+ }
128
141
  });
129
142
  });
130
143
  observer.current.observe(contentRef.current);
131
-
132
144
  }
133
145
 
134
146
  return () => {
135
147
  if (contentRef.current) observer.current?.unobserve(contentRef.current);
136
148
  };
137
149
 
150
+ }, [heightObserver, isExpanded]);
138
151
 
139
- }, [heightObserver]);
140
-
152
+ // Update maxHeight when expanded state changes
153
+ useEffect(() => {
154
+ if (contentWrapperRef.current && contentRef.current) {
155
+ if (isExpanded) {
156
+ const contentHeight = contentRef.current.scrollHeight;
157
+ contentWrapperRef.current.style.maxHeight = `${contentHeight}px`;
158
+ } else {
159
+ contentWrapperRef.current.style.maxHeight = '0px';
160
+ }
161
+ }
162
+ }, [isExpanded]);
141
163
 
142
164
  return (
143
165
  <>
144
-
145
166
  <div
146
167
  {...attributes}
147
168
  data-index={index}
@@ -211,10 +232,7 @@ const AccordionItem = (props: AccordionItemProps) => {
211
232
  clsWrite(itemContentWrapperClassName, 'accordion-collapse')
212
233
  )}
213
234
  role="tabpanel"
214
- style={{
215
- height: '0',
216
- overflow: 'hidden' // "overflow" affects the width, so add `w-100` to `custom-accordion-content__wrapper`
217
- }}>
235
+ style={getTransitionStyle()}>
218
236
  <div className={combinedCls(
219
237
  'custom-accordion-content',
220
238
  clsWrite(itemContentClassName, 'accordion-body')
@@ -1,2 +1,2 @@
1
1
  export { default as Accordion } from './Accordion';
2
- export { default as AccordionItem } from './AccordionItem';
2
+ export { default as AccordionItem } from './AccordionItem';
@@ -47,7 +47,6 @@ import {
47
47
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
48
48
 
49
49
 
50
-
51
50
  export interface MultiSelectValue {
52
51
  items: { label: string; value: string }[];
53
52
  labels: string[];
@@ -273,7 +272,7 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
273
272
 
274
273
 
275
274
  // loading
276
- const [fetchLoading, setFetchLoading] = useState(false);
275
+ const [fetchLoading, setFetchLoading] = useState<boolean>(false);
277
276
  const loadingOutput = <><div className="cus-select-loader">{loader || <svg height="12px" width="12px" viewBox="0 0 512 512"><g><path fill="inherit" d="M256,0c-23.357,0-42.297,18.932-42.297,42.288c0,23.358,18.94,42.288,42.297,42.288c23.357,0,42.279-18.93,42.279-42.288C298.279,18.932,279.357,0,256,0z" /><path fill="inherit" d="M256,427.424c-23.357,0-42.297,18.931-42.297,42.288C213.703,493.07,232.643,512,256,512c23.357,0,42.279-18.93,42.279-42.288C298.279,446.355,279.357,427.424,256,427.424z" /><path fill="inherit" d="M74.974,74.983c-16.52,16.511-16.52,43.286,0,59.806c16.52,16.52,43.287,16.52,59.806,0c16.52-16.511,16.52-43.286,0-59.806C118.261,58.463,91.494,58.463,74.974,74.983z" /><path fill="inherit" d="M377.203,377.211c-16.503,16.52-16.503,43.296,0,59.815c16.519,16.52,43.304,16.52,59.806,0c16.52-16.51,16.52-43.295,0-59.815C420.489,360.692,393.722,360.7,377.203,377.211z" /><path fill="inherit" d="M84.567,256c0.018-23.348-18.922-42.279-42.279-42.279c-23.357-0.009-42.297,18.932-42.279,42.288c-0.018,23.348,18.904,42.279,42.279,42.279C65.645,298.288,84.567,279.358,84.567,256z" /><path fill="inherit" d="M469.712,213.712c-23.357,0-42.279,18.941-42.297,42.288c0,23.358,18.94,42.288,42.297,42.297c23.357,0,42.297-18.94,42.279-42.297C512.009,232.652,493.069,213.712,469.712,213.712z" /><path fill="inherit" d="M74.991,377.22c-16.519,16.511-16.519,43.296,0,59.806c16.503,16.52,43.27,16.52,59.789,0c16.52-16.519,16.52-43.295,0-59.815C118.278,360.692,91.511,360.692,74.991,377.22z" /><path fill="inherit" d="M437.026,134.798c16.52-16.52,16.52-43.304,0-59.824c-16.519-16.511-43.304-16.52-59.823,0c-16.52,16.52-16.503,43.295,0,59.815C393.722,151.309,420.507,151.309,437.026,134.798z" /></g></svg>}</div></>;
278
277
 
279
278
 
@@ -500,21 +499,27 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
500
499
 
501
500
  // Make a request
502
501
  handleFetch(val).then((response: any) => {
503
-
502
+
504
503
  // pop win initalization
505
504
  setTimeout(() => {
506
505
  popwinPosInit();
507
506
  popwinFilterItems(val);
507
+
508
+ // Fix popup position after fetch loading completes
509
+ fixPopupPositionAfterFetch();
510
+
508
511
  }, 0);
509
512
 
510
513
  setFetchLoading(false);
511
514
  });
512
515
  } else {
516
+
513
517
 
514
518
  // pop win initalization
515
519
  setTimeout(() => {
516
520
  popwinPosInit();
517
521
  popwinFilterItems(val);
522
+
518
523
  }, 0);
519
524
 
520
525
  setFetchLoading(false);
@@ -1190,14 +1195,15 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1190
1195
 
1191
1196
  const _btnSelectAll = listContentRef.current.querySelector('.custom-select-multi__control-option-item--select-all');
1192
1197
  const _noDataDiv = listContentRef.current.querySelector('.custom-select-multi__control-option-item--nomatch');
1193
- const emptyFieldsCheck = [].slice.call(listContentRef.current.querySelectorAll('.custom-select-multi__control-option-item')).every((node: any) => {
1198
+ const _items = [].slice.call(listContentRef.current.querySelectorAll('.custom-select-multi__control-option-item'));
1199
+ const itemsDoNotExist = _items.every((node: any) => {
1194
1200
  if (!node.classList.contains('hide')) {
1195
1201
  return false;
1196
1202
  }
1197
1203
  return true;
1198
1204
  });
1199
1205
 
1200
- if (emptyFieldsCheck) {
1206
+ if (itemsDoNotExist) {
1201
1207
  _noDataDiv.classList.remove('hide');
1202
1208
  if (_btnSelectAll !== null) _btnSelectAll.classList.add('hide');
1203
1209
  } else {
@@ -1221,6 +1227,28 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
1221
1227
 
1222
1228
  }
1223
1229
 
1230
+
1231
+ function fixPopupPositionAfterFetch() {
1232
+ if (listContentRef.current === null || !isOpen) return;
1233
+
1234
+ // Get the current position data
1235
+ const currentPos = listContentRef.current.dataset.pos;
1236
+
1237
+ if (currentPos === 'top') {
1238
+ // Recalculate position for upward popup to fix offset issues
1239
+ const _modalRef: any = document.querySelector(`#custom-select__options-wrapper-${idRes}`);
1240
+ if (_modalRef && rootRef.current && selectInputRef.current) {
1241
+ const { x } = getAbsolutePositionOfStage(rootRef.current);
1242
+ const { y } = getAbsolutePositionOfStage(selectInputRef.current);
1243
+
1244
+ _modalRef.style.left = x + 'px';
1245
+ const topPosition = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2;
1246
+ _modalRef.style.top = topPosition + 'px';
1247
+ }
1248
+ }
1249
+ }
1250
+
1251
+
1224
1252
  function cancel() {
1225
1253
  // hide list
1226
1254
  setIsOpen(false);
@@ -2112,6 +2140,17 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
2112
2140
  }
2113
2141
 
2114
2142
 
2143
+ // Select all detection functions in the input box (for "Single selection")
2144
+ function checkUserInputboxIsAllSelected(e: any) {
2145
+ const input = e.target;
2146
+ if (input && typeof input.selectionStart === 'number' && typeof input.selectionEnd === 'number') {
2147
+ setUserInputboxIsAllSelected(input.selectionStart === 0 && input.selectionEnd === input.value.length && input.value.length > 0);
2148
+ } else {
2149
+ setUserInputboxIsAllSelected(false);
2150
+ }
2151
+ }
2152
+
2153
+
2115
2154
  useEffect(() => {
2116
2155
 
2117
2156
  // Call a function when the component has been rendered completely
@@ -2278,15 +2317,6 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
2278
2317
  }, [orginalData]); // Avoid the issue that `setOptionsData(orginalData)` sets the original value to empty on the first entry
2279
2318
 
2280
2319
 
2281
- // Select all detection functions in the input box (for "Single selection")
2282
- function checkUserInputboxIsAllSelected(e: any) {
2283
- const input = e.target;
2284
- if (input && typeof input.selectionStart === 'number' && typeof input.selectionEnd === 'number') {
2285
- setUserInputboxIsAllSelected(input.selectionStart === 0 && input.selectionEnd === input.value.length && input.value.length > 0);
2286
- } else {
2287
- setUserInputboxIsAllSelected(false);
2288
- }
2289
- }
2290
2320
 
2291
2321
 
2292
2322
  return (
@@ -2515,6 +2545,10 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
2515
2545
  setTimeout(() => {
2516
2546
  popwinPosInit();
2517
2547
  popwinFilterItems(controlTempValue);
2548
+
2549
+ // Fix popup position after fetch loading completes
2550
+ fixPopupPositionAfterFetch();
2551
+
2518
2552
  }, 0);
2519
2553
  });
2520
2554
 
@@ -2787,6 +2821,10 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
2787
2821
  setTimeout(() => {
2788
2822
  popwinPosInit();
2789
2823
  popwinFilterItems(controlTempValue);
2824
+
2825
+ // Fix popup position after fetch loading completes
2826
+ fixPopupPositionAfterFetch();
2827
+
2790
2828
  }, 0);
2791
2829
  });
2792
2830
  }}>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "UIUX Lab",
3
3
  "email": "uiuxlab@gmail.com",
4
4
  "name": "funda-ui",
5
- "version": "4.7.545",
5
+ "version": "4.7.560",
6
6
  "description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
7
7
  "repository": {
8
8
  "type": "git",