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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forstok-ui-lib",
3
- "version": "8.5.4",
3
+ "version": "8.5.6",
4
4
  "description": "Forstok UI Components Library",
5
5
  "path": "dist",
6
6
  "main": "dist/index.js",
@@ -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
- const offsetPos = containerEl.getBoundingClientRect();
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
- if (wrapperRef) {
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
- if (offsetPos) {
141
- portalContainerRef.style.left = offsetPos.left + ((parseInt($internalWidth || '0') + offsetPos.width) / 2) + 'px';
142
- let currentTop = offsetPos.top + offsetPos.height;
143
- const dropdownWrapperEl = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
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: () => {