forstok-ui-lib 3.0.0 → 4.0.0

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": "3.0.0",
3
+ "version": "4.0.0",
4
4
  "description": "Forstok UI Components Library",
5
5
  "path": "dist",
6
6
  "main": "dist/index.js",
@@ -34,11 +34,14 @@
34
34
  "@rollup/plugin-typescript": "^12.1.2",
35
35
  "@rollup/plugin-url": "^8.0.2",
36
36
  "@svgr/rollup": "^8.1.0",
37
+ "@types/html-to-text": "^9.0.4",
37
38
  "@types/react": "^19.0.2",
38
39
  "@types/react-dom": "^19.0.2",
40
+ "html-to-text": "^9.0.5",
39
41
  "react": "^19.0.0",
40
42
  "react-dom": "^19.0.0",
41
43
  "react-router-dom": "^7.1.1",
44
+ "react-tooltip": "^4.5.1",
42
45
  "rollup-plugin-dts": "^6.1.1",
43
46
  "rollup-plugin-peer-deps-external": "^2.2.4",
44
47
  "rollup-plugin-postcss": "^4.0.2",
@@ -46,6 +49,7 @@
46
49
  "styled-components": "^6.1.15",
47
50
  "tslib": "^2.8.1",
48
51
  "typescript": "^5.7.2",
49
- "typescript-plugin-styled-components": "^3.0.0"
52
+ "typescript-plugin-styled-components": "^3.0.0",
53
+ "use-state-with-callback": "^3.0.2"
50
54
  }
51
55
  }
