forstok-ui-lib 8.5.4 → 8.5.6
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/dist/index.js +94 -94
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -77
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/dropdown/index.tsx +127 -45
- package/src/components/select/asyncPaginate.tsx +3 -16
package/package.json
CHANGED
|
@@ -6,20 +6,121 @@ import { DropDownContainer, DropDownTitle, DropDownSubTitle, DropDownWrapper, Dr
|
|
|
6
6
|
import type { TMouseEvent } from '../../typeds/base.typed';
|
|
7
7
|
import type { TDropdown } from './typed';
|
|
8
8
|
|
|
9
|
+
const DEFAULT_TOP_OFFSET = 40;
|
|
10
|
+
const DEFAULT_BOTTOM_OFFSET = 35;
|
|
11
|
+
|
|
9
12
|
const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externalMinWidth, $internalWidth, $area, $openPosition, $placement, $top, onClick, $alias, type, portalId, $bottom, $isPopup, ...props }: TDropdown) => {
|
|
10
13
|
const buttonRef = useRef<HTMLElement>(null);
|
|
11
14
|
|
|
15
|
+
const getOffsetValue = (value: string | undefined, fallbackValue: number) => {
|
|
16
|
+
const parsedValue = Number.parseInt(value || '', 10);
|
|
17
|
+
return Number.isNaN(parsedValue) ? fallbackValue : parsedValue;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getViewportHeight = () => window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
|
21
|
+
const getViewportWidth = () => window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|
22
|
+
|
|
23
|
+
const getDropdownWrapperElement = (parentEl: ParentNode | null) => parentEl?.querySelector('._refDropdownWrapper') as HTMLElement | null;
|
|
24
|
+
|
|
25
|
+
const getDropdownPlacement = (containerEl: HTMLElement, wrapperEl: HTMLElement) => {
|
|
26
|
+
if ($placement === 'top') {
|
|
27
|
+
return 'top';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const containerRect = containerEl.getBoundingClientRect();
|
|
31
|
+
const wrapperRect = wrapperEl.getBoundingClientRect();
|
|
32
|
+
const wrapperHeight = wrapperRect.height || wrapperEl.offsetHeight;
|
|
33
|
+
const topOffset = getOffsetValue($top, DEFAULT_TOP_OFFSET);
|
|
34
|
+
const bottomOffset = getOffsetValue($bottom, DEFAULT_BOTTOM_OFFSET);
|
|
35
|
+
const spaceBelow = getViewportHeight() - containerRect.bottom;
|
|
36
|
+
const spaceAbove = containerRect.top;
|
|
37
|
+
const requiredSpaceBelow = wrapperHeight + Math.max(topOffset - containerRect.height, 0);
|
|
38
|
+
const requiredSpaceAbove = wrapperHeight + Math.max(bottomOffset - containerRect.height, 0);
|
|
39
|
+
|
|
40
|
+
if (spaceBelow >= requiredSpaceBelow) {
|
|
41
|
+
return 'bottom';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (spaceAbove >= requiredSpaceAbove) {
|
|
45
|
+
return 'top';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return spaceAbove > spaceBelow ? 'top' : 'bottom';
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const applyDropdownPlacement = (wrapperEl: HTMLElement, placement: 'top' | 'bottom') => {
|
|
52
|
+
if (placement === 'top') {
|
|
53
|
+
wrapperEl.style.top = 'auto';
|
|
54
|
+
wrapperEl.style.bottom = `${getOffsetValue($bottom, DEFAULT_BOTTOM_OFFSET)}px`;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
wrapperEl.style.top = `${getOffsetValue($top, DEFAULT_TOP_OFFSET)}px`;
|
|
59
|
+
wrapperEl.style.bottom = 'auto';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const resetDropdownInlineStyle = (parentEl: ParentNode | null) => {
|
|
63
|
+
const wrapperEl = getDropdownWrapperElement(parentEl);
|
|
64
|
+
if (wrapperEl) {
|
|
65
|
+
wrapperEl.style.top = '';
|
|
66
|
+
wrapperEl.style.bottom = '';
|
|
67
|
+
wrapperEl.style.left = '';
|
|
68
|
+
wrapperEl.style.right = '';
|
|
69
|
+
wrapperEl.style.transform = '';
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const setPortalDropdownPosition = (containerEl: HTMLElement) => {
|
|
74
|
+
if (!portalId) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement | null;
|
|
79
|
+
const wrapperRef = getDropdownWrapperElement(portalContainerRef);
|
|
80
|
+
|
|
81
|
+
if (!portalContainerRef || !wrapperRef) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const offsetPos = containerEl.getBoundingClientRect();
|
|
86
|
+
const placement = getDropdownPlacement(containerEl, wrapperRef);
|
|
87
|
+
const wrapperWidth = wrapperRef.getBoundingClientRect().width || wrapperRef.offsetWidth;
|
|
88
|
+
const viewportWidth = getViewportWidth();
|
|
89
|
+
|
|
90
|
+
let leftValue = offsetPos.left + offsetPos.width - wrapperWidth;
|
|
91
|
+
|
|
92
|
+
if ($openPosition === 'left') {
|
|
93
|
+
leftValue = offsetPos.left;
|
|
94
|
+
} else if ($openPosition === 'center') {
|
|
95
|
+
leftValue = offsetPos.left + (offsetPos.width / 2) - (wrapperWidth / 2);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
leftValue = Math.max(0, Math.min(leftValue, Math.max(viewportWidth - wrapperWidth, 0)));
|
|
99
|
+
|
|
100
|
+
wrapperRef.style.left = '0';
|
|
101
|
+
wrapperRef.style.right = 'auto';
|
|
102
|
+
wrapperRef.style.transform = 'none';
|
|
103
|
+
applyDropdownPlacement(wrapperRef, placement);
|
|
104
|
+
|
|
105
|
+
portalContainerRef.style.left = `${leftValue}px`;
|
|
106
|
+
portalContainerRef.style.top = `${placement === 'top' ? offsetPos.bottom : offsetPos.top}px`;
|
|
107
|
+
portalContainerRef.style.zIndex = $isPopup ? '101' : '8';
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const setInlineDropdownPlacement = (containerEl: HTMLElement) => {
|
|
111
|
+
const wrapperRef = getDropdownWrapperElement(containerEl);
|
|
112
|
+
if (!wrapperRef) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const placement = getDropdownPlacement(containerEl, wrapperRef);
|
|
117
|
+
applyDropdownPlacement(wrapperRef, placement);
|
|
118
|
+
};
|
|
119
|
+
|
|
12
120
|
const evScrollDropdown = () => {
|
|
13
121
|
const containerEl = document.getElementsByClassName('_refContainer is-shown')[0] as HTMLElement;
|
|
14
|
-
if (containerEl) {
|
|
15
|
-
|
|
16
|
-
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
|
|
17
|
-
if (portalContainerRef) {
|
|
18
|
-
const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
|
|
19
|
-
const value = offsetPos.left + offsetPos.width - wrapperRef.getBoundingClientRect().width;
|
|
20
|
-
portalContainerRef.style.left = (value > 0 ? value : offsetPos.left) + 'px';
|
|
21
|
-
portalContainerRef.style.top = offsetPos.top + parseInt($top || '0') - 32 + 'px';
|
|
22
|
-
}
|
|
122
|
+
if (containerEl && portalId) {
|
|
123
|
+
setPortalDropdownPosition(containerEl);
|
|
23
124
|
}
|
|
24
125
|
}
|
|
25
126
|
|
|
@@ -32,6 +133,7 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
32
133
|
const overlayEl = containerRef[i].querySelector(`._refDropdownOverlay`) as HTMLDivElement;
|
|
33
134
|
overlayEl.style.display = 'none';
|
|
34
135
|
containerRef[i].classList.remove('is-shown');
|
|
136
|
+
resetDropdownInlineStyle(containerRef[i]);
|
|
35
137
|
}
|
|
36
138
|
}
|
|
37
139
|
const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
|
|
@@ -41,6 +143,7 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
41
143
|
const portalContainerRef = document.getElementsByClassName('_refDropdownPortal is-shown') as HTMLCollectionOf<HTMLElement>;
|
|
42
144
|
if (portalContainerRef.length) {
|
|
43
145
|
for (let i = 0; i < portalContainerRef.length; i++) {
|
|
146
|
+
resetDropdownInlineStyle(portalContainerRef[i]);
|
|
44
147
|
portalContainerRef[i].style.left = '0';
|
|
45
148
|
portalContainerRef[i].style.top = '0';
|
|
46
149
|
portalContainerRef[i].classList.remove('is-shown');
|
|
@@ -62,7 +165,6 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
62
165
|
if (containerEl) {
|
|
63
166
|
const overlayEl = containerEl.querySelector(`._refDropdownOverlay`) as HTMLDivElement;
|
|
64
167
|
const isCurOpen = containerEl.classList.contains('is-shown');
|
|
65
|
-
const offsetPos = containerEl.getBoundingClientRect();
|
|
66
168
|
|
|
67
169
|
if (!isCurOpen) {
|
|
68
170
|
evResetDropdown();
|
|
@@ -73,25 +175,15 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
73
175
|
if (portalId) {
|
|
74
176
|
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
|
|
75
177
|
const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
|
|
76
|
-
const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
|
|
77
178
|
if (portalContainerRef) {
|
|
78
|
-
if (offsetPos) {
|
|
79
|
-
if (wrapperRef) {
|
|
80
|
-
setTimeout(() => {
|
|
81
|
-
wrapperRef.style.right = 'auto';
|
|
82
|
-
const value = offsetPos.left + offsetPos.width - wrapperRef.getBoundingClientRect().width;
|
|
83
|
-
portalContainerRef.style.left = (value > 0 ? value : offsetPos.left) + 'px';
|
|
84
|
-
portalContainerRef.style.top = offsetPos.top + parseInt($top || '0') - 32 + 'px';
|
|
85
|
-
portalContainerRef.style.zIndex = $isPopup ? '101' : '8';
|
|
86
|
-
refScrollContainerEl && refScrollContainerEl.addEventListener('scroll', evScrollDropdown, true);
|
|
87
|
-
}, 10);
|
|
88
|
-
} else {
|
|
89
|
-
portalContainerRef.style.left = offsetPos.left + ((parseInt($internalWidth || '0') + offsetPos.width) / 2) + 'px';
|
|
90
|
-
portalContainerRef.style.top = (offsetPos.top + offsetPos.height) + 'px';
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
179
|
portalContainerRef.classList.add('is-shown');
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
setPortalDropdownPosition(containerEl);
|
|
182
|
+
refScrollContainerEl && refScrollContainerEl.addEventListener('scroll', evScrollDropdown, true);
|
|
183
|
+
}, 10);
|
|
94
184
|
}
|
|
185
|
+
} else {
|
|
186
|
+
setInlineDropdownPlacement(containerEl);
|
|
95
187
|
}
|
|
96
188
|
}, 10);
|
|
97
189
|
onClick && onClick(e);
|
|
@@ -103,17 +195,16 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
103
195
|
if (portalId) {
|
|
104
196
|
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
|
|
105
197
|
const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
|
|
106
|
-
const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
|
|
107
198
|
if (portalContainerRef) {
|
|
199
|
+
resetDropdownInlineStyle(portalContainerRef);
|
|
108
200
|
portalContainerRef.classList.remove('is-shown');
|
|
109
201
|
portalContainerRef.style.left = '0px';
|
|
110
202
|
portalContainerRef.style.top = '0px';
|
|
111
|
-
|
|
112
|
-
refScrollContainerEl && refScrollContainerEl.removeEventListener('scroll', evScrollDropdown, true);
|
|
113
|
-
}
|
|
203
|
+
refScrollContainerEl && refScrollContainerEl.removeEventListener('scroll', evScrollDropdown, true);
|
|
114
204
|
}
|
|
115
205
|
}
|
|
116
206
|
}, 10);
|
|
207
|
+
resetDropdownInlineStyle(containerEl);
|
|
117
208
|
}
|
|
118
209
|
}
|
|
119
210
|
}
|
|
@@ -134,22 +225,12 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
134
225
|
}
|
|
135
226
|
const containerEl = buttonEl.closest('._refContainer') as HTMLElement;
|
|
136
227
|
if (containerEl) {
|
|
137
|
-
const offsetPos = containerEl.getBoundingClientRect();
|
|
138
228
|
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
|
|
139
229
|
if (portalContainerRef) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (dropdownWrapperEl) {
|
|
145
|
-
dropdownWrapperEl.style.display = 'block';
|
|
146
|
-
if ((currentTop + dropdownWrapperEl.clientHeight) >= document.body.clientHeight) {
|
|
147
|
-
currentTop = offsetPos.top - dropdownWrapperEl.clientHeight - 10;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
portalContainerRef.style.top = currentTop + 'px';
|
|
151
|
-
}
|
|
152
|
-
portalContainerRef.classList.add('is-shown');
|
|
230
|
+
portalContainerRef.classList.add('is-shown');
|
|
231
|
+
setTimeout(() => {
|
|
232
|
+
setPortalDropdownPosition(containerEl);
|
|
233
|
+
}, 10);
|
|
153
234
|
}
|
|
154
235
|
}
|
|
155
236
|
}
|
|
@@ -202,6 +283,7 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
202
283
|
setTimeout(() => {
|
|
203
284
|
const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
|
|
204
285
|
if (portalContainerRef && !portalContainerRef.classList.contains('unhiddenable')) {
|
|
286
|
+
resetDropdownInlineStyle(portalContainerRef);
|
|
205
287
|
portalContainerRef.classList.remove('is-shown');
|
|
206
288
|
portalContainerRef.style.left = '0';
|
|
207
289
|
portalContainerRef.style.top = '0';
|
|
@@ -260,4 +342,4 @@ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externa
|
|
|
260
342
|
);
|
|
261
343
|
}
|
|
262
344
|
|
|
263
|
-
export default DropDownComponent;
|
|
345
|
+
export default DropDownComponent;
|
|
@@ -57,8 +57,8 @@ const SelectAsyncPaginateComponent = ({ loadOptions, ...props }: TSelect) => {
|
|
|
57
57
|
customOption,
|
|
58
58
|
MenuList,
|
|
59
59
|
defaultValue,
|
|
60
|
-
reset,
|
|
61
|
-
setReset,
|
|
60
|
+
// reset,
|
|
61
|
+
// setReset,
|
|
62
62
|
evChange,
|
|
63
63
|
isForceUpdate,
|
|
64
64
|
setForceUpdate,
|
|
@@ -97,10 +97,6 @@ const SelectAsyncPaginateComponent = ({ loadOptions, ...props }: TSelect) => {
|
|
|
97
97
|
) => {
|
|
98
98
|
const newValue = value as OnChangeValue<TOption, false>;
|
|
99
99
|
|
|
100
|
-
if (mode !== "multi-select" && actionMeta?.action === "select-option") {
|
|
101
|
-
setInputValue("");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
100
|
if (actionMeta) {
|
|
105
101
|
const { action, option } = actionMeta;
|
|
106
102
|
|
|
@@ -299,6 +295,7 @@ const SelectAsyncPaginateComponent = ({ loadOptions, ...props }: TSelect) => {
|
|
|
299
295
|
}, [setMenuIsOpen]);
|
|
300
296
|
|
|
301
297
|
const onMenuClose = useCallback(() => {
|
|
298
|
+
setInputValue("");
|
|
302
299
|
setMenuIsOpen && setMenuIsOpen(false);
|
|
303
300
|
}, [setMenuIsOpen]);
|
|
304
301
|
|
|
@@ -345,16 +342,6 @@ const SelectAsyncPaginateComponent = ({ loadOptions, ...props }: TSelect) => {
|
|
|
345
342
|
return value;
|
|
346
343
|
}
|
|
347
344
|
|
|
348
|
-
if (action.action === "set-value") {
|
|
349
|
-
setInputValue("");
|
|
350
|
-
return "";
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (action.action === "menu-close") {
|
|
354
|
-
setInputValue("");
|
|
355
|
-
return "";
|
|
356
|
-
}
|
|
357
|
-
|
|
358
345
|
return value;
|
|
359
346
|
},
|
|
360
347
|
onMenuClose: () => {
|