@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.
Files changed (64) hide show
  1. package/bundle/bundle.umd.js +1 -1
  2. package/bundle/bundle.umd.min.js +1 -1
  3. package/bundle/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  4. package/bundle/data/StickyMobileData.d.ts +2 -2
  5. package/dist/components/StickyBottomMenu/StickyBottomMenu.mobile.js +61 -4
  6. package/dist/components/StickyBottomMenu/StickyBottomMenu.mobile.js.map +1 -1
  7. package/dist/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  8. package/dist/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
  9. package/dist/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
  10. package/dist/data/StickyMobileData.d.ts +2 -2
  11. package/lib/common.css +1 -1
  12. package/lib/components/StickyBottomMenu/StickyBottomMenu.mobile.js +61 -4
  13. package/lib/components/StickyBottomMenu/StickyBottomMenu.mobile.js.map +1 -1
  14. package/lib/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  15. package/lib/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
  16. package/lib/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
  17. package/lib/data/StickyMobileData.d.ts +2 -2
  18. package/mobile/bundle/bundle.umd.js +69 -18
  19. package/mobile/bundle/bundle.umd.min.js +1 -1
  20. package/mobile/bundle/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  21. package/mobile/bundle/data/StickyMobileData.d.ts +2 -2
  22. package/mobile/dist/components/StickyBottomMenu/StickyBottomMenu.js +61 -4
  23. package/mobile/dist/components/StickyBottomMenu/StickyBottomMenu.js.map +1 -1
  24. package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  25. package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
  26. package/mobile/dist/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
  27. package/mobile/dist/data/StickyMobileData.d.ts +2 -2
  28. package/mobile/lib/common.css +1 -1
  29. package/mobile/lib/components/StickyBottomMenu/StickyBottomMenu.js +61 -4
  30. package/mobile/lib/components/StickyBottomMenu/StickyBottomMenu.js.map +1 -1
  31. package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.d.ts +2 -1
  32. package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.js +1 -4
  33. package/mobile/lib/components/StickyBottomMenu/StickyBottomMenuItem.js.map +1 -1
  34. package/mobile/lib/data/StickyMobileData.d.ts +2 -2
  35. package/mobile/src/components/BenefitsBlock/BenefitsBlock.example.json +2 -0
  36. package/mobile/src/components/BonusBenefitsBlock/BonusBenefitsBlock.example.json +2 -0
  37. package/mobile/src/components/ContactsBlock/ContactsBlock.example.json +1 -0
  38. package/mobile/src/components/ErrorBlock/ErrorBlock.example.json +2 -0
  39. package/mobile/src/components/ImgBlock/ImgBlock.example.json +2 -0
  40. package/mobile/src/components/InsuranceAmountBlock/InsuranceAmountBlock.example.json +2 -0
  41. package/mobile/src/components/ProductBlock/ProductBlock.example.json +4 -7
  42. package/mobile/src/components/RichTextBlock/RichTextBlock.example.json +2 -0
  43. package/mobile/src/components/StepsBlock/StepsBlock.example.json +1 -0
  44. package/mobile/src/components/StickyBottomMenu/StickyBottomMenu.tsx +119 -11
  45. package/mobile/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
  46. package/mobile/src/components/TextBlock/TextBlock.example.json +2 -0
  47. package/mobile/src/components/UnitBlock/UnitBlock.example.json +2 -0
  48. package/mobile/src/data/StickyMobileData.ts +2 -2
  49. package/package.json +1 -1
  50. package/src/components/BenefitsBlock/BenefitsBlock.example.json +2 -0
  51. package/src/components/BonusBenefitsBlock/BonusBenefitsBlock.example.json +2 -0
  52. package/src/components/ContactsBlock/ContactsBlock.example.json +1 -0
  53. package/src/components/ErrorBlock/ErrorBlock.example.json +2 -0
  54. package/src/components/ImgBlock/ImgBlock.example.json +2 -0
  55. package/src/components/InsuranceAmountBlock/InsuranceAmountBlock.example.json +2 -0
  56. package/src/components/ProductBlock/ProductBlock.example.json +4 -7
  57. package/src/components/RichTextBlock/RichTextBlock.example.json +2 -0
  58. package/src/components/StepsBlock/StepsBlock.example.json +1 -0
  59. package/src/components/StickyBottomMenu/StickyBottomMenu.fixture.mobile.tsx +2 -0
  60. package/src/components/StickyBottomMenu/StickyBottomMenu.mobile.tsx +119 -11
  61. package/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
  62. package/src/components/TextBlock/TextBlock.example.json +2 -0
  63. package/src/components/UnitBlock/UnitBlock.example.json +2 -0
  64. 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,7 @@