@@ -154,7 +154,7 @@ export const InfoGroup = styled.div`
154
154
  width: 100%;
155
155
  justify-content: left;
156
156
  margin-bottom: 14px;
157
- span {
157
+ span:first-child {
158
158
  position: relative;
159
159
  &:after {
160
160
  position: absolute;
@@ -0,0 +1,325 @@
1
+ import styled from 'styled-components';
2
+ import { dropBase } from '../../assets/stylesheets/bases.styles';
3
+ import type { TDropdown } from './dropdown.typed';
4
+
5
+ type TDropdownChild = Pick<TDropdown, '$internalWidth' | '$openPosition' | '$placement' | '$bottom' | '$top'>
6
+ type TDropdownParent = Pick<TDropdown, '$openPosition' | '$placement' | '$bottom' | '$top' | '$alias' | '$externalWidth' | '$externalMinWidth' | '$area'>
7
+
8
+ const getDropDownContainerModifiedStyled = ({ $top, $bottom, $placement, $alias, $openPosition, $externalWidth, $externalMinWidth, $area }: TDropdownParent) => {
9
+ const axTop = $top ? (parseInt($top) + 5)+'px' : '40px'
10
+ let style = `
11
+ @keyframes droptodown {
12
+ 90% {
13
+ top: ${axTop};
14
+ }
15
+ 100% {
16
+ top: ${$top || '35px'};
17
+ }
18
+ }
19
+ @keyframes droptoup {
20
+ 50% {
21
+ bottom: -100px;
22
+ }
23
+ 50% {
24
+ bottom: -50px;
25
+ }
26
+ 100% {
27
+ bottom: 0px;
28
+ }
29
+ }
30
+ @keyframes dropgodown {
31
+ 90% {
32
+ bottom: ${axTop};
33
+ }
34
+ 100% {
35
+ bottom: ${$bottom || '35px'};
36
+ }
37
+ }
38
+ @keyframse dropgoup {
39
+ 50% {
40
+ top: -100px;
41
+ }
42
+ 50% {
43
+ top: -50px;
44
+ }
45
+ 100% {
46
+ top: 0px;
47
+ }
48
+ }
49
+ & ${DropDownWrapper} {
50
+ display: none;
51
+ }
52
+ &.is-shown {
53
+ & ${DropDownControl} button {
54
+ box-shadow: var(--act-shd-bx);
55
+ }
56
+ @media only screen and (max-width: 767px) {
57
+ & ${DropDownWrapper} {
58
+ display: grid;
59
+ left: 0;
60
+ bottom:0;
61
+ ${$placement === 'top' ? 'animation: dropgoup .075s;' : 'animation: droptoup .075s;'}
62
+ overflow-x: hidden;
63
+ }
64
+ & ${DropDownBody} {
65
+ ._refFilterDropdown a {
66
+ text-align: left !important;
67
+ }
68
+ }
69
+ }
70
+ @media only screen and (min-width: 768px) {
71
+ & ${DropDownWrapper} {
72
+ display: grid;
73
+ ${$placement === 'top' ? `animation: dropgodown .075s linear; bottom: ${$bottom || '35px'};` : `animation: droptodown .075s linear; top: ${$top || '35px'};`}
74
+ left: ${($alias === "_dropdownFilterContainer" && $openPosition !== 'left') ? '100%': $openPosition === 'left' ? '0' : 'auto'};
75
+ }
76
+ }
77
+ @media only screen and (min-width: 1024px) {
78
+ & ${DropDownWrapper} {
79
+ left: ${($alias === "_dropdownFilterContainer" && $openPosition !== 'left') ? '30%': $openPosition === 'left' ? '0' : 'auto'};
80
+ }
81
+ }
82
+ @media only screen and (min-width: 1280px) {
83
+ & ${DropDownWrapper} {
84
+ left: ${($alias === "_dropdownFilterContainer" && $openPosition !== 'left') ? '0': $openPosition === 'left' ? '0' : 'auto'};
85
+ }
86
+ }
87
+ }
88
+ `
89
+ if ($alias === '_dropdownFilterContainer') {
90
+ style += `
91
+ margin-top: 4px;
92
+ ${DropDownControl} {
93
+ margin-top: -4px;
94
+ }
95
+ `
96
+ }
97
+ if ($externalWidth) {
98
+ style += `
99
+ width: ${$externalWidth}
100
+ `
101
+ }
102
+ if ($externalMinWidth) {
103
+ style += `
104
+ min-width: ${$externalMinWidth}
105
+ `
106
+ }
107
+ if ($area === 'mobile') {
108
+ style += `
109
+ @media (min-width: 320px) and (max-width: 480px) {
110
+ ${DropDownWrapper} {
111
+ width: 100%;
112
+ align-content: start;
113
+ z-index: 88;
114
+ }
115
+ }
116
+ `
117
+ }
118
+ return style
119
+ }
120
+
121
+ const getDropDownWrapperModifiedStyled = ({ $internalWidth, $openPosition, $placement, $bottom, $top }: TDropdownChild) => {
122
+ let style = ''
123
+ if ($internalWidth) {
124
+ style += `
125
+ width: ${$internalWidth};
126
+ `
127
+ } else {
128
+ style +=`
129
+ width: auto;
130
+ white-space: nowrap;
131
+ ${DropDownBody} {
132
+ overflow: unset;
133
+ }
134
+ `
135
+ }
136
+ if ($openPosition === 'left') {
137
+ style += `
138
+ left: 0;
139
+ right: auto;
140
+ `
141
+ } else if ($openPosition === 'center') {
142
+ style += `
143
+ left: 50%;
144
+ right: auto;
145
+ transform: translateX(-50%);
146
+ `
147
+ }
148
+ if ($placement === 'top' && $bottom) {
149
+ style += `
150
+ top: unset; bottom: ${$bottom}
151
+ `
152
+ } else if ($top) {
153
+ style += `
154
+ top: ${$top};
155
+ `
156
+ }
157
+ return style
158
+ }
159
+
160
+ const getDropDownBodyModifiedStyled = ({ $area }:{ $area?: string }) => {
161
+ let style = ''
162
+ if ($area === 'promotion') {
163
+ style += `
164
+ max-height: 347px;
165
+ overflow-y: auto;
166
+ `
167
+ }
168
+ return style
169
+ }
170
+
171
+ const getDropDownActionModifiedStyled = ({ $position }:{ $position?: string }) => {
172
+ let style = `
173
+ justify-self: end;
174
+ `
175
+ if ($position === 'middle') {
176
+ style += `
177
+ width: 100%;
178
+ text-align: center;
179
+ `
180
+ } else if ($position === 'left') {
181
+ style += `
182
+ width: 100%;
183
+ `
184
+ } else if ($position === 'end') {
185
+ style += `
186
+ width: 100%;
187
+ text-align: end
188
+ `
189
+ }
190
+ return style
191
+ }
192
+
193
+ export const DropDownWrapper = styled.section<TDropdownChild>`
194
+ ${dropBase}
195
+ position: fixed;
196
+ width: 100vw;
197
+ z-index: 102;
198
+ display: none;
199
+ border-radius: 10px 10px 0px 0px;
200
+ > div,
201
+ > section {
202
+ padding: 1em;
203
+ }
204
+ @media only screen and (min-width: 768px) {
205
+ position: absolute;
206
+ min-width: 110px;
207
+ width: 100vw;
208
+ top: 40px;
209
+ right: 0;
210
+ z-index: 10;
211
+ border-radius: var(--sec-rd);
212
+ > div,
213
+ > section {
214
+ padding: 1em;
215
+ ._refFilterDropdown {
216
+ > * {
217
+ margin-left: -1em;
218
+ margin-right: -1em;
219
+ &:first-child {
220
+ margin-top: -1em;
221
+ }
222
+ &:last-child {
223
+ margin-bottom: -1em;
224
+ }
225
+ }
226
+ > article {
227
+ padding: 1em;
228
+ width: calc(100% + 2em);
229
+ }
230
+ }
231
+ }
232
+ ${getDropDownWrapperModifiedStyled}
233
+ }
234
+ `
235
+
236
+ export const DropDownOverlayWrapper = styled.div`
237
+ width: 100%;
238
+ height: 100%;
239
+ position: fixed;
240
+ top: 0;
241
+ left: 0;
242
+ z-index: 100;
243
+ background-color: rgba(0, 0, 0, .1);
244
+ display: none;
245
+ @media only screen and (min-width: 768px) {
246
+ display: none !important;
247
+ }
248
+ `
249
+
250
+ export const DropDownControl = styled.section`
251
+ display: block;
252
+ `
253
+
254
+ export const DropdownControlWrapper = styled.div`
255
+ ._refDropdownControl {
256
+ display: none;
257
+ }
258
+ ._refDropdownControlMobile {
259
+ display: block;
260
+ }
261
+ @media only screen and (min-width: 1024px) {
262
+ ._refDropdownControl {
263
+ display: block;
264
+ }
265
+ ._refDropdownControlMobile {
266
+ display: none;
267
+ }
268
+ }
269
+ `
270
+
271
+ export const DropDownContainer = styled.section<{ $area?: string }>`
272
+ position: relative;
273
+ ${getDropDownContainerModifiedStyled}
274
+ @media only screen and (min-width: 1024px) {
275
+ &._refContainerhover:hover {
276
+ ${DropDownWrapper} {
277
+ display: grid;
278
+ animation: droptodown .075s linear;
279
+ top: '35px';
280
+ }
281
+ }
282
+ }
283
+ `
284
+
285
+ export const DropDownTitle = styled.div`
286
+ font-weight: 600;
287
+ border-bottom: 1px solid var(--sec-clr-ln);
288
+ `
289
+
290
+ export const DropDownSubTitle = styled.p`
291
+ color: var(--mt-clr);
292
+ margin-top: 4px;
293
+ margin-bottom: 0;
294
+ font-weight: 400;
295
+ line-height: 1;
296
+ letter-spacing: normal;
297
+ `
298
+
299
+ export const DropDownBody = styled.section<{ $area?: string }>`
300
+ overflow-y: auto;
301
+ max-height: 75vh;
302
+ overflow-x: hidden;
303
+ @media (max-width: 767px) {
304
+ max-height: 65vh;
305
+ }
306
+ ${getDropDownBodyModifiedStyled}
307
+ `
308
+
309
+ export const DropDownAction = styled.section<{ $position?: string }>`
310
+ border-top: 1px solid var(--sec-clr-ln);
311
+ ${getDropDownActionModifiedStyled}
312
+ `
313
+
314
+ export const DropdownPortalContainer = styled.div`
315
+ display: inline-block;
316
+ position: fixed;
317
+ top: 0;
318
+ left: 0;
319
+ z-index: 999;
320
+ &.is-shown {
321
+ & ${DropDownWrapper} {
322
+ display: block;
323
+ }
324
+ }
325
+ `
@@ -0,0 +1,254 @@
1
+ import { useEffect, useRef, isValidElement } from 'react';
2
+ import ReactTooltip from 'react-tooltip';
3
+ import ReactPortalComponent from '../portal/react_portal';
4
+ import { DropDownContainer, DropDownTitle, DropDownSubTitle, DropDownWrapper, DropDownOverlayWrapper, DropDownControl, DropDownBody, DropDownAction, DropdownControlWrapper, DropdownPortalContainer } from './dropdown.styles';
5
+ import type { TMouseEvent } from '../../typeds/base.typed';
6
+ import type { TDropdown } from './dropdown.typed';
7
+
8
+ const DropDownComponent = ({ children, title, subTitle, $externalWidth, $externalMinWidth, $internalWidth, $area, $openPosition, $placement, $top, onClick, $alias, type, portalId, $bottom, ...props }: TDropdown) => {
9
+ useEffect(() => {
10
+ ReactTooltip.rebuild() ;
11
+ }, [])
12
+
13
+ const buttonRef = useRef<HTMLElement>(null);
14
+
15
+ const evScrollDropdown = () => {
16
+ const containerEl = document.getElementsByClassName('_refContainer is-shown')[0] as HTMLElement;
17
+ if (containerEl) {
18
+ const offsetPos = containerEl.getBoundingClientRect();
19
+ const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
20
+ if (portalContainerRef) {
21
+ const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
22
+ portalContainerRef.style.left = offsetPos.left + offsetPos.width - wrapperRef.getBoundingClientRect().width + 'px';
23
+ portalContainerRef.style.top = offsetPos.top + parseInt($top || '0') - 32 + 'px';
24
+ }
25
+ }
26
+ }
27
+
28
+ const evResetDropdown = () => {
29
+ const containerRef = document.getElementsByClassName('_refContainer is-shown') as HTMLCollectionOf<HTMLElement>;
30
+ if (containerRef.length) {
31
+ for (let i = 0; i < containerRef.length; i++) {
32
+ containerRef[i].classList.remove('is-shown');
33
+ }
34
+ }
35
+ const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
36
+ refScrollContainerEl.removeEventListener('scroll', evScrollDropdown, true);
37
+ setTimeout(() => {
38
+ if (portalId) {
39
+ const portalContainerRef = document.getElementsByClassName('_refDropdownPortal is-shown') as HTMLCollectionOf<HTMLElement>;
40
+ if (portalContainerRef.length) {
41
+ for (let i = 0; i < portalContainerRef.length; i++) {
42
+ portalContainerRef[i].style.left = '0';
43
+ portalContainerRef[i].style.top = '0';
44
+ portalContainerRef[i].classList.remove('is-shown');
45
+ }
46
+ }
47
+ }
48
+ },10);
49
+ }
50
+
51
+ const evToogleDropdown: TMouseEvent = e => {
52
+ const currRefEl = buttonRef.current;
53
+ if (currRefEl) {
54
+ const buttonEl = (e.target as HTMLElement).closest(`.${currRefEl.classList[0]}`);
55
+ if (!buttonEl) {
56
+ return;
57
+ }
58
+ const containerEl = buttonEl.closest('._refContainer') as HTMLElement;
59
+ if (containerEl) {
60
+ const isCurOpen = containerEl.classList.contains('is-shown');
61
+ const offsetPos = containerEl.getBoundingClientRect();
62
+
63
+ if (!isCurOpen) {
64
+ evResetDropdown();
65
+ containerEl.classList.add('is-shown');
66
+ setTimeout(() => {
67
+ if (portalId) {
68
+ const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
69
+ const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
70
+ const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
71
+ if (portalContainerRef) {
72
+ if (offsetPos) {
73
+ if (wrapperRef) {
74
+ setTimeout(() => {
75
+ wrapperRef.style.right = 'auto';
76
+ portalContainerRef.style.left = offsetPos.left + offsetPos.width - wrapperRef.getBoundingClientRect().width + 'px';
77
+ portalContainerRef.style.top = offsetPos.top + parseInt($top || '0') - 32 + 'px';
78
+ portalContainerRef.style.zIndex = '8';
79
+ refScrollContainerEl.addEventListener('scroll', evScrollDropdown, true);
80
+ }, 10);
81
+ } else {
82
+ portalContainerRef.style.left = offsetPos.left + ((parseInt($internalWidth || '0') + offsetPos.width) / 2) + 'px';
83
+ portalContainerRef.style.top = (offsetPos.top + offsetPos.height) + 'px';
84
+ }
85
+ }
86
+ portalContainerRef.classList.add('is-shown');
87
+ }
88
+ }
89
+ }, 10);
90
+ onClick && onClick(e);
91
+ } else {
92
+ containerEl.classList.remove('is-shown');
93
+ setTimeout(() => {
94
+ if (portalId) {
95
+ const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
96
+ const refScrollContainerEl = document.querySelector('._refScrollContainer') as HTMLElement;
97
+ const wrapperRef = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
98
+ if (portalContainerRef) {
99
+ portalContainerRef.classList.remove('is-shown');
100
+ portalContainerRef.style.left = '0px';
101
+ portalContainerRef.style.top = '0px';
102
+ if (wrapperRef) {
103
+ refScrollContainerEl.removeEventListener('scroll', evScrollDropdown, true);
104
+ }
105
+ }
106
+ }
107
+ }, 10);
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ const evMouseEnter: TMouseEvent = e => {
114
+ const currRefEl = buttonRef.current;
115
+ if (currRefEl) {
116
+ const buttonEl = (e.target as HTMLElement).closest(`.${currRefEl.classList[0]}`);
117
+ if (!buttonEl) {
118
+ return;
119
+ }
120
+ const portalContainerRefs = document.querySelectorAll(`._refDropdownPortal`) as NodeListOf<HTMLElement>;
121
+ for (const portalContainerRef of portalContainerRefs) {
122
+ portalContainerRef.classList.remove('is-shown');
123
+ portalContainerRef.style.left = '0';
124
+ portalContainerRef.style.top = '0';
125
+ }
126
+ const containerEl = buttonEl.closest('._refContainer') as HTMLElement;
127
+ if (containerEl) {
128
+ const offsetPos = containerEl.getBoundingClientRect();
129
+ const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
130
+ if (portalContainerRef) {
131
+ if (offsetPos) {
132
+ portalContainerRef.style.left = offsetPos.left + ((parseInt($internalWidth || '0') + offsetPos.width) / 2) + 'px';
133
+ let currentTop = offsetPos.top + offsetPos.height;
134
+ const dropdownWrapperEl = portalContainerRef.querySelector('._refDropdownWrapper') as HTMLElement;
135
+ if (dropdownWrapperEl) {
136
+ dropdownWrapperEl.style.display = 'block';
137
+ if ((currentTop + dropdownWrapperEl.clientHeight) >= document.body.clientHeight) {
138
+ currentTop = offsetPos.top - dropdownWrapperEl.clientHeight - 10;
139
+ }
140
+ }
141
+ portalContainerRef.style.top = currentTop + 'px';
142
+ }
143
+ portalContainerRef.classList.add('is-shown');
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ useEffect(() => {
150
+ setTimeout(() => {
151
+ const portalContainerRefs = document.querySelectorAll(`._refDropdownPortal._refHover`) as NodeListOf<HTMLElement>;
152
+ for (let portalContainerRef of portalContainerRefs) {
153
+ portalContainerRef && portalContainerRef.addEventListener('mouseenter', (event) => {
154
+ const el = event.target as HTMLElement;
155
+ el.classList.add('is-shown');
156
+ el.classList.add('unhiddenable');
157
+ })
158
+ portalContainerRef && portalContainerRef.addEventListener('mouseleave', (event) => {
159
+ const el = event.target as HTMLElement;
160
+ el.classList.remove('is-shown');
161
+ el.classList.remove('unhiddenable');
162
+ el.style.left = '0';
163
+ el.style.top = '0';
164
+ })
165
+ }
166
+ }, 1);
167
+ return () => {
168
+ const portalContainerRefs = document.querySelectorAll(`._refDropdownPortal._refHover`) as NodeListOf<HTMLElement>;
169
+ for (let portalContainerRef of portalContainerRefs) {
170
+ portalContainerRef && portalContainerRef.removeEventListener('mouseenter', (event) => {
171
+ const el = event.target as HTMLElement;
172
+ el.classList.add('is-shown');
173
+ el.classList.add('unhiddenable');
174
+ }, true)
175
+ portalContainerRef && portalContainerRef.removeEventListener('mouseleave', (event) => {
176
+ const el = event.target as HTMLElement;
177
+ el.classList.remove('is-shown');
178
+ el.classList.remove('unhiddenable');
179
+ el.style.left = '0';
180
+ el.style.top = '0';
181
+ }, true)
182
+ }
183
+ };
184
+ }, [portalId])
185
+
186
+ const evMouseLeave: TMouseEvent = e => {
187
+ const currRefEl = buttonRef.current;
188
+ if (currRefEl) {
189
+ const buttonEl = (e.target as HTMLElement).closest(`.${currRefEl.classList[0]}`);
190
+ if (!buttonEl) {
191
+ return;
192
+ }
193
+ setTimeout(() => {
194
+ const portalContainerRef = document.querySelector(`#${portalId} ._refDropdownPortal`) as HTMLElement;
195
+ if (portalContainerRef && !portalContainerRef.classList.contains('unhiddenable')) {
196
+ portalContainerRef.classList.remove('is-shown');
197
+ portalContainerRef.style.left = '0';
198
+ portalContainerRef.style.top = '0';
199
+ }
200
+ }, 150);
201
+ }
202
+ }
203
+
204
+ const evCloseDropdown = () => {
205
+ evResetDropdown();
206
+ }
207
+
208
+ const DropDownSubTitleEl = (subTitle) ? <DropDownSubTitle>{subTitle}</DropDownSubTitle> : null;
209
+ const DropDownTitleEl = (title) ? <DropDownTitle>{title} {DropDownSubTitleEl}</DropDownTitle> : null;
210
+ const ControlChildrenFilter = children.filter((child: any) => isValidElement(child) ? ((child.props as any)['aria-label'] === 'control') : null);
211
+ const DropDownControlEl = (ControlChildrenFilter && isValidElement(ControlChildrenFilter[0])) ?
212
+ type === 'hover' ? (
213
+ <DropdownControlWrapper>
214
+ <DropDownControl className='_refDropdownControl' {...portalId && { onMouseEnter: evMouseEnter, onMouseLeave: evMouseLeave }}>{(ControlChildrenFilter[0].props as any).children}</DropDownControl>
215
+ <DropDownControl className='_refDropdownControlMobile' ref={buttonRef} onClick={evToogleDropdown}>{(ControlChildrenFilter[0].props as any).children}</DropDownControl>
216
+ </DropdownControlWrapper>
217
+ ) : <DropDownControl ref={buttonRef} onClick={evToogleDropdown} >{(ControlChildrenFilter[0].props as any).children}</DropDownControl>
218
+ : null
219
+ const BodyChildrenFilter = children.filter((child: any) => isValidElement(child) ? ((child.props as any)['aria-label'] === 'body') : null)
220
+ const DropDownBodyEl = (BodyChildrenFilter && isValidElement(BodyChildrenFilter[0])) ? <DropDownBody $area={$area}>{(BodyChildrenFilter[0].props as any).children}</DropDownBody> : null
221
+ const ActionChildrenFilter = children.filter((child: any) => isValidElement(child) ? ((child.props as any)['aria-label'] === 'action') : null)
222
+ const DropDownActionEl = (ActionChildrenFilter && isValidElement(ActionChildrenFilter[0])) ? <DropDownAction $position={(ActionChildrenFilter[0].props as any)['data-position']} className={(ActionChildrenFilter[0].props as any).className}>{(ActionChildrenFilter[0].props as any).children}</DropDownAction> : null
223
+
224
+ const dropdownWrapperEl = <DropDownWrapper
225
+ className='_refDropdownWrapper'
226
+ {...$internalWidth && { $internalWidth: $internalWidth }}
227
+ {...$top && { $top: $top }}
228
+ {...$openPosition && { $openPosition: $openPosition }}
229
+ {...$placement && { $placement: $placement }}
230
+ {...$bottom && { $bottom: $bottom }}>
231
+ {DropDownTitleEl}
232
+ {DropDownBodyEl}
233
+ {DropDownActionEl}
234
+ </DropDownWrapper>
235
+ return (
236
+ <DropDownContainer
237
+ className={`_refContainer ${type ? `_refContainer${type}` : ``}`}
238
+ {...$externalWidth && { $externalWidth: $externalWidth }}
239
+ {...$externalMinWidth && { $externalMinWidth: $externalMinWidth }}
240
+ {...$area && { $area: $area }}
241
+ {...$top && { $top: $top }}
242
+ {...$alias && { $alias: $alias }}
243
+ {...$openPosition && { $openPosition: $openPosition }}
244
+ {...$placement && { $placement: $placement }}
245
+ {...$bottom && { $bottom: $bottom }}
246
+ {...props}>
247
+ {DropDownControlEl}
248
+ <DropDownOverlayWrapper className='_refDropdownOverlay' onClick={evCloseDropdown} />
249
+ { portalId ? <ReactPortalComponent wrapperId={portalId}><DropdownPortalContainer className={`_refDropdownPortal ${type === 'hover' ? '_refHover' : ''}`}>{dropdownWrapperEl}</DropdownPortalContainer></ReactPortalComponent> : dropdownWrapperEl }
250
+ </DropDownContainer>
251
+ );
252
+ }
253
+
254
+ export default DropDownComponent;
@@ -0,0 +1,24 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import type { TMouseEvent } from '../../typeds/base.typed'
4
+
5
+ export type TDropdown = {
6
+ children: ReactNode[]
7
+ title?: string
8
+ subTitle?: string
9
+ $externalWidth?: string
10
+ $externalMinWidth?: string
11
+ $internalWidth?: string
12
+ $area?: string
13
+ $openPosition?: string
14
+ $placement?: string
15
+ $top?: string
16
+ $bottom?: string
17
+ $alias?: string
18
+ type?: string
19
+ portalId?: string
20
+ onClick?: TMouseEvent
21
+ detail?: string
22
+ }
23
+
24
+ export type TCloseDropdownFunction = (currentTarget: EventTarget & HTMLElement) => void
@@ -6,3 +6,12 @@ export { default as ButtonComponent } from './button/button';
6
6
  export { default as LabelComponent } from './label/label';
7
7
  export { default as IconComponent } from './icon/icon';
8
8
  export { default as LoadingComponent } from './loading/loading';
9
+ export { default as DropdownComponent } from './dropdown/dropdown';
10
+ export { default as MessageComponent } from './message/message';
11
+ export { default as MessageQuestionComponent } from './message/message_question';
12
+ export { default as PopupComponent } from './popup/popup';
13
+ export { default as ReactPortalComponent } from './portal/react_portal';
14
+
15
+ export * from './dropdown/dropdown.typed';
16
+ export * from './message/message.typed';
17
+ export * from './popup/popup.typed';