@redneckz/wildless-cms-uni-blocks 0.14.254 → 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 (42) 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/StickyBottomMenu/StickyBottomMenu.tsx +119 -11
  36. package/mobile/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
  37. package/mobile/src/data/StickyMobileData.ts +2 -2
  38. package/package.json +1 -1
  39. package/src/components/StickyBottomMenu/StickyBottomMenu.fixture.mobile.tsx +2 -0
  40. package/src/components/StickyBottomMenu/StickyBottomMenu.mobile.tsx +119 -11
  41. package/src/components/StickyBottomMenu/StickyBottomMenuItem.tsx +5 -10
  42. package/src/data/StickyMobileData.ts +2 -2
@@ -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
  );
@@ -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.254",
3
+ "version": "0.14.255",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "ЦК",
@@ -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
  );
@@ -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
  }