@redneckz/wildless-cms-uni-blocks 0.14.253 → 0.14.255
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/bundle/bundle.umd.js +1 -1
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/bundle/data/StickyMobileData.d.ts +2 -2
- package/dist/components/StickyBottomMenu/StickyBottomMenu.mobile.js +61 -4
- package/dist/components/StickyBottomMenu/StickyBottomMenu.mobile.js.map +1 -1
- package/dist/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/dist/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
- package/dist/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
- package/dist/data/StickyMobileData.d.ts +2 -2
- package/lib/common.css +1 -1
- package/lib/components/StickyBottomMenu/StickyBottomMenu.mobile.js +61 -4
- package/lib/components/StickyBottomMenu/StickyBottomMenu.mobile.js.map +1 -1
- package/lib/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/lib/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
- package/lib/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
- package/lib/data/StickyMobileData.d.ts +2 -2
- package/mobile/bundle/bundle.umd.js +69 -18
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/mobile/bundle/data/StickyMobileData.d.ts +2 -2
- package/mobile/dist/components/StickyBottomMenu/StickyBottomMenu.js +61 -4
- package/mobile/dist/components/StickyBottomMenu/StickyBottomMenu.js.map +1 -1
- package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
- package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
- package/mobile/dist/data/StickyMobileData.d.ts +2 -2
- package/mobile/lib/common.css +1 -1
- package/mobile/lib/components/StickyBottomMenu/StickyBottomMenu.js +61 -4
- package/mobile/lib/components/StickyBottomMenu/StickyBottomMenu.js.map +1 -1
- package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
- package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
- package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
- package/mobile/lib/data/StickyMobileData.d.ts +2 -2
- package/mobile/src/components/BenefitsBlock/BenefitsBlock.example.json +2 -0
- package/mobile/src/components/BonusBenefitsBlock/BonusBenefitsBlock.example.json +2 -0
- package/mobile/src/components/ContactsBlock/ContactsBlock.example.json +1 -0
- package/mobile/src/components/ErrorBlock/ErrorBlock.example.json +2 -0
- package/mobile/src/components/ImgBlock/ImgBlock.example.json +2 -0
- package/mobile/src/components/InsuranceAmountBlock/InsuranceAmountBlock.example.json +2 -0
- package/mobile/src/components/ProductBlock/ProductBlock.example.json +4 -7
- package/mobile/src/components/RichTextBlock/RichTextBlock.example.json +2 -0
- package/mobile/src/components/StepsBlock/StepsBlock.example.json +1 -0
- package/mobile/src/components/StickyBottomMenu/StickyBottomMenu.tsx +119 -11
- package/mobile/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
- package/mobile/src/components/TextBlock/TextBlock.example.json +2 -0
- package/mobile/src/components/UnitBlock/UnitBlock.example.json +2 -0
- package/mobile/src/data/StickyMobileData.ts +2 -2
- package/package.json +1 -1
- package/src/components/BenefitsBlock/BenefitsBlock.example.json +2 -0
- package/src/components/BonusBenefitsBlock/BonusBenefitsBlock.example.json +2 -0
- package/src/components/ContactsBlock/ContactsBlock.example.json +1 -0
- package/src/components/ErrorBlock/ErrorBlock.example.json +2 -0
- package/src/components/ImgBlock/ImgBlock.example.json +2 -0
- package/src/components/InsuranceAmountBlock/InsuranceAmountBlock.example.json +2 -0
- package/src/components/ProductBlock/ProductBlock.example.json +4 -7
- package/src/components/RichTextBlock/RichTextBlock.example.json +2 -0
- package/src/components/StepsBlock/StepsBlock.example.json +1 -0
- package/src/components/StickyBottomMenu/StickyBottomMenu.fixture.mobile.tsx +2 -0
- package/src/components/StickyBottomMenu/StickyBottomMenu.mobile.tsx +119 -11
- package/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
- package/src/components/TextBlock/TextBlock.example.json +2 -0
- package/src/components/UnitBlock/UnitBlock.example.json +2 -0
- package/src/data/StickyMobileData.ts +2 -2
|
@@ -14,11 +14,7 @@
|
|
|
14
14
|
"height": 234
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"items": [
|
|
18
|
-
"Элемент списка 1",
|
|
19
|
-
"Элемент списка 2",
|
|
20
|
-
"Элемент списка 3"
|
|
21
|
-
],
|
|
17
|
+
"items": ["Элемент списка 1", "Элемент списка 2", "Элемент списка 3"],
|
|
22
18
|
"isDotted": true,
|
|
23
19
|
"buttons": [
|
|
24
20
|
{
|
|
@@ -53,6 +49,8 @@
|
|
|
53
49
|
"С показателем",
|
|
54
50
|
{
|
|
55
51
|
"content": {
|
|
52
|
+
"version": "primary",
|
|
53
|
+
"padding": "",
|
|
56
54
|
"title": "Продукт",
|
|
57
55
|
"description": "Описание",
|
|
58
56
|
"headlineVersion": "XL",
|
|
@@ -64,7 +62,6 @@
|
|
|
64
62
|
"version": "secondary"
|
|
65
63
|
}
|
|
66
64
|
],
|
|
67
|
-
"version": "primary",
|
|
68
65
|
"benefitsVersion": "normal",
|
|
69
66
|
"benefits": [
|
|
70
67
|
{
|
|
@@ -93,4 +90,4 @@
|
|
|
93
90
|
]
|
|
94
91
|
}
|
|
95
92
|
]
|
|
96
|
-
]
|
|
93
|
+
]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"content": {
|
|
3
|
+
"version": "primary",
|
|
4
|
+
"padding": "",
|
|
3
5
|
"__html": "<h1>Заголовок 1</h1>\n<h2>Заголовок 2</h2>\n<h3>Заголовок 3</h3>\n<h4>Заголовок 4</h4>\n<h5>Заголовок 5</h5>\n<h6>Заголовок 6</h6>\n<p>Параграф, в котором много текста и даже <a href=\"#\">ссылка</a></p>\n<p><strong>Жирный текст</strong>, <em>Наклонный текст</em></p>\n<ul>\n <li>Список с точками</li>\n <li>Список с точками</li>\n</ul>\n<ol>\n <li>Нумерованный список</li>\n <li>Нумерованный список</li>\n</ol>\n",
|
|
4
6
|
"richVersion": ""
|
|
5
7
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from '@redneckz/uni-jsx/lib/hooks';
|
|
2
|
+
import { useBool } from '@redneckz/uni-jsx/lib/hooks/useBool';
|
|
3
|
+
import { useOutsideClick } from '@redneckz/uni-jsx/lib/hooks/useOutsideClick';
|
|
1
4
|
import { type StickyMenuItem } from '../../data/StickyMobileData';
|
|
2
|
-
import { useActiveRoute } from '../../hooks/useActiveRoute';
|
|
3
5
|
import { BlockWrapper } from '../../ui-kit/BlockWrapper';
|
|
6
|
+
import { CloseButton } from '../../ui-kit/DialogManager/CloseButton';
|
|
7
|
+
import { usePopupManager } from '../../ui-kit/PopupManager/usePopupManager';
|
|
4
8
|
import { UniBlock } from '../../UniBlock/UniBlock';
|
|
5
9
|
import { StickyBottomMenuBurger } from './StickyBottomMenuBurger';
|
|
6
10
|
import { StickyBottomMenuItem } from './StickyBottomMenuItem';
|
|
@@ -9,36 +13,140 @@ import { useBurgerMenuDialog } from './useBurgerMenuDialog';
|
|
|
9
13
|
|
|
10
14
|
const EMPTY_MENU = [];
|
|
11
15
|
|
|
16
|
+
interface CurrentActiveItem {
|
|
17
|
+
activeIndex: number;
|
|
18
|
+
currentItemPosition: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line max-lines-per-function
|
|
12
22
|
export const StickyBottomMenu = UniBlock<StickyBottomMenuProps>(({ sticky, ...rest }) => {
|
|
13
23
|
const { menuItems = EMPTY_MENU } = sticky ?? {};
|
|
14
24
|
const [isBurgerMenuDialogOpen, { toggle, close }] = useBurgerMenuDialog(
|
|
15
25
|
rest.options?.page?.sitemap ?? {},
|
|
16
26
|
);
|
|
17
|
-
|
|
18
|
-
const [, activeItem] = useActiveRoute(menuItems);
|
|
27
|
+
const popup = usePopupManager();
|
|
19
28
|
|
|
20
29
|
const middleIdx = Math.floor(menuItems.length / 2);
|
|
21
30
|
const leftItems = menuItems.slice(0, middleIdx);
|
|
22
31
|
const rightItems = menuItems.slice(middleIdx);
|
|
23
32
|
|
|
33
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
34
|
+
const [currentItemPosition, setCurrentItemPosition] = useState<string>('');
|
|
35
|
+
const [popupState, { setFalse: setPopupClosed, setTrue: setPopupOpened }] = useBool();
|
|
36
|
+
|
|
37
|
+
const closePopup = useCallback(() => {
|
|
38
|
+
setPopupClosed();
|
|
39
|
+
setActiveIndex(-1);
|
|
40
|
+
setCurrentItemPosition('');
|
|
41
|
+
popup.close();
|
|
42
|
+
}, [popup]);
|
|
43
|
+
|
|
44
|
+
const menuRef = useRef<HTMLDivElement | null>(null);
|
|
45
|
+
const popupRef = useOutsideClick<HTMLDivElement>(closePopup);
|
|
46
|
+
|
|
47
|
+
const openPopup = useCallback(
|
|
48
|
+
(index: number, itemsPosition: string) => {
|
|
49
|
+
setPopupOpened();
|
|
50
|
+
close();
|
|
51
|
+
const menuDimensions = menuRef?.current?.getBoundingClientRect();
|
|
52
|
+
|
|
53
|
+
popup.open(
|
|
54
|
+
<div
|
|
55
|
+
onClick={(e) => e.stopPropagation()}
|
|
56
|
+
className="sticky py-xl top-0 rounded-t-3xl bg-white z-10"
|
|
57
|
+
>
|
|
58
|
+
<div className="container px-xl text-center text-h3">
|
|
59
|
+
{itemsPosition === 'left' ? leftItems[index].title : rightItems[index].title}
|
|
60
|
+
<CloseButton className="absolute top-0 right-0" onClose={closePopup} />
|
|
61
|
+
</div>
|
|
62
|
+
<div
|
|
63
|
+
className="bg-white text-l h-[70vh] overflow-y-auto no-scrollbar"
|
|
64
|
+
ref={popupRef}
|
|
65
|
+
></div>
|
|
66
|
+
</div>,
|
|
67
|
+
{
|
|
68
|
+
top:
|
|
69
|
+
-Math.max(
|
|
70
|
+
globalThis.document?.documentElement?.clientHeight || 0,
|
|
71
|
+
globalThis.innerHeight || 0,
|
|
72
|
+
) *
|
|
73
|
+
0.7 -
|
|
74
|
+
56,
|
|
75
|
+
left: menuDimensions?.left || 0,
|
|
76
|
+
width: menuDimensions?.width,
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
},
|
|
80
|
+
[close, popup],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const handleMenuItemClick = useCallback(
|
|
84
|
+
(index: number, itemsPosition: string) => {
|
|
85
|
+
setCurrentItemPosition(itemsPosition);
|
|
86
|
+
setActiveIndex(index);
|
|
87
|
+
openPopup(index, itemsPosition);
|
|
88
|
+
},
|
|
89
|
+
[openPopup],
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!popupRef.current) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!popupRef.current.shadowRoot) {
|
|
98
|
+
popupRef.current?.attachShadow({ mode: 'open' });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const shadowRoot = popupRef.current.shadowRoot;
|
|
102
|
+
if (!shadowRoot) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (currentItemPosition === 'left') {
|
|
107
|
+
shadowRoot.innerHTML = leftItems[activeIndex]?.__html || '';
|
|
108
|
+
} else {
|
|
109
|
+
shadowRoot.innerHTML = rightItems[activeIndex]?.__html || '';
|
|
110
|
+
}
|
|
111
|
+
}, [activeIndex, currentItemPosition, popupState]);
|
|
112
|
+
|
|
24
113
|
return (
|
|
25
114
|
<BlockWrapper className="h-[74px] z-[100] relative" defaultPadding="p-0" {...rest}>
|
|
26
|
-
<div
|
|
27
|
-
{
|
|
115
|
+
<div
|
|
116
|
+
ref={menuRef}
|
|
117
|
+
className="ml-auto container bg-white flex justify-center shadow-blue-gray"
|
|
118
|
+
>
|
|
119
|
+
{leftItems.map(
|
|
120
|
+
renderMenuItem(handleMenuItemClick, 'left', { activeIndex, currentItemPosition }),
|
|
121
|
+
)}
|
|
28
122
|
<StickyBottomMenuBurger isActive={isBurgerMenuDialogOpen} onClick={toggle} />
|
|
29
|
-
{rightItems.map(
|
|
123
|
+
{rightItems.map(
|
|
124
|
+
renderMenuItem(handleMenuItemClick, 'right', { activeIndex, currentItemPosition }),
|
|
125
|
+
)}
|
|
30
126
|
</div>
|
|
31
127
|
</BlockWrapper>
|
|
32
128
|
);
|
|
33
129
|
});
|
|
34
130
|
|
|
35
131
|
const renderMenuItem =
|
|
36
|
-
(
|
|
37
|
-
(
|
|
132
|
+
(
|
|
133
|
+
handleMenuItemClick: (index: number, itemsPosition: string) => void,
|
|
134
|
+
itemsPosition: string,
|
|
135
|
+
currentActiveItem: CurrentActiveItem,
|
|
136
|
+
) =>
|
|
137
|
+
(_: StickyMenuItem, i: number, arr: StickyMenuItem[]) => {
|
|
138
|
+
return (
|
|
38
139
|
<StickyBottomMenuItem
|
|
39
|
-
key={_.
|
|
40
|
-
isActive={_ === activeItem}
|
|
140
|
+
key={_.title || String(i)}
|
|
41
141
|
item={_}
|
|
42
|
-
|
|
142
|
+
isActive={
|
|
143
|
+
arr[currentActiveItem.activeIndex]?.title === _?.title &&
|
|
144
|
+
currentActiveItem.currentItemPosition === itemsPosition
|
|
145
|
+
}
|
|
146
|
+
onClick={(e) => {
|
|
147
|
+
e.stopPropagation();
|
|
148
|
+
handleMenuItemClick(i, itemsPosition);
|
|
149
|
+
}}
|
|
43
150
|
/>
|
|
44
151
|
);
|
|
152
|
+
};
|
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
2
|
import { type StickyMenuItem } from '../../data/StickyMobileData';
|
|
3
|
-
import { useLink } from '../../hooks/useLink';
|
|
4
3
|
import { Icon } from '../../ui-kit/Icon/Icon';
|
|
4
|
+
import { type PreventableEvent } from '../../ui-kit/PreventableEvent';
|
|
5
5
|
import { style } from '../../utils/style';
|
|
6
6
|
|
|
7
7
|
interface StickyBottomMenuItemProps {
|
|
8
8
|
isActive?: boolean;
|
|
9
9
|
item?: StickyMenuItem;
|
|
10
|
-
onClick?: () => void;
|
|
10
|
+
onClick?: (e: PreventableEvent) => void;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const StickyBottomMenuItem = JSX<StickyBottomMenuItemProps>(
|
|
14
14
|
({ isActive, item, onClick }) => {
|
|
15
|
-
const link = useLink({ isRemote: true });
|
|
16
|
-
const { href, onClick: handleClick } = link({ href: item?.href, onClick });
|
|
17
|
-
|
|
18
15
|
return (
|
|
19
|
-
<
|
|
16
|
+
<div
|
|
20
17
|
className={style(
|
|
21
18
|
isActive ? 'text-primary-main' : 'text-primary-text',
|
|
22
19
|
`w-10 m-4 flex justify-center items-center flex-col text-xs cursor-pointer`,
|
|
23
20
|
)}
|
|
24
|
-
href={href}
|
|
25
|
-
target="_self"
|
|
26
21
|
title={item?.title || ''}
|
|
27
|
-
onClick={
|
|
22
|
+
onClick={onClick}
|
|
28
23
|
>
|
|
29
24
|
<Icon
|
|
30
25
|
className="w-6 h-6"
|
|
@@ -32,7 +27,7 @@ export const StickyBottomMenuItem = JSX<StickyBottomMenuItemProps>(
|
|
|
32
27
|
iconVersion={isActive ? 'color' : 'black'}
|
|
33
28
|
/>
|
|
34
29
|
{item?.title || ''}
|
|
35
|
-
</
|
|
30
|
+
</div>
|
|
36
31
|
);
|
|
37
32
|
},
|
|
38
33
|
);
|
package/package.json
CHANGED
|
@@ -14,11 +14,7 @@
|
|
|
14
14
|
"height": 234
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
|
-
"items": [
|
|
18
|
-
"Элемент списка 1",
|
|
19
|
-
"Элемент списка 2",
|
|
20
|
-
"Элемент списка 3"
|
|
21
|
-
],
|
|
17
|
+
"items": ["Элемент списка 1", "Элемент списка 2", "Элемент списка 3"],
|
|
22
18
|
"isDotted": true,
|
|
23
19
|
"buttons": [
|
|
24
20
|
{
|
|
@@ -53,6 +49,8 @@
|
|
|
53
49
|
"С показателем",
|
|
54
50
|
{
|
|
55
51
|
"content": {
|
|
52
|
+
"version": "primary",
|
|
53
|
+
"padding": "",
|
|
56
54
|
"title": "Продукт",
|
|
57
55
|
"description": "Описание",
|
|
58
56
|
"headlineVersion": "XL",
|
|
@@ -64,7 +62,6 @@
|
|
|
64
62
|
"version": "secondary"
|
|
65
63
|
}
|
|
66
64
|
],
|
|
67
|
-
"version": "primary",
|
|
68
65
|
"benefitsVersion": "normal",
|
|
69
66
|
"benefits": [
|
|
70
67
|
{
|
|
@@ -93,4 +90,4 @@
|
|
|
93
90
|
]
|
|
94
91
|
}
|
|
95
92
|
]
|
|
96
|
-
]
|
|
93
|
+
]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"content": {
|
|
3
|
+
"version": "primary",
|
|
4
|
+
"padding": "",
|
|
3
5
|
"__html": "<h1>Заголовок 1</h1>\n<h2>Заголовок 2</h2>\n<h3>Заголовок 3</h3>\n<h4>Заголовок 4</h4>\n<h5>Заголовок 5</h5>\n<h6>Заголовок 6</h6>\n<p>Параграф, в котором много текста и даже <a href=\"#\">ссылка</a></p>\n<p><strong>Жирный текст</strong>, <em>Наклонный текст</em></p>\n<ul>\n <li>Список с точками</li>\n <li>Список с точками</li>\n</ul>\n<ol>\n <li>Нумерованный список</li>\n <li>Нумерованный список</li>\n</ol>\n",
|
|
4
6
|
"richVersion": ""
|
|
5
7
|
}
|
|
@@ -2,6 +2,7 @@ import '../../setup-fixture';
|
|
|
2
2
|
|
|
3
3
|
import { type BlockRendererOptions } from '../../BlockRenderer/BlockRendererOptions';
|
|
4
4
|
import { DialogManager } from '../../ui-kit/DialogManager/DialogManager';
|
|
5
|
+
import { PopupManager } from '../../ui-kit/PopupManager/PopupManager';
|
|
5
6
|
import { StickyBottomMenu } from './StickyBottomMenu';
|
|
6
7
|
|
|
7
8
|
const options = {
|
|
@@ -15,6 +16,7 @@ export default {
|
|
|
15
16
|
options={options}
|
|
16
17
|
sticky={{ $ref: '/wcms-resources/sticky-mobile-menu.json' }}
|
|
17
18
|
/>
|
|
19
|
+
<PopupManager />
|
|
18
20
|
<DialogManager />
|
|
19
21
|
</div>
|
|
20
22
|
),
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from '@redneckz/uni-jsx/lib/hooks';
|
|
2
|
+
import { useBool } from '@redneckz/uni-jsx/lib/hooks/useBool';
|
|
3
|
+
import { useOutsideClick } from '@redneckz/uni-jsx/lib/hooks/useOutsideClick';
|
|
1
4
|
import { type StickyMenuItem } from '../../data/StickyMobileData';
|
|
2
|
-
import { useActiveRoute } from '../../hooks/useActiveRoute';
|
|
3
5
|
import { BlockWrapper } from '../../ui-kit/BlockWrapper';
|
|
6
|
+
import { CloseButton } from '../../ui-kit/DialogManager/CloseButton';
|
|
7
|
+
import { usePopupManager } from '../../ui-kit/PopupManager/usePopupManager';
|
|
4
8
|
import { UniBlock } from '../../UniBlock/UniBlock';
|
|
5
9
|
import { StickyBottomMenuBurger } from './StickyBottomMenuBurger';
|
|
6
10
|
import { StickyBottomMenuItem } from './StickyBottomMenuItem';
|
|
@@ -9,36 +13,140 @@ import { useBurgerMenuDialog } from './useBurgerMenuDialog';
|
|
|
9
13
|
|
|
10
14
|
const EMPTY_MENU = [];
|
|
11
15
|
|
|
16
|
+
interface CurrentActiveItem {
|
|
17
|
+
activeIndex: number;
|
|
18
|
+
currentItemPosition: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line max-lines-per-function
|
|
12
22
|
export const StickyBottomMenu = UniBlock<StickyBottomMenuProps>(({ sticky, ...rest }) => {
|
|
13
23
|
const { menuItems = EMPTY_MENU } = sticky ?? {};
|
|
14
24
|
const [isBurgerMenuDialogOpen, { toggle, close }] = useBurgerMenuDialog(
|
|
15
25
|
rest.options?.page?.sitemap ?? {},
|
|
16
26
|
);
|
|
17
|
-
|
|
18
|
-
const [, activeItem] = useActiveRoute(menuItems);
|
|
27
|
+
const popup = usePopupManager();
|
|
19
28
|
|
|
20
29
|
const middleIdx = Math.floor(menuItems.length / 2);
|
|
21
30
|
const leftItems = menuItems.slice(0, middleIdx);
|
|
22
31
|
const rightItems = menuItems.slice(middleIdx);
|
|
23
32
|
|
|
33
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
34
|
+
const [currentItemPosition, setCurrentItemPosition] = useState<string>('');
|
|
35
|
+
const [popupState, { setFalse: setPopupClosed, setTrue: setPopupOpened }] = useBool();
|
|
36
|
+
|
|
37
|
+
const closePopup = useCallback(() => {
|
|
38
|
+
setPopupClosed();
|
|
39
|
+
setActiveIndex(-1);
|
|
40
|
+
setCurrentItemPosition('');
|
|
41
|
+
popup.close();
|
|
42
|
+
}, [popup]);
|
|
43
|
+
|
|
44
|
+
const menuRef = useRef<HTMLDivElement | null>(null);
|
|
45
|
+
const popupRef = useOutsideClick<HTMLDivElement>(closePopup);
|
|
46
|
+
|
|
47
|
+
const openPopup = useCallback(
|
|
48
|
+
(index: number, itemsPosition: string) => {
|
|
49
|
+
setPopupOpened();
|
|
50
|
+
close();
|
|
51
|
+
const menuDimensions = menuRef?.current?.getBoundingClientRect();
|
|
52
|
+
|
|
53
|
+
popup.open(
|
|
54
|
+
<div
|
|
55
|
+
onClick={(e) => e.stopPropagation()}
|
|
56
|
+
className="sticky py-xl top-0 rounded-t-3xl bg-white z-10"
|
|
57
|
+
>
|
|
58
|
+
<div className="container px-xl text-center text-h3">
|
|
59
|
+
{itemsPosition === 'left' ? leftItems[index].title : rightItems[index].title}
|
|
60
|
+
<CloseButton className="absolute top-0 right-0" onClose={closePopup} />
|
|
61
|
+
</div>
|
|
62
|
+
<div
|
|
63
|
+
className="bg-white text-l h-[70vh] overflow-y-auto no-scrollbar"
|
|
64
|
+
ref={popupRef}
|
|
65
|
+
></div>
|
|
66
|
+
</div>,
|
|
67
|
+
{
|
|
68
|
+
top:
|
|
69
|
+
-Math.max(
|
|
70
|
+
globalThis.document?.documentElement?.clientHeight || 0,
|
|
71
|
+
globalThis.innerHeight || 0,
|
|
72
|
+
) *
|
|
73
|
+
0.7 -
|
|
74
|
+
56,
|
|
75
|
+
left: menuDimensions?.left || 0,
|
|
76
|
+
width: menuDimensions?.width,
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
},
|
|
80
|
+
[close, popup],
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const handleMenuItemClick = useCallback(
|
|
84
|
+
(index: number, itemsPosition: string) => {
|
|
85
|
+
setCurrentItemPosition(itemsPosition);
|
|
86
|
+
setActiveIndex(index);
|
|
87
|
+
openPopup(index, itemsPosition);
|
|
88
|
+
},
|
|
89
|
+
[openPopup],
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!popupRef.current) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!popupRef.current.shadowRoot) {
|
|
98
|
+
popupRef.current?.attachShadow({ mode: 'open' });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const shadowRoot = popupRef.current.shadowRoot;
|
|
102
|
+
if (!shadowRoot) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (currentItemPosition === 'left') {
|
|
107
|
+
shadowRoot.innerHTML = leftItems[activeIndex]?.__html || '';
|
|
108
|
+
} else {
|
|
109
|
+
shadowRoot.innerHTML = rightItems[activeIndex]?.__html || '';
|
|
110
|
+
}
|
|
111
|
+
}, [activeIndex, currentItemPosition, popupState]);
|
|
112
|
+
|
|
24
113
|
return (
|
|
25
114
|
<BlockWrapper className="h-[74px] z-[100] relative" defaultPadding="p-0" {...rest}>
|
|
26
|
-
<div
|
|
27
|
-
{
|
|
115
|
+
<div
|
|
116
|
+
ref={menuRef}
|
|
117
|
+
className="ml-auto container bg-white flex justify-center shadow-blue-gray"
|
|
118
|
+
>
|
|
119
|
+
{leftItems.map(
|
|
120
|
+
renderMenuItem(handleMenuItemClick, 'left', { activeIndex, currentItemPosition }),
|
|
121
|
+
)}
|
|
28
122
|
<StickyBottomMenuBurger isActive={isBurgerMenuDialogOpen} onClick={toggle} />
|
|
29
|
-
{rightItems.map(
|
|
123
|
+
{rightItems.map(
|
|
124
|
+
renderMenuItem(handleMenuItemClick, 'right', { activeIndex, currentItemPosition }),
|
|
125
|
+
)}
|
|
30
126
|
</div>
|
|
31
127
|
</BlockWrapper>
|
|
32
128
|
);
|
|
33
129
|
});
|
|
34
130
|
|
|
35
131
|
const renderMenuItem =
|
|
36
|
-
(
|
|
37
|
-
(
|
|
132
|
+
(
|
|
133
|
+
handleMenuItemClick: (index: number, itemsPosition: string) => void,
|
|
134
|
+
itemsPosition: string,
|
|
135
|
+
currentActiveItem: CurrentActiveItem,
|
|
136
|
+
) =>
|
|
137
|
+
(_: StickyMenuItem, i: number, arr: StickyMenuItem[]) => {
|
|
138
|
+
return (
|
|
38
139
|
<StickyBottomMenuItem
|
|
39
|
-
key={_.
|
|
40
|
-
isActive={_ === activeItem}
|
|
140
|
+
key={_.title || String(i)}
|
|
41
141
|
item={_}
|
|
42
|
-
|
|
142
|
+
isActive={
|
|
143
|
+
arr[currentActiveItem.activeIndex]?.title === _?.title &&
|
|
144
|
+
currentActiveItem.currentItemPosition === itemsPosition
|
|
145
|
+
}
|
|
146
|
+
onClick={(e) => {
|
|
147
|
+
e.stopPropagation();
|
|
148
|
+
handleMenuItemClick(i, itemsPosition);
|
|
149
|
+
}}
|
|
43
150
|
/>
|
|
44
151
|
);
|
|
152
|
+
};
|
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
2
|
import { type StickyMenuItem } from '../../data/StickyMobileData';
|
|
3
|
-
import { useLink } from '../../hooks/useLink';
|
|
4
3
|
import { Icon } from '../../ui-kit/Icon/Icon';
|
|
4
|
+
import { type PreventableEvent } from '../../ui-kit/PreventableEvent';
|
|
5
5
|
import { style } from '../../utils/style';
|
|
6
6
|
|
|
7
7
|
interface StickyBottomMenuItemProps {
|
|
8
8
|
isActive?: boolean;
|
|
9
9
|
item?: StickyMenuItem;
|
|
10
|
-
onClick?: () => void;
|
|
10
|
+
onClick?: (e: PreventableEvent) => void;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const StickyBottomMenuItem = JSX<StickyBottomMenuItemProps>(
|
|
14
14
|
({ isActive, item, onClick }) => {
|
|
15
|
-
const link = useLink({ isRemote: true });
|
|
16
|
-
const { href, onClick: handleClick } = link({ href: item?.href, onClick });
|
|
17
|
-
|
|
18
15
|
return (
|
|
19
|
-
<
|
|
16
|
+
<div
|
|
20
17
|
className={style(
|
|
21
18
|
isActive ? 'text-primary-main' : 'text-primary-text',
|
|
22
19
|
`w-10 m-4 flex justify-center items-center flex-col text-xs cursor-pointer`,
|
|
23
20
|
)}
|
|
24
|
-
href={href}
|
|
25
|
-
target="_self"
|
|
26
21
|
title={item?.title || ''}
|
|
27
|
-
onClick={
|
|
22
|
+
onClick={onClick}
|
|
28
23
|
>
|
|
29
24
|
<Icon
|
|
30
25
|
className="w-6 h-6"
|
|
@@ -32,7 +27,7 @@ export const StickyBottomMenuItem = JSX<StickyBottomMenuItemProps>(
|
|
|
32
27
|
iconVersion={isActive ? 'color' : 'black'}
|
|
33
28
|
/>
|
|
34
29
|
{item?.title || ''}
|
|
35
|
-
</
|
|
30
|
+
</div>
|
|
36
31
|
);
|
|
37
32
|
},
|
|
38
33
|
);
|