@gravity-ui/page-constructor 1.6.0 → 1.7.0-alpha.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.css +6 -1
  3. package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.js +26 -12
  4. package/build/cjs/components/RouterLink/RouterLink.d.ts +1 -0
  5. package/build/cjs/components/navigation/components/Header/Header.css +85 -0
  6. package/build/cjs/components/navigation/components/Header/Header.d.ts +28 -0
  7. package/build/cjs/components/navigation/components/Header/Header.js +81 -0
  8. package/build/cjs/components/navigation/components/Logo/Logo.css +18 -0
  9. package/build/cjs/components/navigation/components/Logo/Logo.d.ts +7 -0
  10. package/build/cjs/components/navigation/components/Logo/Logo.js +13 -0
  11. package/build/cjs/components/navigation/components/MobileNavigation/MobileNavigation.css +58 -0
  12. package/build/cjs/components/navigation/components/MobileNavigation/MobileNavigation.d.ts +13 -0
  13. package/build/cjs/components/navigation/components/MobileNavigation/MobileNavigation.js +45 -0
  14. package/build/cjs/components/navigation/components/Navigation/Navigation.css +43 -0
  15. package/build/cjs/components/navigation/components/Navigation/Navigation.d.ts +11 -0
  16. package/build/cjs/components/navigation/components/Navigation/Navigation.js +70 -0
  17. package/build/cjs/components/navigation/components/NavigationItem/NavigationItem.css +40 -0
  18. package/build/cjs/components/navigation/components/NavigationItem/NavigationItem.d.ts +12 -0
  19. package/build/cjs/components/navigation/components/NavigationItem/NavigationItem.js +47 -0
  20. package/build/cjs/components/navigation/components/NavigationPopup/NavigationPopup.css +33 -0
  21. package/build/cjs/components/navigation/components/NavigationPopup/NavigationPopup.d.ts +24 -0
  22. package/build/cjs/components/navigation/components/NavigationPopup/NavigationPopup.js +57 -0
  23. package/build/cjs/components/navigation/components/SocialIcon/SocialIcon.css +20 -0
  24. package/build/cjs/components/navigation/components/SocialIcon/SocialIcon.d.ts +7 -0
  25. package/build/cjs/components/navigation/components/SocialIcon/SocialIcon.js +10 -0
  26. package/build/cjs/containers/PageConstructor/PageConstructor.d.ts +2 -0
  27. package/build/cjs/containers/PageConstructor/PageConstructor.js +4 -2
  28. package/build/cjs/context/locationContext/locationContext.d.ts +1 -0
  29. package/build/cjs/icons/NavigationArrow.d.ts +2 -0
  30. package/build/cjs/icons/NavigationArrow.js +9 -0
  31. package/build/cjs/icons/NavigationClose.d.ts +2 -0
  32. package/build/cjs/icons/NavigationClose.js +9 -0
  33. package/build/cjs/icons/NavigationOpen.d.ts +2 -0
  34. package/build/cjs/icons/NavigationOpen.js +11 -0
  35. package/build/cjs/icons/index.d.ts +3 -0
  36. package/build/cjs/icons/index.js +3 -0
  37. package/build/cjs/models/constructor-items/blocks.d.ts +3 -1
  38. package/build/cjs/models/navigation.d.ts +59 -0
  39. package/build/cjs/models/navigation.js +10 -0
  40. package/build/cjs/text-transform/blocks.js +6 -1
  41. package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.css +6 -1
  42. package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.js +28 -14
  43. package/build/esm/components/RouterLink/RouterLink.d.ts +1 -0
  44. package/build/esm/components/navigation/components/Header/Header.css +85 -0
  45. package/build/esm/components/navigation/components/Header/Header.d.ts +29 -0
  46. package/build/esm/components/navigation/components/Header/Header.js +79 -0
  47. package/build/esm/components/navigation/components/Logo/Logo.css +18 -0
  48. package/build/esm/components/navigation/components/Logo/Logo.d.ts +8 -0
  49. package/build/esm/components/navigation/components/Logo/Logo.js +11 -0
  50. package/build/esm/components/navigation/components/MobileNavigation/MobileNavigation.css +58 -0
  51. package/build/esm/components/navigation/components/MobileNavigation/MobileNavigation.d.ts +14 -0
  52. package/build/esm/components/navigation/components/MobileNavigation/MobileNavigation.js +43 -0
  53. package/build/esm/components/navigation/components/Navigation/Navigation.css +43 -0
  54. package/build/esm/components/navigation/components/Navigation/Navigation.d.ts +12 -0
  55. package/build/esm/components/navigation/components/Navigation/Navigation.js +69 -0
  56. package/build/esm/components/navigation/components/NavigationItem/NavigationItem.css +40 -0
  57. package/build/esm/components/navigation/components/NavigationItem/NavigationItem.d.ts +13 -0
  58. package/build/esm/components/navigation/components/NavigationItem/NavigationItem.js +46 -0
  59. package/build/esm/components/navigation/components/NavigationPopup/NavigationPopup.css +33 -0
  60. package/build/esm/components/navigation/components/NavigationPopup/NavigationPopup.d.ts +25 -0
  61. package/build/esm/components/navigation/components/NavigationPopup/NavigationPopup.js +54 -0
  62. package/build/esm/components/navigation/components/SocialIcon/SocialIcon.css +20 -0
  63. package/build/esm/components/navigation/components/SocialIcon/SocialIcon.d.ts +8 -0
  64. package/build/esm/components/navigation/components/SocialIcon/SocialIcon.js +8 -0
  65. package/build/esm/containers/PageConstructor/PageConstructor.d.ts +2 -0
  66. package/build/esm/containers/PageConstructor/PageConstructor.js +4 -2
  67. package/build/esm/context/locationContext/locationContext.d.ts +1 -0
  68. package/build/esm/icons/NavigationArrow.d.ts +2 -0
  69. package/build/esm/icons/NavigationArrow.js +4 -0
  70. package/build/esm/icons/NavigationClose.d.ts +2 -0
  71. package/build/esm/icons/NavigationClose.js +4 -0
  72. package/build/esm/icons/NavigationOpen.d.ts +2 -0
  73. package/build/esm/icons/NavigationOpen.js +6 -0
  74. package/build/esm/icons/index.d.ts +3 -0
  75. package/build/esm/icons/index.js +3 -0
  76. package/build/esm/models/constructor-items/blocks.d.ts +3 -1
  77. package/build/esm/models/navigation.d.ts +59 -0
  78. package/build/esm/models/navigation.js +7 -0
  79. package/build/esm/text-transform/blocks.js +6 -1
  80. package/package.json +4 -1
  81. package/server/models/constructor-items/blocks.d.ts +3 -1
  82. package/server/text-transform/blocks.js +6 -1
  83. package/styles/mixins.scss +38 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0](https://github.com/gravity-ui/page-constructor/compare/v1.6.1...v1.7.0) (2022-11-10)
4
+
5
+
6
+ ### Features
7
+
8
+ * **ExtendedFeatures:** add content ([#51](https://github.com/gravity-ui/page-constructor/issues/51)) ([0990563](https://github.com/gravity-ui/page-constructor/commit/0990563a62c3f8f4d4cfb206cedb7a1205cb1797))
9
+
10
+ ## [1.6.1](https://github.com/gravity-ui/page-constructor/compare/v1.4.1...v1.6.1) (2022-11-10)
11
+
12
+ ### Bug Fixes
13
+
14
+ * fix storybook's content
15
+
16
+
3
17
  ## [1.6.0](https://github.com/gravity-ui/page-constructor/pulls?q=is%3Apr+is%3Aclosed) (2022-11-09)
4
18
 
5
19
  ### Features
@@ -12,6 +12,8 @@ unpredictable css rules order in build */
12
12
  }
13
13
  .pc-ExtendedFeaturesBlock__item {
14
14
  margin-top: 32px;
15
+ }
16
+ .pc-ExtendedFeaturesBlock__item.col {
15
17
  padding-right: 32px;
16
18
  }
17
19
  .pc-ExtendedFeaturesBlock__item-title {
@@ -74,12 +76,15 @@ unpredictable css rules order in build */
74
76
  height: 32px;
75
77
  background-size: cover;
76
78
  display: block;
77
- margin-bottom: 8px;
79
+ margin-bottom: 12px;
78
80
  }
79
81
  @media (max-width: 577px) {
80
82
  .pc-ExtendedFeaturesBlock__item {
81
83
  margin-top: 32px;
82
84
  }
85
+ .pc-ExtendedFeaturesBlock__item.col {
86
+ padding-right: 8px;
87
+ }
83
88
  }
84
89
  @media (min-width: 769px) {
85
90
  .pc-ExtendedFeaturesBlock.pc-AnimateBlock .pc-ExtendedFeaturesBlock__item, .pc-AnimateBlock .pc-ExtendedFeaturesBlock .pc-ExtendedFeaturesBlock__item {
@@ -2,26 +2,40 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ExtendedFeaturesBlock = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const react_1 = (0, tslib_1.__importDefault)(require("react"));
5
+ const react_1 = (0, tslib_1.__importStar)(require("react"));
6
6
  const utils_1 = require("../../utils");
7
7
  const grid_1 = require("../../grid");
8
8
  const components_1 = require("../../components/");
9
+ const sub_blocks_1 = require("../../sub-blocks");
10
+ const Image_1 = (0, tslib_1.__importDefault)(require("../../components/Image/Image"));
11
+ const ThemeValueContext_1 = require("../../context/theme/ThemeValueContext");
12
+ const utils_2 = require("../../components/Media/Image/utils");
9
13
  const b = (0, utils_1.block)('ExtendedFeaturesBlock');
10
14
  const DEFAULT_SIZES = {
11
15
  all: 12,
12
16
  sm: 6,
13
17
  md: 4,
14
18
  };
15
- const ExtendedFeaturesBlock = ({ title, description, items, colSizes = DEFAULT_SIZES, animated, }) => (react_1.default.createElement(components_1.AnimateBlock, { className: b(), animate: animated },
16
- react_1.default.createElement(components_1.BlockHeader, { title: title, description: description, className: b('header') }),
17
- react_1.default.createElement("div", { className: b('items') },
18
- react_1.default.createElement(grid_1.Row, null, items.map(({ title: itemTitle, text, link, label, icon }) => (react_1.default.createElement(grid_1.Col, { className: b('item'), key: text || itemTitle, sizes: colSizes },
19
- icon && react_1.default.createElement("img", { src: icon, className: b('icon') }),
20
- itemTitle && (react_1.default.createElement("h5", { className: b('item-title', { 'has-label': Boolean(label) }) },
21
- react_1.default.createElement(components_1.HTML, null, itemTitle),
22
- label && react_1.default.createElement("div", { className: b('item-label') }, label))),
23
- text && (react_1.default.createElement("div", { className: b('item-text') },
24
- react_1.default.createElement(components_1.HTML, null, text))),
25
- link && react_1.default.createElement(components_1.Link, Object.assign({ className: b('item-link') }, link)))))))));
19
+ const ExtendedFeaturesBlock = ({ title, description, items, colSizes = DEFAULT_SIZES, animated, }) => {
20
+ const { themeValue: theme } = (0, react_1.useContext)(ThemeValueContext_1.ThemeValueContext);
21
+ return (react_1.default.createElement(components_1.AnimateBlock, { className: b(), animate: animated },
22
+ react_1.default.createElement(components_1.BlockHeader, { title: title, description: description, className: b('header') }),
23
+ react_1.default.createElement("div", { className: b('items') },
24
+ react_1.default.createElement(grid_1.Row, null, items.map(({ title: itemTitle, text, link, links, label, icon }) => {
25
+ const itemLinks = links || [];
26
+ const iconThemed = icon && (0, utils_1.getThemedValue)(icon, theme);
27
+ const iconData = iconThemed && (0, utils_2.getMediaImage)(iconThemed);
28
+ if (link) {
29
+ itemLinks.push(link);
30
+ }
31
+ return (react_1.default.createElement(grid_1.Col, { className: b('item'), key: text || itemTitle, sizes: colSizes },
32
+ iconData && react_1.default.createElement(Image_1.default, Object.assign({}, iconData, { className: b('icon') })),
33
+ react_1.default.createElement("div", { className: b('container') },
34
+ itemTitle && (react_1.default.createElement("h5", { className: b('item-title') },
35
+ react_1.default.createElement(components_1.HTML, null, itemTitle),
36
+ label && (react_1.default.createElement("div", { className: b('item-label') }, label)))),
37
+ react_1.default.createElement(sub_blocks_1.Content, { text: text, links: itemLinks, size: "s", colSizes: { all: 12, md: 12 } }))));
38
+ })))));
39
+ };
26
40
  exports.ExtendedFeaturesBlock = ExtendedFeaturesBlock;
27
41
  exports.default = exports.ExtendedFeaturesBlock;
@@ -1,6 +1,7 @@
1
1
  import { WithChildren } from '../../models';
2
2
  export interface RouterLinkProps {
3
3
  href: string;
4
+ [key: string]: any;
4
5
  }
5
6
  declare const RouterLink: ({ href, children }: WithChildren<RouterLinkProps>) => JSX.Element;
6
7
  export default RouterLink;
@@ -0,0 +1,85 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .header {
4
+ position: sticky;
5
+ z-index: 98;
6
+ top: 0;
7
+ display: flex;
8
+ justify-content: center;
9
+ align-items: center;
10
+ height: var(--header-height);
11
+ background-color: var(--yc-color-base-background);
12
+ box-shadow: inset 0px -1px 0px var(--yc-color-line-generic);
13
+ }
14
+ .header__wrapper {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ height: var(--header-height);
19
+ }
20
+ @media (min-width: 769px) {
21
+ .header__mobile-menu-button {
22
+ display: none;
23
+ }
24
+ }
25
+ .header__navigation, .header__left, .header__right {
26
+ display: flex;
27
+ align-items: center;
28
+ }
29
+ .header__navigation {
30
+ position: relative;
31
+ flex: 1 0 0;
32
+ justify-content: flex-start;
33
+ margin-right: 20px;
34
+ }
35
+ @media (max-width: 768px) {
36
+ .header__navigation {
37
+ display: none;
38
+ }
39
+ }
40
+ .header__right {
41
+ flex: 0;
42
+ justify-content: flex-end;
43
+ }
44
+ .header__navigation-container {
45
+ display: flex;
46
+ overflow-x: hidden;
47
+ flex: 1 0 0;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ margin-right: 20px;
51
+ }
52
+ .header__buttons {
53
+ display: flex;
54
+ }
55
+ @media (max-width: 768px) {
56
+ .header__buttons {
57
+ display: none;
58
+ }
59
+ }
60
+ .header__buttons > *:not(:last-child) {
61
+ margin-right: 16px;
62
+ }
63
+ .header__button {
64
+ margin-top: 0;
65
+ }
66
+ .header__logo {
67
+ margin: 0 32px 0 0;
68
+ cursor: pointer;
69
+ }
70
+ @media (max-width: 768px) {
71
+ .header__navigation-container {
72
+ justify-content: flex-end;
73
+ }
74
+ .header__left {
75
+ flex: 1 0 0;
76
+ }
77
+ }
78
+ @media (max-width: 576px) {
79
+ .header__navigation-container {
80
+ margin-right: 12px;
81
+ }
82
+ .header__logo {
83
+ margin-right: 0;
84
+ }
85
+ }
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { HeaderData, NavigationLogo } from '../../../../models/navigation';
3
+ export interface HeaderProps {
4
+ logo: NavigationLogo;
5
+ data: HeaderData;
6
+ }
7
+ interface HeaderState {
8
+ isSidebarOpened: boolean;
9
+ activeItemIndex: number;
10
+ }
11
+ declare class Header extends React.Component<HeaderProps, HeaderState> {
12
+ ref: React.RefObject<unknown>;
13
+ state: {
14
+ isSidebarOpened: boolean;
15
+ activeItemIndex: number;
16
+ };
17
+ render(): JSX.Element;
18
+ private renderLeft;
19
+ private renderLogo;
20
+ private renderRight;
21
+ private renderRightItems;
22
+ private renderMobileMenuButton;
23
+ private renderMobileNavigation;
24
+ private onActiveItemChange;
25
+ private onSidebarOpenedChange;
26
+ private hideSidebar;
27
+ }
28
+ export default Header;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = (0, tslib_1.__importStar)(require("react"));
5
+ const bem_cn_lite_1 = (0, tslib_1.__importDefault)(require("bem-cn-lite"));
6
+ const grid_1 = require("../../../../grid");
7
+ const OutsideClick_1 = (0, tslib_1.__importDefault)(require("../../../OutsideClick/OutsideClick"));
8
+ const Control_1 = (0, tslib_1.__importDefault)(require("../../../Control/Control"));
9
+ const Logo_1 = (0, tslib_1.__importDefault)(require("../Logo/Logo"));
10
+ const Navigation_1 = (0, tslib_1.__importDefault)(require("../Navigation/Navigation"));
11
+ const MobileNavigation_1 = (0, tslib_1.__importDefault)(require("../MobileNavigation/MobileNavigation"));
12
+ const NavigationItem_1 = (0, tslib_1.__importDefault)(require("../NavigationItem/NavigationItem"));
13
+ const icons_1 = require("../../../../icons");
14
+ const b = (0, bem_cn_lite_1.default)('header');
15
+ class Header extends react_1.default.Component {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.ref = (0, react_1.createRef)();
19
+ this.state = {
20
+ isSidebarOpened: false,
21
+ activeItemIndex: -1,
22
+ };
23
+ this.onActiveItemChange = (index) => {
24
+ this.setState({ activeItemIndex: index });
25
+ };
26
+ this.onSidebarOpenedChange = (isSidebarOpened) => {
27
+ this.setState({ isSidebarOpened });
28
+ };
29
+ this.hideSidebar = () => {
30
+ this.setState({ isSidebarOpened: false });
31
+ };
32
+ }
33
+ render() {
34
+ return (react_1.default.createElement(grid_1.Grid, { className: b() },
35
+ react_1.default.createElement(grid_1.Row, null,
36
+ react_1.default.createElement(grid_1.Col, null,
37
+ react_1.default.createElement("header", { className: b('wrapper') },
38
+ this.renderLogo(),
39
+ this.renderLeft(),
40
+ this.renderRight(),
41
+ this.renderMobileNavigation())))));
42
+ }
43
+ renderLeft() {
44
+ const { activeItemIndex } = this.state;
45
+ const { leftItems } = this.props.data;
46
+ return (leftItems && (react_1.default.createElement("div", { className: b('navigation-container') },
47
+ react_1.default.createElement(Navigation_1.default, { className: b('navigation'), links: leftItems, activeItemIndex: activeItemIndex, onActiveItemChange: this.onActiveItemChange }))));
48
+ }
49
+ renderLogo() {
50
+ const { logo } = this.props;
51
+ if (!logo) {
52
+ return null;
53
+ }
54
+ return (react_1.default.createElement("div", { className: b('left') },
55
+ react_1.default.createElement(Logo_1.default, Object.assign({}, logo, { className: b('logo') }))));
56
+ }
57
+ renderRight() {
58
+ return (react_1.default.createElement("div", { className: b('right') },
59
+ this.renderMobileMenuButton(),
60
+ this.renderRightItems()));
61
+ }
62
+ renderRightItems() {
63
+ const { rightItems } = this.props.data;
64
+ return (rightItems && (react_1.default.createElement("div", { className: b('buttons') }, rightItems.map((button) => (react_1.default.createElement(NavigationItem_1.default, { key: button.text, data: button, className: b('button') }))))));
65
+ }
66
+ renderMobileMenuButton() {
67
+ const { isSidebarOpened } = this.state;
68
+ const iconProps = { icon: isSidebarOpened ? icons_1.NavigationClose : icons_1.NavigationOpen, iconSize: 36 };
69
+ return (react_1.default.createElement(Control_1.default, Object.assign({ className: b('mobile-menu-button'), onClick: (e) => {
70
+ e.stopPropagation();
71
+ this.onSidebarOpenedChange(!isSidebarOpened);
72
+ }, size: "l" }, iconProps)));
73
+ }
74
+ renderMobileNavigation() {
75
+ const { leftItems, rightItems } = this.props.data;
76
+ const { isSidebarOpened, activeItemIndex } = this.state;
77
+ return (react_1.default.createElement(OutsideClick_1.default, { onOutsideClick: () => this.onSidebarOpenedChange(false) },
78
+ react_1.default.createElement(MobileNavigation_1.default, { topItems: leftItems, bottomItems: rightItems, isOpened: isSidebarOpened, activeItemIndex: activeItemIndex, onActiveItemChange: this.onActiveItemChange, onClose: this.hideSidebar })));
79
+ }
80
+ }
81
+ exports.default = Header;
@@ -0,0 +1,18 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .logo {
4
+ display: flex;
5
+ align-items: center;
6
+ font-weight: 500;
7
+ font-size: var(--yc-text-header-2-font-size);
8
+ line-height: var(--yc-text-header-2-line-height);
9
+ }
10
+ .logo__icon {
11
+ width: 178px;
12
+ height: 36px;
13
+ margin-right: 8px;
14
+ object-fit: contain;
15
+ }
16
+ .logo__text {
17
+ white-space: nowrap;
18
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { NavigationLogo } from '../../../../models/navigation';
3
+ export interface LogoProps extends NavigationLogo {
4
+ className?: string;
5
+ }
6
+ declare const Logo: React.FC<LogoProps>;
7
+ export default Logo;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = (0, tslib_1.__importDefault)(require("react"));
5
+ const bem_cn_lite_1 = (0, tslib_1.__importDefault)(require("bem-cn-lite"));
6
+ const index_1 = require("../../../index");
7
+ const RouterLink_1 = (0, tslib_1.__importDefault)(require("../../../RouterLink/RouterLink"));
8
+ const b = (0, bem_cn_lite_1.default)('logo');
9
+ const Logo = ({ icon, text, className }) => (react_1.default.createElement(RouterLink_1.default, { href: "/", passHref: true },
10
+ react_1.default.createElement("div", { className: b(null, className) },
11
+ icon && react_1.default.createElement(index_1.Image, { className: b('icon'), src: icon }),
12
+ react_1.default.createElement("span", { className: b('text') }, text))));
13
+ exports.default = Logo;
@@ -0,0 +1,58 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .mobile-navigation {
4
+ position: fixed;
5
+ z-index: 100;
6
+ top: var(--header-height);
7
+ left: 0;
8
+ width: 100%;
9
+ border-bottom-right-radius: var(--pc-border-radius);
10
+ border-bottom-left-radius: var(--pc-border-radius);
11
+ background-color: var(--yc-color-base-background);
12
+ box-shadow: 0px 3px 10px var(--yc-color-sfx-shadow);
13
+ font-size: var(--yc-text-body-2-font-size);
14
+ line-height: var(--yc-text-body-2-line-height);
15
+ }
16
+ @media (min-width: 769px) {
17
+ .mobile-navigation {
18
+ display: none;
19
+ }
20
+ }
21
+ .mobile-navigation__wrapper {
22
+ padding: 32px 20px;
23
+ }
24
+ .mobile-navigation__button {
25
+ margin-top: 24px;
26
+ }
27
+ .mobile-navigation__links {
28
+ position: relative;
29
+ display: flex;
30
+ flex-direction: column;
31
+ padding-bottom: 24px;
32
+ margin: 0;
33
+ padding: 0;
34
+ list-style: none;
35
+ }
36
+ .mobile-navigation__links-item:not(:last-child) {
37
+ margin-bottom: 24px;
38
+ }
39
+ .mobile-navigation__dropdown-item:not(:last-child) {
40
+ margin-bottom: 16px;
41
+ }
42
+ .mobile-navigation__popup {
43
+ z-index: 101;
44
+ display: flex;
45
+ flex-direction: column;
46
+ min-width: 220px;
47
+ padding: 16px;
48
+ border: 1px solid var(--yc-color-line-generic);
49
+ border-top-width: 0;
50
+ border-radius: calc(var(--pc-border-radius) / 2);
51
+ background: var(--yc-color-base-float);
52
+ box-shadow: 0 3px 10px var(--yc-color-sfx-shadow);
53
+ }
54
+ @media (min-width: 769px) {
55
+ .mobile-navigation__popup {
56
+ display: none;
57
+ }
58
+ }
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { NavigationItem as NavigationItemModel } from '../../../../models/navigation';
3
+ export interface MobileNavigationProps {
4
+ className?: string;
5
+ isOpened?: boolean;
6
+ topItems?: NavigationItemModel[];
7
+ bottomItems?: NavigationItemModel[];
8
+ activeItemIndex: number;
9
+ onClose: () => void;
10
+ onActiveItemChange: (index: number) => void;
11
+ }
12
+ declare const MobileNavigation: React.FC<MobileNavigationProps>;
13
+ export default MobileNavigation;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const bem_cn_lite_1 = (0, tslib_1.__importDefault)(require("bem-cn-lite"));
5
+ const react_1 = (0, tslib_1.__importStar)(require("react"));
6
+ const Foldable_1 = (0, tslib_1.__importDefault)(require("../../../Foldable/Foldable"));
7
+ const uikit_1 = require("@gravity-ui/uikit");
8
+ const navigation_1 = require("../../../../models/navigation");
9
+ const NavigationItem_1 = (0, tslib_1.__importDefault)(require("../NavigationItem/NavigationItem"));
10
+ const b = (0, bem_cn_lite_1.default)('mobile-navigation');
11
+ const MobileNavigationDropdown = ({ data, onItemClick, onToggle, isOpened = false, }) => {
12
+ const ref = (0, react_1.useRef)(null);
13
+ return (react_1.default.createElement("div", { ref: ref, className: b('dropdown') },
14
+ react_1.default.createElement(NavigationItem_1.default, { data: data, onClick: onToggle, isOpened: isOpened }),
15
+ isOpened && (react_1.default.createElement(uikit_1.Popup, { anchorRef: ref, open: isOpened, className: b('popup') }, data.items.map((item) => (react_1.default.createElement(NavigationItem_1.default, { key: item.text, data: item, className: b('dropdown-item'), onClick: onItemClick })))))));
16
+ };
17
+ const MobileNavigationItem = ({ link, index, isActive, onActiveItemChange, onClose, }) => {
18
+ const toggleActive = (0, react_1.useCallback)((e) => {
19
+ e.stopPropagation();
20
+ if (onActiveItemChange) {
21
+ onActiveItemChange(isActive ? -1 : index);
22
+ }
23
+ }, [isActive, index, onActiveItemChange]);
24
+ const onItemClick = (0, react_1.useCallback)((e) => {
25
+ toggleActive(e);
26
+ onClose();
27
+ }, [toggleActive, onClose]);
28
+ return (react_1.default.createElement("li", { key: index, className: b('links-item') }, link.type === navigation_1.NavigationItemType.Dropdown ? (react_1.default.createElement(MobileNavigationDropdown, { data: link, onToggle: toggleActive, isOpened: isActive, onItemClick: onItemClick })) : (react_1.default.createElement(NavigationItem_1.default, { data: link, onClick: onItemClick }))));
29
+ };
30
+ const MobileNavigation = (props) => {
31
+ if (typeof window === 'undefined') {
32
+ return null;
33
+ }
34
+ const { isOpened, topItems, bottomItems, activeItemIndex, onActiveItemChange, onClose } = props;
35
+ return (react_1.default.createElement(uikit_1.Portal, null,
36
+ react_1.default.createElement(Foldable_1.default, { key: topItems === null || topItems === void 0 ? void 0 : topItems.length, className: b(), isOpened: Boolean(isOpened) },
37
+ react_1.default.createElement("div", { className: b('wrapper') },
38
+ react_1.default.createElement("nav", null,
39
+ react_1.default.createElement("ul", { className: b('links') }, topItems === null || topItems === void 0 ? void 0 : topItems.map((link, index) => {
40
+ const isActive = index === activeItemIndex;
41
+ return (react_1.default.createElement(MobileNavigationItem, { key: index, link: link, index: index, isActive: isOpened && isActive, onClose: onClose, onActiveItemChange: onActiveItemChange }));
42
+ }))), bottomItems === null || bottomItems === void 0 ? void 0 :
43
+ bottomItems.map((item) => (react_1.default.createElement(NavigationItem_1.default, { key: item.text, data: item, className: b('button') })))))));
44
+ };
45
+ exports.default = MobileNavigation;
@@ -0,0 +1,43 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .navigation {
4
+ font-size: var(--yc-text-body-2-font-size);
5
+ line-height: var(--yc-text-body-2-line-height);
6
+ }
7
+ .navigation__links {
8
+ position: relative;
9
+ display: flex;
10
+ align-items: center;
11
+ margin: 0;
12
+ padding: 0;
13
+ list-style: none;
14
+ }
15
+ .navigation__links-item {
16
+ position: relative;
17
+ height: var(--header-height);
18
+ line-height: var(--header-height);
19
+ cursor: pointer;
20
+ outline: none;
21
+ color: inherit;
22
+ text-decoration: none;
23
+ }
24
+ .utilityfocus .navigation__links-item:focus {
25
+ outline: 2px solid #ffdb4d;
26
+ }
27
+ .navigation__links-item:hover, .navigation__links-item:active {
28
+ color: var(--yc-color-text-link);
29
+ }
30
+ .navigation__links-item:not(:last-child) {
31
+ margin-right: 20px;
32
+ }
33
+ .navigation__slider-container {
34
+ position: absolute;
35
+ right: 0;
36
+ bottom: 0;
37
+ left: 0;
38
+ }
39
+ .navigation__slider {
40
+ width: 100%;
41
+ height: 2px;
42
+ background-color: var(--yc-color-text-link);
43
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { NavigationItem as NavigationItemModel } from '../../../../models/navigation';
3
+ export interface NavigationProps {
4
+ links: NavigationItemModel[];
5
+ activeItemIndex: number;
6
+ onActiveItemChange: (index: number) => void;
7
+ className?: string;
8
+ highlightActiveItem?: boolean;
9
+ }
10
+ declare const Navigation: React.FC<NavigationProps>;
11
+ export default Navigation;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const lodash_1 = (0, tslib_1.__importDefault)(require("lodash"));
5
+ const bem_cn_lite_1 = (0, tslib_1.__importDefault)(require("bem-cn-lite"));
6
+ const react_1 = (0, tslib_1.__importStar)(require("react"));
7
+ const OverflowScroller_1 = (0, tslib_1.__importDefault)(require("../../../OverflowScroller/OverflowScroller"));
8
+ const navigation_1 = require("../../../../models/navigation");
9
+ const NavigationPopup_1 = (0, tslib_1.__importDefault)(require("../NavigationPopup/NavigationPopup"));
10
+ const NavigationItem_1 = (0, tslib_1.__importDefault)(require("../NavigationItem/NavigationItem"));
11
+ const locationContext_1 = require("../../../../context/locationContext");
12
+ const b = (0, bem_cn_lite_1.default)('navigation');
13
+ const Navigation = ({ className, onActiveItemChange, links, activeItemIndex, highlightActiveItem, }) => {
14
+ const { asPath, pathname } = (0, react_1.useContext)(locationContext_1.LocationContext);
15
+ const itemRefs = (0, react_1.useRef)([]);
16
+ const [itemPositions, setItemPosition] = (0, react_1.useState)([]);
17
+ const [lastLeftScroll, setLastLeftScroll] = (0, react_1.useState)(0);
18
+ const hidePopup = (0, react_1.useCallback)(() => {
19
+ onActiveItemChange(-1);
20
+ }, [onActiveItemChange]);
21
+ const getItemClickHandler = (0, react_1.useCallback)((index) => (e) => {
22
+ e.stopPropagation();
23
+ onActiveItemChange(index === activeItemIndex ? -1 : index);
24
+ }, [activeItemIndex, onActiveItemChange]);
25
+ const renderNavDropdown = (data, onClick, isActive, position) => {
26
+ const { text, items } = data, popupProps = (0, tslib_1.__rest)(data, ["text", "items"]);
27
+ return (react_1.default.createElement(react_1.Fragment, null,
28
+ react_1.default.createElement(NavigationItem_1.default, { className: b('link'), onClick: onClick, isOpened: isActive, data: { text, type: navigation_1.NavigationItemType.Dropdown } }),
29
+ isActive && (react_1.default.createElement(NavigationPopup_1.default, Object.assign({ left: position, onClose: hidePopup, items: items }, popupProps)))));
30
+ };
31
+ const slider = (react_1.default.createElement("div", { className: b('slider-container') },
32
+ react_1.default.createElement("div", { className: b('slider') })));
33
+ const content = (react_1.default.createElement("nav", null,
34
+ react_1.default.createElement("ul", { className: b('links') }, links.map((link, index) => {
35
+ const isActive = index === activeItemIndex;
36
+ const onClick = getItemClickHandler(index);
37
+ return (react_1.default.createElement("li", { ref: (el) => itemRefs.current.push(el), key: index, className: b('links-item') },
38
+ link.type === navigation_1.NavigationItemType.Dropdown ? (renderNavDropdown(link, onClick, isActive, itemPositions[index])) : (react_1.default.createElement(NavigationItem_1.default, { data: link, onClick: onClick })),
39
+ highlightActiveItem && isActive && slider));
40
+ }))));
41
+ const calculateItemPositions = (0, react_1.useCallback)(() => {
42
+ if (itemRefs.current.length) {
43
+ const currentItemPositions = itemRefs.current.map((itemRef) => (itemRef && itemRef.getBoundingClientRect().left) || 0);
44
+ setItemPosition(currentItemPositions);
45
+ }
46
+ }, []);
47
+ (0, react_1.useEffect)(() => {
48
+ const debouncedCalculateItemPositions = lodash_1.default.debounce(calculateItemPositions, 100);
49
+ const calculateOnScroll = lodash_1.default.debounce(() => {
50
+ const curLeftScroll = window.pageXOffset;
51
+ if (curLeftScroll !== lastLeftScroll) {
52
+ setLastLeftScroll(window.pageXOffset);
53
+ calculateItemPositions();
54
+ }
55
+ }, 100);
56
+ calculateItemPositions();
57
+ setLastLeftScroll(window.pageXOffset);
58
+ window.addEventListener('resize', debouncedCalculateItemPositions);
59
+ window.addEventListener('scroll', calculateOnScroll);
60
+ return () => {
61
+ window.removeEventListener(`resize`, calculateItemPositions);
62
+ window.removeEventListener('scroll', calculateOnScroll);
63
+ };
64
+ }, [calculateItemPositions, itemRefs, lastLeftScroll]);
65
+ (0, react_1.useEffect)(() => {
66
+ hidePopup();
67
+ }, [hidePopup, asPath, pathname]);
68
+ return (react_1.default.createElement(OverflowScroller_1.default, { className: b(null, className), onScrollStart: hidePopup, onScrollEnd: calculateItemPositions }, content));
69
+ };
70
+ exports.default = Navigation;
@@ -0,0 +1,40 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .navigation-item {
4
+ position: relative;
5
+ display: flex;
6
+ align-items: center;
7
+ }
8
+ .navigation-item_type_link {
9
+ color: var(--yc-color-text-primary);
10
+ color: inherit;
11
+ text-decoration: none;
12
+ outline: none;
13
+ }
14
+ .utilityfocus .navigation-item_type_link:focus {
15
+ outline: 2px solid #ffdb4d;
16
+ }
17
+ .navigation-item_type_link:hover, .navigation-item_type_link_active {
18
+ color: var(--yc-color-text-link);
19
+ }
20
+ .navigation-item_type_button {
21
+ display: inline-block;
22
+ }
23
+ .navigation-item__arrow {
24
+ position: relative;
25
+ top: -2px;
26
+ width: 9px;
27
+ height: 9px;
28
+ margin-left: 5px;
29
+ }
30
+ .navigation-item__icon {
31
+ width: 20px;
32
+ height: 20px;
33
+ margin-right: 8px;
34
+ border-radius: 50%;
35
+ object-fit: cover;
36
+ }
37
+ .navigation-item__dropdown {
38
+ margin-left: 7px;
39
+ color: var(--yc-color-text-secondary);
40
+ }
@@ -0,0 +1,12 @@
1
+ import React, { MouseEventHandler } from 'react';
2
+ import { NavigationButtonItem, NavigationDropdownItem, NavigationSocialItem, NavigationLinkItem } from '../../../../models/navigation';
3
+ declare type DropdownItemData = Omit<NavigationDropdownItem, 'items'>;
4
+ export declare type NavigationItemData = NavigationLinkItem | NavigationButtonItem | NavigationSocialItem | DropdownItemData;
5
+ export interface NavigationItemProps {
6
+ data: NavigationItemData;
7
+ className?: string;
8
+ onClick?: MouseEventHandler;
9
+ isOpened?: boolean;
10
+ }
11
+ declare const NavigationItem: React.FC<NavigationItemProps>;
12
+ export default NavigationItem;