1
1
  {
2
2
  "content": {
3
3
  "version": "primary",
4
+ "padding": "",
4
5
  "title": "Шаги",
5
6
  "description": "Описание",
6
7
  "showLines": true,
@@ -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 className="ml-auto container bg-white flex justify-center shadow-blue-gray">
27
- {leftItems.map(renderMenuItem(activeItem, close))}
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(renderMenuItem(activeItem, close))}
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
- (activeItem: StickyMenuItem, close: () => void) => (_: StickyMenuItem, i: number) =>
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={_.href || String(i)}
40
- isActive={_ === activeItem}
140
+ key={_.title || String(i)}
41
141
  item={_}
42
- onClick={close}
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
- <a
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={handleClick}
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
- </a>
30
+ </div>
36
31
  );
37
32
  },
38
33
  );
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "title": "Текстовый блок",
4
6
  "description": "Описание"
5
7
  }
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "prefix": "префикс",
4
6
  "unit": 1,
5
7
  "suffix": "суффикс"
@@ -6,8 +6,8 @@ import { type Picture } from '../model/Picture';
6
6
  export interface StickyMenuItem {
7
7
  /** @title Название */
8
8
  title?: string;
9
- /** @title Адрес */
10
- href?: string;
9
+ /** @title Html */
10
+ __html?: string;
11
11
  /** @title Иконка */
12
12
  icon?: Picture;
13
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redneckz/wildless-cms-uni-blocks",
3
- "version": "0.14.253",
3
+ "version": "0.14.255",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "ЦК",
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "title": "Преимущества",
4
6
  "benefitsBlockVersion": "primary",
5
7
  "benefitList": [
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "title": "Вы можете оплатить бонусными баллами",
4
6
  "subtitle": "Удобный каталог с большим ассортиментом товаров и сервисов",
5
7
  "columnsCount": "4",
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "content": {
3
3
  "version": "secondary",
4
+ "padding": "",
4
5
  "info": [
5
6
  [
6
7
  {
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "transparent",
4
+ "padding": "",
3
5
  "title": "Заголовок",
4
6
  "description": "Описание",
5
7
  "error": {
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "image": {
4
6
  "format": "webp",
5
7
  "size": {
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "title": "Заголовок",
4
6
  "insuranceTabs": [
5
7
  {
@@ -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,7 @@
1
1
  {
2
2
  "content": {
3
3
  "version": "primary",
4
+ "padding": "",
4
5
  "title": "Шаги",
5
6
  "description": "Описание",
6
7
  "showLines": true,
@@ -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 className="ml-auto container bg-white flex justify-center shadow-blue-gray">
27
- {leftItems.map(renderMenuItem(activeItem, close))}
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(renderMenuItem(activeItem, close))}
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
- (activeItem: StickyMenuItem, close: () => void) => (_: StickyMenuItem, i: number) =>
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={_.href || String(i)}
40
- isActive={_ === activeItem}
140
+ key={_.title || String(i)}
41
141
  item={_}
42
- onClick={close}
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
- <a
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={handleClick}
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
- </a>
30
+ </div>
36
31
  );
37
32
  },
38
33
  );
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "title": "Текстовый блок",
4
6
  "description": "Описание"
5
7
  }
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "content": {
3
+ "version": "primary",
4
+ "padding": "",
3
5
  "prefix": "префикс",
4
6
  "unit": 1,
5
7
  "suffix": "суффикс"
@@ -6,8 +6,8 @@ import { type Picture } from '../model/Picture';
6
6
  export interface StickyMenuItem {
7
7
  /** @title Название */
8
8
  title?: string;
9
- /** @title Адрес */
10
- href?: string;
9
+ /** @title Html */
10
+ __html?: string;
11
11
  /** @title Иконка */
12
12
  icon?: Picture;
13
13
  }