funda-ui 4.7.533 → 4.7.555
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/LiveSearch/index.js +16 -8
- package/Select/index.js +14 -5
- package/lib/cjs/Accordion/index.js +71 -660
- package/lib/cjs/LiveSearch/index.js +16 -8
- package/lib/cjs/Select/index.js +14 -5
- 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/LiveSearch/index.tsx +15 -11
- package/lib/esm/Select/index.tsx +11 -5
- package/package.json +1 -1
|
@@ -3026,7 +3026,6 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
|
|
|
3026
3026
|
if (isBlurringRef.current && !MANUAL_REQ) return;
|
|
3027
3027
|
|
|
3028
3028
|
//
|
|
3029
|
-
var contentHeightOffset = 80;
|
|
3030
3029
|
var contentMaxHeight = 0;
|
|
3031
3030
|
|
|
3032
3031
|
// update modal position
|
|
@@ -3067,6 +3066,11 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
|
|
|
3067
3066
|
var _contentActualHeight = listContentRef.current.querySelector('.livesearch__options-contentlist-inner').clientHeight;
|
|
3068
3067
|
if (targetPos === 'top') {
|
|
3069
3068
|
contentMaxHeight = _triggerBox.top;
|
|
3069
|
+
|
|
3070
|
+
// Calculate the final height with minimum height protection
|
|
3071
|
+
var contentHeightOffset = 0;
|
|
3072
|
+
var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
3073
|
+
|
|
3070
3074
|
if (_contentBox.height > _contentActualHeight) {
|
|
3071
3075
|
if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
|
|
3072
3076
|
} else {
|
|
@@ -3074,11 +3078,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
|
|
|
3074
3078
|
|
|
3075
3079
|
// recalculate the height
|
|
3076
3080
|
_contentBox = listContentRef.current.getBoundingClientRect();
|
|
3077
|
-
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height =
|
|
3081
|
+
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
|
|
3078
3082
|
}
|
|
3079
3083
|
}
|
|
3080
3084
|
if (targetPos === 'bottom') {
|
|
3081
3085
|
contentMaxHeight = window.innerHeight - _triggerBox.bottom;
|
|
3086
|
+
|
|
3087
|
+
// Calculate the final height with minimum height protection
|
|
3088
|
+
var _contentHeightOffset = 10;
|
|
3089
|
+
var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
3090
|
+
|
|
3082
3091
|
if (_contentBox.height > _contentActualHeight) {
|
|
3083
3092
|
if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
|
|
3084
3093
|
} else {
|
|
@@ -3086,7 +3095,7 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
|
|
|
3086
3095
|
|
|
3087
3096
|
// recalculate the height
|
|
3088
3097
|
_contentBox = listContentRef.current.getBoundingClientRect();
|
|
3089
|
-
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height =
|
|
3098
|
+
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = _finalHeight + 'px';
|
|
3090
3099
|
}
|
|
3091
3100
|
}
|
|
3092
3101
|
|
|
@@ -3095,17 +3104,16 @@ var LiveSearch = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(
|
|
|
3095
3104
|
// Adjust position
|
|
3096
3105
|
if (targetPos === 'top') {
|
|
3097
3106
|
_modalRef.style.left = x + 'px';
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
_modalRef.style.
|
|
3107
|
+
_modalRef.style.bottom = 'auto';
|
|
3108
|
+
// Position the popup above the trigger without overlapping
|
|
3109
|
+
var topPosition = y - POS_OFFSET - listContentRef.current.clientHeight - 2;
|
|
3110
|
+
_modalRef.style.top = topPosition + 'px';
|
|
3102
3111
|
_modalRef.classList.add('pos-top');
|
|
3103
3112
|
}
|
|
3104
3113
|
if (targetPos === 'bottom') {
|
|
3105
3114
|
_modalRef.style.left = x + 'px';
|
|
3106
3115
|
_modalRef.style.bottom = 'auto';
|
|
3107
3116
|
_modalRef.style.top = y + height + POS_OFFSET + 'px';
|
|
3108
|
-
_modalRef.style.setProperty('position', 'absolute', 'important');
|
|
3109
3117
|
_modalRef.classList.remove('pos-top');
|
|
3110
3118
|
}
|
|
3111
3119
|
|
package/lib/cjs/Select/index.js
CHANGED
|
@@ -4289,7 +4289,6 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
|
|
|
4289
4289
|
if (isBlurringRef.current) return;
|
|
4290
4290
|
|
|
4291
4291
|
//
|
|
4292
|
-
var contentHeightOffset = 80;
|
|
4293
4292
|
var contentMaxHeight = 0;
|
|
4294
4293
|
|
|
4295
4294
|
// update modal position
|
|
@@ -4370,9 +4369,14 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
|
|
|
4370
4369
|
|
|
4371
4370
|
// height restrictions
|
|
4372
4371
|
contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
|
|
4372
|
+
|
|
4373
|
+
// Calculate the final height with minimum height protection
|
|
4374
|
+
var contentHeightOffset = 0;
|
|
4375
|
+
var finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
4376
|
+
|
|
4373
4377
|
if (_contentBox.height > contentMaxHeight) {
|
|
4374
|
-
listContentRef.current.style.height =
|
|
4375
|
-
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height =
|
|
4378
|
+
listContentRef.current.style.height = finalHeight + 'px';
|
|
4379
|
+
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
|
|
4376
4380
|
|
|
4377
4381
|
// has scrollbar
|
|
4378
4382
|
listContentRef.current.dataset.hasScrollbar = 'true';
|
|
@@ -4393,9 +4397,14 @@ var Select = /*#__PURE__*/(0,external_root_React_commonjs2_react_commonjs_react_
|
|
|
4393
4397
|
|
|
4394
4398
|
// height restrictions
|
|
4395
4399
|
contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
|
|
4400
|
+
|
|
4401
|
+
// Calculate the final height with minimum height protection
|
|
4402
|
+
var _contentHeightOffset = 10;
|
|
4403
|
+
var _finalHeight = Math.max(contentMaxHeight - _contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
4404
|
+
|
|
4396
4405
|
if (_contentBox.height > contentMaxHeight) {
|
|
4397
|
-
listContentRef.current.style.height =
|
|
4398
|
-
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height =
|
|
4406
|
+
listContentRef.current.style.height = _finalHeight + 'px';
|
|
4407
|
+
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = _finalHeight;
|
|
4399
4408
|
|
|
4400
4409
|
// has scrollbar
|
|
4401
4410
|
listContentRef.current.dataset.hasScrollbar = 'true';
|
|
@@ -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';
|
|
@@ -276,7 +276,6 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
//
|
|
279
|
-
const contentHeightOffset = 80;
|
|
280
279
|
let contentMaxHeight = 0;
|
|
281
280
|
|
|
282
281
|
// update modal position
|
|
@@ -321,6 +320,10 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
321
320
|
if (targetPos === 'top') {
|
|
322
321
|
contentMaxHeight = _triggerBox.top;
|
|
323
322
|
|
|
323
|
+
// Calculate the final height with minimum height protection
|
|
324
|
+
const contentHeightOffset = 0;
|
|
325
|
+
const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
326
|
+
|
|
324
327
|
if (_contentBox.height > _contentActualHeight) {
|
|
325
328
|
if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
|
|
326
329
|
} else {
|
|
@@ -328,7 +331,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
328
331
|
|
|
329
332
|
// recalculate the height
|
|
330
333
|
_contentBox = listContentRef.current.getBoundingClientRect();
|
|
331
|
-
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height =
|
|
334
|
+
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
|
|
332
335
|
|
|
333
336
|
}
|
|
334
337
|
}
|
|
@@ -336,6 +339,10 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
336
339
|
if (targetPos === 'bottom') {
|
|
337
340
|
contentMaxHeight = window.innerHeight - _triggerBox.bottom;
|
|
338
341
|
|
|
342
|
+
// Calculate the final height with minimum height protection
|
|
343
|
+
const contentHeightOffset = 10;
|
|
344
|
+
const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
345
|
+
|
|
339
346
|
if (_contentBox.height > _contentActualHeight) {
|
|
340
347
|
if (_contentActualHeight > 0) listContentRef.current.style.height = _contentActualHeight + 'px';
|
|
341
348
|
} else {
|
|
@@ -343,7 +350,7 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
343
350
|
|
|
344
351
|
// recalculate the height
|
|
345
352
|
_contentBox = listContentRef.current.getBoundingClientRect();
|
|
346
|
-
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height =
|
|
353
|
+
if (_contentBox.height > contentMaxHeight) listContentRef.current.style.height = finalHeight + 'px';
|
|
347
354
|
}
|
|
348
355
|
|
|
349
356
|
}
|
|
@@ -355,25 +362,22 @@ const LiveSearch = forwardRef((props: LiveSearchProps, externalRef: any) => {
|
|
|
355
362
|
// Adjust position
|
|
356
363
|
if (targetPos === 'top') {
|
|
357
364
|
_modalRef.style.left = x + 'px';
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
_modalRef.style.
|
|
365
|
+
_modalRef.style.bottom = 'auto';
|
|
366
|
+
// Position the popup above the trigger without overlapping
|
|
367
|
+
const topPosition = y - POS_OFFSET - (listContentRef.current.clientHeight) - 2;
|
|
368
|
+
_modalRef.style.top = topPosition + 'px';
|
|
362
369
|
_modalRef.classList.add('pos-top');
|
|
370
|
+
|
|
363
371
|
}
|
|
364
372
|
|
|
365
373
|
if (targetPos === 'bottom') {
|
|
366
374
|
_modalRef.style.left = x + 'px';
|
|
367
375
|
_modalRef.style.bottom = 'auto';
|
|
368
376
|
_modalRef.style.top = y + height + POS_OFFSET + 'px';
|
|
369
|
-
_modalRef.style.setProperty('position', 'absolute', 'important');
|
|
370
377
|
_modalRef.classList.remove('pos-top');
|
|
371
378
|
}
|
|
372
379
|
|
|
373
380
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
381
|
// STEP 5:
|
|
378
382
|
//-----------
|
|
379
383
|
// Determine whether it exceeds the far right or left side of the screen
|
package/lib/esm/Select/index.tsx
CHANGED
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
|
|
50
51
|
export interface MultiSelectValue {
|
|
51
52
|
items: { label: string; value: string }[];
|
|
52
53
|
labels: string[];
|
|
@@ -815,7 +816,6 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
|
|
|
815
816
|
if (isBlurringRef.current) return;
|
|
816
817
|
|
|
817
818
|
//
|
|
818
|
-
const contentHeightOffset = 80;
|
|
819
819
|
let contentMaxHeight = 0;
|
|
820
820
|
|
|
821
821
|
// update modal position
|
|
@@ -904,10 +904,13 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
|
|
|
904
904
|
// height restrictions
|
|
905
905
|
contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
|
|
906
906
|
|
|
907
|
+
// Calculate the final height with minimum height protection
|
|
908
|
+
const contentHeightOffset = 0;
|
|
909
|
+
const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
907
910
|
|
|
908
911
|
if (_contentBox.height > contentMaxHeight) {
|
|
909
|
-
listContentRef.current.style.height =
|
|
910
|
-
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height =
|
|
912
|
+
listContentRef.current.style.height = finalHeight + 'px';
|
|
913
|
+
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
|
|
911
914
|
|
|
912
915
|
// has scrollbar
|
|
913
916
|
listContentRef.current.dataset.hasScrollbar = 'true';
|
|
@@ -933,10 +936,13 @@ const Select = forwardRef((props: SelectProps, externalRef: any) => {
|
|
|
933
936
|
// height restrictions
|
|
934
937
|
contentMaxHeight = listContainerHeightLimit(contentMaxHeight);
|
|
935
938
|
|
|
939
|
+
// Calculate the final height with minimum height protection
|
|
940
|
+
const contentHeightOffset = 10;
|
|
941
|
+
const finalHeight = Math.max(contentMaxHeight - contentHeightOffset, 150); // Ensure minimum height of 150px
|
|
936
942
|
|
|
937
943
|
if (_contentBox.height > contentMaxHeight) {
|
|
938
|
-
listContentRef.current.style.height =
|
|
939
|
-
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height =
|
|
944
|
+
listContentRef.current.style.height = finalHeight + 'px';
|
|
945
|
+
if (typeof listContentRef.current.dataset.height === 'undefined') listContentRef.current.dataset.height = finalHeight;
|
|
940
946
|
|
|
941
947
|
// has scrollbar
|
|
942
948
|
listContentRef.current.dataset.hasScrollbar = 'true';
|
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.555",
|
|
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",
|