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.
- package/Accordion/index.js +71 -660
- package/Select/index.js +40 -11
- package/lib/cjs/Accordion/index.js +71 -660
- package/lib/cjs/Select/index.js +40 -11
- package/lib/esm/Accordion/Accordion.tsx +44 -79
- package/lib/esm/Accordion/AccordionItem.tsx +37 -19
- package/lib/esm/Accordion/index.tsx +1 -1
- package/lib/esm/Select/index.tsx +52 -14
- package/package.json +1 -1
package/lib/cjs/Select/index.js
CHANGED
|
@@ -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
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
106
|
+
//Initialize expanded items based on defaultActiveIndex or defaultActiveAll
|
|
147
107
|
useEffect(() => {
|
|
148
|
-
|
|
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
|
-
//
|
|
153
|
-
|
|
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 =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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';
|
package/lib/esm/Select/index.tsx
CHANGED
|
@@ -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
|
|
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 (
|
|
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.
|
|
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",
|