@gravity-ui/page-constructor 2.0.0-beta.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.css +4 -4
  3. package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.js +1 -1
  4. package/build/cjs/blocks/Map/schema.d.ts +0 -12
  5. package/build/cjs/components/HTML/HTML.d.ts +1 -1
  6. package/build/cjs/components/Map/GoogleMap.js +7 -5
  7. package/build/cjs/components/Map/Map.css +5 -0
  8. package/build/cjs/components/Map/YMap/YMap.d.ts +4 -2
  9. package/build/cjs/components/Map/YMap/YMap.js +18 -10
  10. package/build/cjs/components/Map/YMap/YandexMap.js +18 -9
  11. package/build/cjs/models/constructor-items/common.d.ts +0 -2
  12. package/build/cjs/navigation/components/Header/Header.css +23 -0
  13. package/build/cjs/navigation/components/Header/Header.js +12 -8
  14. package/build/cjs/navigation/components/MobileNavigation/MobileNavigation.css +5 -2
  15. package/build/cjs/navigation/components/MobileNavigation/MobileNavigation.d.ts +2 -2
  16. package/build/cjs/navigation/components/MobileNavigation/MobileNavigation.js +11 -11
  17. package/build/cjs/navigation/components/Navigation/Navigation.css +0 -11
  18. package/build/cjs/navigation/components/Navigation/Navigation.d.ts +4 -11
  19. package/build/cjs/navigation/components/Navigation/Navigation.js +5 -23
  20. package/build/cjs/navigation/components/NavigationDropdownItem/NavigationDropdownItem.d.ts +11 -0
  21. package/build/cjs/navigation/components/NavigationDropdownItem/NavigationDropdownItem.js +14 -0
  22. package/build/cjs/navigation/components/NavigationListItem/NavigationListItem.css +11 -0
  23. package/build/cjs/navigation/components/NavigationListItem/NavigationListItem.d.ts +16 -0
  24. package/build/cjs/navigation/components/NavigationListItem/NavigationListItem.js +28 -0
  25. package/build/cjs/navigation/constants.d.ts +6 -0
  26. package/build/cjs/navigation/constants.js +10 -0
  27. package/build/cjs/navigation/utils.d.ts +10 -0
  28. package/build/cjs/navigation/utils.js +11 -0
  29. package/build/cjs/schema/validators/common.d.ts +0 -6
  30. package/build/cjs/schema/validators/common.js +0 -4
  31. package/build/cjs/sub-blocks/HubspotForm/HubspotForm.css +1 -0
  32. package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.css +4 -4
  33. package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.js +1 -1
  34. package/build/esm/blocks/Map/schema.d.ts +0 -12
  35. package/build/esm/components/HTML/HTML.d.ts +1 -1
  36. package/build/esm/components/Map/GoogleMap.js +7 -5
  37. package/build/esm/components/Map/Map.css +5 -0
  38. package/build/esm/components/Map/YMap/YMap.d.ts +4 -2
  39. package/build/esm/components/Map/YMap/YMap.js +18 -10
  40. package/build/esm/components/Map/YMap/YandexMap.js +18 -9
  41. package/build/esm/models/constructor-items/common.d.ts +0 -2
  42. package/build/esm/navigation/components/Header/Header.css +23 -0
  43. package/build/esm/navigation/components/Header/Header.js +12 -8
  44. package/build/esm/navigation/components/MobileNavigation/MobileNavigation.css +5 -2
  45. package/build/esm/navigation/components/MobileNavigation/MobileNavigation.d.ts +2 -2
  46. package/build/esm/navigation/components/MobileNavigation/MobileNavigation.js +11 -11
  47. package/build/esm/navigation/components/Navigation/Navigation.css +0 -11
  48. package/build/esm/navigation/components/Navigation/Navigation.d.ts +4 -11
  49. package/build/esm/navigation/components/Navigation/Navigation.js +6 -25
  50. package/build/esm/navigation/components/NavigationDropdownItem/NavigationDropdownItem.d.ts +11 -0
  51. package/build/esm/navigation/components/NavigationDropdownItem/NavigationDropdownItem.js +12 -0
  52. package/build/esm/navigation/components/NavigationListItem/NavigationListItem.css +11 -0
  53. package/build/esm/navigation/components/NavigationListItem/NavigationListItem.d.ts +17 -0
  54. package/build/esm/navigation/components/NavigationListItem/NavigationListItem.js +24 -0
  55. package/build/esm/navigation/constants.d.ts +6 -0
  56. package/build/esm/navigation/constants.js +7 -0
  57. package/build/esm/navigation/utils.d.ts +10 -0
  58. package/build/esm/navigation/utils.js +7 -0
  59. package/build/esm/schema/validators/common.d.ts +0 -6
  60. package/build/esm/schema/validators/common.js +0 -4
  61. package/build/esm/sub-blocks/HubspotForm/HubspotForm.css +1 -0
  62. package/package.json +2 -5
  63. package/server/models/constructor-items/common.d.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.0](https://github.com/gravity-ui/page-constructor/compare/v1.25.2...v2.0.0) (2023-03-23)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * update uikit up to 4, update react up to 18([#134](https://github.com/gravity-ui/page-constructor/issues/134)) (#212)
9
+
10
+ ### Features
11
+
12
+ * map-block changing the logic of zoom and center ([#219](https://github.com/gravity-ui/page-constructor/issues/219)) ([d332844](https://github.com/gravity-ui/page-constructor/commit/d33284425878cdbfacdf7813826d909e9ab696cb))
13
+ * update uikit up to 4, update react up to 18([#134](https://github.com/gravity-ui/page-constructor/issues/134)) ([#212](https://github.com/gravity-ui/page-constructor/issues/212)) ([377b1f5](https://github.com/gravity-ui/page-constructor/commit/377b1f59c25d08458082232075e2e7bcfe84fe5c))
14
+
15
+ ## [1.25.2](https://github.com/gravity-ui/page-constructor/compare/v1.25.1...v1.25.2) (2023-03-21)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **ExtendedFeatures:** label position fixed ([#175](https://github.com/gravity-ui/page-constructor/issues/175)) ([fb8d206](https://github.com/gravity-ui/page-constructor/commit/fb8d206ad2378564a1dc7a7295f02da13ae66df1))
21
+
22
+ ## [1.25.1](https://github.com/gravity-ui/page-constructor/compare/v1.25.0...v1.25.1) (2023-03-20)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * cannot read stopPropagation of undefined in navigation utils ([#221](https://github.com/gravity-ui/page-constructor/issues/221)) ([e20904a](https://github.com/gravity-ui/page-constructor/commit/e20904abfcc14339be777747a4c26187dba8cd58))
28
+
29
+ ## [1.25.0](https://github.com/gravity-ui/page-constructor/compare/v1.24.0...v1.25.0) (2023-03-14)
30
+
31
+
32
+ ### Features
33
+
34
+ * update react-player version ([#217](https://github.com/gravity-ui/page-constructor/issues/217)) ([806dea6](https://github.com/gravity-ui/page-constructor/commit/806dea69c911c789782b8100a364187675ebf3d3))
35
+
36
+ ## [1.24.0](https://github.com/gravity-ui/page-constructor/compare/v1.23.0...v1.24.0) (2023-03-13)
37
+
38
+
39
+ ### Features
40
+
41
+ * add dropdown item in right column of navigation ([#213](https://github.com/gravity-ui/page-constructor/issues/213)) ([71f23a8](https://github.com/gravity-ui/page-constructor/commit/71f23a8ff00948fa62b3bd5b7833b171b59176d6))
42
+
3
43
  ## [1.23.0](https://github.com/gravity-ui/page-constructor/compare/v1.22.1...v1.23.0) (2023-03-09)
4
44
 
5
45
 
@@ -21,7 +21,7 @@ unpredictable css rules order in build */
21
21
  line-height: var(--yc-text-header-1-line-height);
22
22
  color: var(--pc-text-header-color);
23
23
  font-weight: var(--yc-text-accent-font-weight);
24
- display: flex;
24
+ display: block;
25
25
  position: relative;
26
26
  margin-bottom: 8px;
27
27
  }
@@ -42,13 +42,13 @@ unpredictable css rules order in build */
42
42
  font-size: var(--yc-text-caption-2-font-size);
43
43
  line-height: var(--yc-text-caption-2-line-height);
44
44
  position: relative;
45
- top: 5px;
45
+ top: -3px;
46
46
  height: 16px;
47
47
  margin-left: 8px;
48
- padding: 0 5px;
48
+ padding: 1.5px 5px 2px;
49
49
  color: var(--yc-color-base-background);
50
50
  background-color: var(--yc-my-color-brand-normal);
51
- border-radius: 3px;
51
+ border-radius: 4px;
52
52
  }
53
53
  .pc-ExtendedFeaturesBlock__item-text, .pc-ExtendedFeaturesBlock__item-link {
54
54
  font-size: var(--yc-text-body-2-font-size);
@@ -33,7 +33,7 @@ const ExtendedFeaturesBlock = ({ title, description, items, colSizes = DEFAULT_S
33
33
  react_1.default.createElement("div", { className: b('container') },
34
34
  itemTitle && (react_1.default.createElement("h5", { className: b('item-title') },
35
35
  react_1.default.createElement(components_1.HTML, null, itemTitle),
36
- label && (react_1.default.createElement("div", { className: b('item-label') }, label)))),
36
+ label && (react_1.default.createElement("span", { className: b('item-label') }, label)))),
37
37
  react_1.default.createElement(sub_blocks_1.Content, { text: text, links: itemLinks, size: "s", colSizes: { all: 12, md: 12 }, buttons: buttons, additionalInfo: additionalInfo }))));
38
38
  })))));
39
39
  };
@@ -6,12 +6,6 @@ export declare const Map: {
6
6
  zoom: {
7
7
  type: string;
8
8
  };
9
- center: {
10
- type: string;
11
- items: {
12
- type: string;
13
- };
14
- };
15
9
  address: {
16
10
  type: string;
17
11
  };
@@ -70,12 +64,6 @@ export declare const MapBlock: {
70
64
  zoom: {
71
65
  type: string;
72
66
  };
73
- center: {
74
- type: string;
75
- items: {
76
- type: string;
77
- };
78
- };
79
67
  address: {
80
68
  type: string;
81
69
  };
@@ -7,7 +7,7 @@ export interface HTMLProps {
7
7
  }
8
8
  declare const HTML: ({ children, block, className }: WithChildren<HTMLProps>) => React.DetailedReactHTMLElement<{
9
9
  dangerouslySetInnerHTML: {
10
- __html: string & (boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | null);
10
+ __html: string | (string & React.ReactElement<any, string | React.JSXElementConstructor<any>>) | (string & React.ReactFragment) | (string & React.ReactPortal);
11
11
  };
12
12
  className: string | undefined;
13
13
  }, HTMLElement> | null;
@@ -8,18 +8,20 @@ const mapsContext_1 = require("../../context/mapsContext/mapsContext");
8
8
  const localeContext_1 = require("../../context/localeContext/localeContext");
9
9
  const mobileContext_1 = require("../../context/mobileContext");
10
10
  const helpers_1 = require("./helpers");
11
+ const configure_1 = require("../../utils/configure");
11
12
  const b = (0, utils_1.block)('map');
12
- function getScriptSrc(apiKey, scriptSrc, address, lang) {
13
- return `${scriptSrc}?key=${apiKey}&language=${lang}&q=${encodeURI(address)}`;
13
+ function getScriptSrc(params) {
14
+ const { apiKey, scriptSrc, address, lang, zoom } = params;
15
+ return `${scriptSrc}?key=${apiKey}&language=${lang}${zoom ? '&zoom=' + zoom : ''}&q=${encodeURI(address)}`;
14
16
  }
15
17
  const GoogleMap = (props) => {
16
- const { address } = props;
18
+ const { address, zoom } = props;
17
19
  const { apiKey, scriptSrc } = (0, react_1.useContext)(mapsContext_1.MapsContext);
18
- const { lang = 'ru' } = (0, react_1.useContext)(localeContext_1.LocaleContext);
20
+ const { lang = configure_1.Lang.Ru } = (0, react_1.useContext)(localeContext_1.LocaleContext);
19
21
  const isMobile = (0, react_1.useContext)(mobileContext_1.MobileContext);
20
22
  const [height, setHeight] = (0, react_1.useState)(undefined);
21
23
  const ref = (0, react_1.useRef)(null);
22
- const src = (0, react_1.useMemo)(() => getScriptSrc(apiKey, scriptSrc, address, lang), [apiKey, scriptSrc, address, lang]);
24
+ const src = (0, react_1.useMemo)(() => getScriptSrc({ apiKey, scriptSrc, address, lang, zoom }), [apiKey, scriptSrc, address, lang, zoom]);
23
25
  (0, react_1.useEffect)(() => {
24
26
  const updateSize = lodash_1.default.debounce(() => {
25
27
  if (ref.current) {
@@ -7,9 +7,13 @@ unpredictable css rules order in build */
7
7
  overflow: hidden;
8
8
  display: flex;
9
9
  }
10
+ .pc-map_hidden {
11
+ opacity: 0;
12
+ }
10
13
  .pc-map__spinner {
11
14
  margin: 0 auto;
12
15
  align-self: center;
16
+ position: absolute;
13
17
  }
14
18
  .pc-map__wrapper {
15
19
  min-height: 300px;
@@ -17,4 +21,5 @@ unpredictable css rules order in build */
17
21
  flex-direction: column;
18
22
  align-items: center;
19
23
  justify-content: center;
24
+ position: relative;
20
25
  }
@@ -1,13 +1,15 @@
1
- import { YMapMarker } from '../../../models';
1
+ import { YMapProps, YMapMarker } from '../../../models';
2
+ type PlacemarksProps = Pick<YMapProps, 'zoom' | 'markers'>;
2
3
  export declare class YMap {
3
4
  private ymap;
4
5
  private mapRef;
5
6
  private coords;
6
7
  constructor(ymap: Ymaps.Map, mapRef: HTMLDivElement | null);
7
- showPlacemarks(markers: YMapMarker[]): Promise<void>;
8
+ showPlacemarks(props: PlacemarksProps): Promise<void>;
8
9
  findAddress(marker: YMapMarker): Promise<void>;
9
10
  findCoordinate(marker: YMapMarker): void;
10
11
  private drawPlaceMarkStyle;
11
12
  private recalcZoomAndCenter;
12
13
  private clearOldPlacemarks;
13
14
  }
15
+ export {};
@@ -22,9 +22,9 @@ class YMap {
22
22
  this.ymap = ymap;
23
23
  this.mapRef = mapRef;
24
24
  }
25
- async showPlacemarks(markers) {
25
+ async showPlacemarks(props) {
26
26
  this.clearOldPlacemarks();
27
- for (const marker of markers) {
27
+ for (const marker of props.markers) {
28
28
  if (marker.address) {
29
29
  await this.findAddress(marker);
30
30
  }
@@ -32,7 +32,7 @@ class YMap {
32
32
  this.findCoordinate(marker);
33
33
  }
34
34
  }
35
- this.recalcZoomAndCenter();
35
+ this.recalcZoomAndCenter(props);
36
36
  }
37
37
  async findAddress(marker) {
38
38
  try {
@@ -52,10 +52,7 @@ class YMap {
52
52
  this.ymap.geoObjects.add(geoObject);
53
53
  }
54
54
  drawPlaceMarkStyle(geoObject, marker) {
55
- if (!marker.label) {
56
- return;
57
- }
58
- const { iconColor, preset = DEFAULT_PLACEMARKS_PRESET } = marker.label;
55
+ const { iconColor, preset = DEFAULT_PLACEMARKS_PRESET } = marker.label || {};
59
56
  let localIconColor = iconColor;
60
57
  // You can set the preset option together with the iconColor option only if it not a 'Stretchy' preset
61
58
  if (!preset.includes('Stretchy') && !iconColor) {
@@ -68,9 +65,10 @@ class YMap {
68
65
  }
69
66
  });
70
67
  }
71
- recalcZoomAndCenter() {
68
+ recalcZoomAndCenter(props) {
72
69
  var _a, _b;
73
70
  const coordsLength = this.coords.length;
71
+ const { zoom = 0 } = props;
74
72
  if (!coordsLength) {
75
73
  return;
76
74
  }
@@ -79,10 +77,20 @@ class YMap {
79
77
  leftBottom = [Math.min(leftBottom[0], point[0]), Math.min(leftBottom[1], point[1])];
80
78
  rightTop = [Math.max(rightTop[0], point[0]), Math.max(rightTop[1], point[1])];
81
79
  });
82
- const newMapParams = window.ymaps.util.bounds.getCenterAndZoom([leftBottom, rightTop], [(_a = this.mapRef) === null || _a === void 0 ? void 0 : _a.clientWidth, (_b = this.mapRef) === null || _b === void 0 ? void 0 : _b.clientHeight], undefined, { margin: DEFAULT_MAP_CONTROL_BUTTON_HEIGHT });
80
+ let newMapParams = {
81
+ zoom,
82
+ center: [],
83
+ };
84
+ if (zoom) {
85
+ // compute only the center
86
+ newMapParams.center = window.ymaps.util.bounds.getCenter([leftBottom, rightTop]);
87
+ }
88
+ else {
89
+ newMapParams = window.ymaps.util.bounds.getCenterAndZoom([leftBottom, rightTop], [(_a = this.mapRef) === null || _a === void 0 ? void 0 : _a.clientWidth, (_b = this.mapRef) === null || _b === void 0 ? void 0 : _b.clientHeight], undefined, { margin: DEFAULT_MAP_CONTROL_BUTTON_HEIGHT });
90
+ }
83
91
  this.ymap.setCenter(newMapParams.center);
84
92
  // Use default zoom for one placemark
85
- if (coordsLength > 1) {
93
+ if (coordsLength > 1 && !zoom) {
86
94
  this.ymap.setZoom(newMapParams.zoom);
87
95
  }
88
96
  }
@@ -16,8 +16,12 @@ const helpers_1 = require("../helpers");
16
16
  const b = (0, utils_1.block)('map');
17
17
  const DEFAULT_CONTAINER_ID = 'ymap';
18
18
  const DEFAULT_ZOOM = 9;
19
+ // Center - is a required parameter for creating a new map
20
+ // We use this init center to create a map
21
+ // The real center of the map will be calculated later, using the coordinates of the markers
22
+ const INITIAL_CENTER = [0, 0];
19
23
  const YandexMap = (props) => {
20
- const { markers, zoom, center, id } = props;
24
+ const { markers, zoom, id } = props;
21
25
  const { apiKey, scriptSrc, nonce } = (0, react_1.useContext)(mapsContext_1.MapsContext);
22
26
  const isMobile = (0, react_1.useContext)(mobileContext_1.MobileContext);
23
27
  const { lang = 'ru' } = (0, react_1.useContext)(localeContext_1.LocaleContext);
@@ -26,6 +30,7 @@ const YandexMap = (props) => {
26
30
  const [height, setHeight] = (0, react_1.useState)(undefined);
27
31
  const ref = (0, react_1.useRef)(null);
28
32
  const [loading, setLoading] = (0, react_1.useState)(false);
33
+ const [ready, setReady] = (0, react_1.useState)(false);
29
34
  const [attemptsIndex, setAttemptsIndex] = (0, react_1.useState)(0);
30
35
  const onTryAgain = (0, react_1.useCallback)(() => {
31
36
  setAttemptsIndex(attemptsIndex + 1);
@@ -33,20 +38,17 @@ const YandexMap = (props) => {
33
38
  (0, react_1.useEffect)(() => {
34
39
  (async function () {
35
40
  var _a;
36
- if (!center) {
37
- return;
38
- }
39
41
  setLoading(true);
40
42
  await YandexMapApiLoader_1.YMapsApiLoader.loadApi(apiKey, scriptSrc, lang, nonce);
41
43
  (_a = window.ymaps) === null || _a === void 0 ? void 0 : _a.ready(() => {
42
44
  setYmaps(new YMap_1.YMap(new window.ymaps.Map(containerId, {
43
- center,
45
+ center: INITIAL_CENTER,
44
46
  zoom: zoom || DEFAULT_ZOOM,
45
47
  }, { autoFitToViewport: 'always' }), ref.current));
46
48
  });
47
49
  setLoading(false);
48
50
  })();
49
- }, [apiKey, lang, scriptSrc, containerId, zoom, center, nonce, attemptsIndex, setLoading]);
51
+ }, [apiKey, lang, scriptSrc, containerId, zoom, nonce, attemptsIndex, setLoading]);
50
52
  (0, react_1.useEffect)(() => {
51
53
  const updateSize = lodash_1.default.debounce(() => {
52
54
  if (ref.current) {
@@ -61,12 +63,19 @@ const YandexMap = (props) => {
61
63
  }, [markers, ymap, setYmaps, isMobile]);
62
64
  (0, react_1.useEffect)(() => {
63
65
  if (ymap) {
64
- ymap.showPlacemarks(markers);
66
+ // show with computed center and placemarks
67
+ const showPlacemarks = async () => {
68
+ await ymap.showPlacemarks({ markers, zoom });
69
+ setReady(true);
70
+ };
71
+ showPlacemarks();
65
72
  }
66
73
  });
67
- if (!center)
74
+ if (!markers)
68
75
  return null;
69
76
  return (react_1.default.createElement(ErrorWrapper_1.default, { isError: YandexMapApiLoader_1.YMapsApiLoader.status === YandexMapApiLoader_1.MapApiStatus.Error, text: (0, i18n_1.default)('map-load-error'), buttonText: (0, i18n_1.default)('map-try-again'), handler: onTryAgain, className: b('wrapper') },
70
- react_1.default.createElement("div", { id: containerId, className: b(), ref: ref, style: { height } }, loading ? react_1.default.createElement(uikit_1.Spin, { size: "xl", className: b('spinner') }) : null)));
77
+ react_1.default.createElement("div", { className: b('wrapper') },
78
+ react_1.default.createElement("div", { id: containerId, className: b({ hidden: !ready }), ref: ref, style: { height } }),
79
+ loading ? react_1.default.createElement(uikit_1.Spin, { size: "xl", className: b('spinner') }) : null)));
71
80
  };
72
81
  exports.default = YandexMap;
@@ -189,7 +189,6 @@ export interface MediaProps extends Animatable, Partial<MediaComponentDataLensPr
189
189
  export type Coordinate = number[];
190
190
  export interface MapBaseProps {
191
191
  zoom?: number;
192
- center?: Coordinate;
193
192
  }
194
193
  export interface GMapProps extends MapBaseProps {
195
194
  address: string;
@@ -197,7 +196,6 @@ export interface GMapProps extends MapBaseProps {
197
196
  export interface YMapProps extends MapBaseProps {
198
197
  markers: YMapMarker[];
199
198
  id: string;
200
- center: Coordinate;
201
199
  }
202
200
  export interface YMapMarker {
203
201
  address?: string;
@@ -41,6 +41,8 @@ unpredictable css rules order in build */
41
41
  .pc-header__right {
42
42
  flex: 0;
43
43
  justify-content: flex-end;
44
+ font-size: var(--yc-text-body-2-font-size);
45
+ line-height: var(--yc-text-body-2-line-height);
44
46
  }
45
47
  .pc-header__navigation-container {
46
48
  display: flex;
@@ -53,6 +55,9 @@ unpredictable css rules order in build */
53
55
  .pc-header__buttons {
54
56
  display: flex;
55
57
  align-items: center;
58
+ margin: 0;
59
+ padding: 0;
60
+ list-style: none;
56
61
  }
57
62
  @media (max-width: 768px) {
58
63
  .pc-header__buttons {
@@ -62,6 +67,24 @@ unpredictable css rules order in build */
62
67
  .pc-header__buttons > *:not(:last-child) {
63
68
  margin-right: 16px;
64
69
  }
70
+ .pc-header__buttons-item {
71
+ position: relative;
72
+ height: var(--header-height);
73
+ line-height: var(--header-height);
74
+ cursor: pointer;
75
+ outline: none;
76
+ color: inherit;
77
+ text-decoration: none;
78
+ }
79
+ .utilityfocus .pc-header__buttons-item:focus {
80
+ outline: 2px solid #ffdb4d;
81
+ }
82
+ .pc-header__buttons-item:hover, .pc-header__buttons-item:active {
83
+ color: var(--yc-color-text-link);
84
+ }
85
+ .pc-header__buttons-item:not(:last-child) {
86
+ margin-right: 20px;
87
+ }
65
88
  .pc-header__button {
66
89
  margin-top: 0;
67
90
  }
@@ -7,11 +7,12 @@ const utils_1 = require("../../../utils");
7
7
  const grid_1 = require("../../../grid");
8
8
  const OutsideClick_1 = tslib_1.__importDefault(require("../../../components/OutsideClick/OutsideClick"));
9
9
  const Control_1 = tslib_1.__importDefault(require("../../../components/Control/Control"));
10
+ const icons_1 = require("../../../icons");
11
+ const constants_1 = require("../../constants");
10
12
  const Navigation_1 = tslib_1.__importDefault(require("../Navigation/Navigation"));
11
13
  const MobileNavigation_1 = tslib_1.__importDefault(require("../MobileNavigation/MobileNavigation"));
12
- const NavigationItem_1 = tslib_1.__importDefault(require("../NavigationItem/NavigationItem"));
13
14
  const Logo_1 = tslib_1.__importDefault(require("../Logo/Logo"));
14
- const icons_1 = require("../../../icons");
15
+ const NavigationListItem_1 = require("../NavigationListItem/NavigationListItem");
15
16
  const b = (0, utils_1.block)('header');
16
17
  const ICON_SIZE = 36;
17
18
  const MobileMenuButton = ({ isSidebarOpened, onSidebarOpenedChange, }) => {
@@ -27,10 +28,13 @@ const MobileMenuButton = ({ isSidebarOpened, onSidebarOpenedChange, }) => {
27
28
  const Header = ({ data, logo }) => {
28
29
  const { leftItems, rightItems } = data;
29
30
  const [isSidebarOpened, setIsSidebarOpened] = (0, react_1.useState)(false);
30
- const [activeItemIndex, setActiveItemIndex] = (0, react_1.useState)(-1);
31
- const onActiveItemChange = (0, react_1.useCallback)((index) => {
32
- setActiveItemIndex(index);
31
+ const [activeItemId, setactiveItemId] = (0, react_1.useState)(undefined);
32
+ const onActiveItemChange = (0, react_1.useCallback)((id) => {
33
+ setactiveItemId(id);
33
34
  }, []);
35
+ const hidePopup = (0, react_1.useCallback)(() => {
36
+ onActiveItemChange();
37
+ }, [onActiveItemChange]);
34
38
  const onSidebarOpenedChange = (0, react_1.useCallback)((isOpen) => {
35
39
  setIsSidebarOpened(isOpen);
36
40
  }, []);
@@ -44,12 +48,12 @@ const Header = ({ data, logo }) => {
44
48
  logo && (react_1.default.createElement("div", { className: b('left') },
45
49
  react_1.default.createElement(Logo_1.default, Object.assign({}, logo, { className: b('logo') })))),
46
50
  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: onActiveItemChange })),
51
+ react_1.default.createElement(Navigation_1.default, { className: b('navigation'), links: leftItems, activeItemId: activeItemId, onActiveItemChange: onActiveItemChange })),
48
52
  react_1.default.createElement("div", { className: b('right') },
49
53
  react_1.default.createElement(MobileMenuButton, { isSidebarOpened: isSidebarOpened, onSidebarOpenedChange: onSidebarOpenedChange }),
50
- rightItems && (react_1.default.createElement("div", { className: b('buttons') }, rightItems.map((button) => (react_1.default.createElement(NavigationItem_1.default, { key: button.text, data: button })))))),
54
+ rightItems && (react_1.default.createElement("ul", { className: b('buttons') }, rightItems.map((button, index) => (react_1.default.createElement(NavigationListItem_1.NavigationListItem, { key: index, className: b('buttons-item'), item: button, index: index, activeItemId: activeItemId, hidePopup: hidePopup, column: constants_1.ItemColumnName.Right, onActiveItemChange: onActiveItemChange })))))),
51
55
  react_1.default.createElement(OutsideClick_1.default, { onOutsideClick: () => onSidebarOpenedChange(false) },
52
- react_1.default.createElement(MobileNavigation_1.default, { topItems: leftItems, bottomItems: rightItems, isOpened: isSidebarOpened, activeItemIndex: activeItemIndex, onActiveItemChange: onActiveItemChange, onClose: hideSidebar })))))));
56
+ react_1.default.createElement(MobileNavigation_1.default, { topItems: leftItems, bottomItems: rightItems, isOpened: isSidebarOpened, activeItemId: activeItemId, onActiveItemChange: onActiveItemChange, onClose: hideSidebar })))))));
53
57
  };
54
58
  exports.Header = Header;
55
59
  exports.default = exports.Header;
@@ -24,7 +24,10 @@ unpredictable css rules order in build */
24
24
  .pc-mobile-navigation__button {
25
25
  margin-top: 24px;
26
26
  }
27
- .pc-mobile-navigation__links {
27
+ .pc-mobile-navigation__nav {
28
+ margin-bottom: 24px;
29
+ }
30
+ .pc-mobile-navigation__rows {
28
31
  position: relative;
29
32
  display: flex;
30
33
  flex-direction: column;
@@ -33,7 +36,7 @@ unpredictable css rules order in build */
33
36
  padding: 0;
34
37
  list-style: none;
35
38
  }
36
- .pc-mobile-navigation__links-item:not(:last-child) {
39
+ .pc-mobile-navigation__rows-item:not(:last-child) {
37
40
  margin-bottom: 24px;
38
41
  }
39
42
  .pc-mobile-navigation__dropdown-item:not(:last-child) {
@@ -5,9 +5,9 @@ export interface MobileNavigationProps {
5
5
  isOpened?: boolean;
6
6
  topItems?: NavigationItemModel[];
7
7
  bottomItems?: NavigationItemModel[];
8
- activeItemIndex: number;
8
+ activeItemId?: string;
9
9
  onClose: () => void;
10
- onActiveItemChange: (index: number) => void;
10
+ onActiveItemChange: (id?: string) => void;
11
11
  }
12
12
  declare const MobileNavigation: React.FC<MobileNavigationProps>;
13
13
  export default MobileNavigation;
@@ -6,6 +6,7 @@ const uikit_1 = require("@gravity-ui/uikit");
6
6
  const utils_1 = require("../../../utils");
7
7
  const Foldable_1 = tslib_1.__importDefault(require("../../../components/Foldable/Foldable"));
8
8
  const models_1 = require("../../../models");
9
+ const constants_1 = require("../../constants");
9
10
  const NavigationItem_1 = tslib_1.__importDefault(require("../NavigationItem/NavigationItem"));
10
11
  const b = (0, utils_1.block)('mobile-navigation');
11
12
  const MobileNavigationDropdown = ({ data, onItemClick, onToggle, isOpened = false, }) => {
@@ -14,32 +15,31 @@ const MobileNavigationDropdown = ({ data, onItemClick, onToggle, isOpened = fals
14
15
  react_1.default.createElement(NavigationItem_1.default, { data: data, onClick: onToggle, isOpened: isOpened }),
15
16
  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
  };
17
- const MobileNavigationItem = ({ link, index, isActive, onActiveItemChange, onClose, }) => {
18
+ const MobileNavigationItem = ({ item, index, isOpened, activeItemId, onActiveItemChange, column, onClose, }) => {
19
+ const id = `${column}-${index}`;
20
+ const isActive = id === activeItemId && isOpened;
18
21
  const toggleActive = (0, react_1.useCallback)((e) => {
19
22
  e.stopPropagation();
20
23
  if (onActiveItemChange) {
21
- onActiveItemChange(isActive ? -1 : index);
24
+ onActiveItemChange(isActive ? undefined : `${column}-${index}`);
22
25
  }
23
- }, [isActive, index, onActiveItemChange]);
26
+ }, [onActiveItemChange, isActive, column, index]);
24
27
  const onItemClick = (0, react_1.useCallback)((e) => {
25
28
  toggleActive(e);
26
29
  onClose();
27
30
  }, [toggleActive, onClose]);
28
- return (react_1.default.createElement("li", { key: index, className: b('links-item') }, link.type === models_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 }))));
31
+ return (react_1.default.createElement("li", { key: index, className: b('rows-item') }, item.type === models_1.NavigationItemType.Dropdown ? (react_1.default.createElement(MobileNavigationDropdown, { data: item, onToggle: toggleActive, isOpened: isActive, onItemClick: onItemClick })) : (react_1.default.createElement(NavigationItem_1.default, { data: item, onClick: onItemClick }))));
29
32
  };
30
33
  const MobileNavigation = (props) => {
31
34
  if (typeof window === 'undefined') {
32
35
  return null;
33
36
  }
34
- const { isOpened, topItems, bottomItems, activeItemIndex, onActiveItemChange, onClose } = props;
37
+ const { isOpened, topItems, bottomItems, activeItemId, onActiveItemChange, onClose } = props;
35
38
  return (react_1.default.createElement(uikit_1.Portal, null,
36
39
  react_1.default.createElement(Foldable_1.default, { key: topItems === null || topItems === void 0 ? void 0 : topItems.length, className: b(), isOpened: Boolean(isOpened) },
37
40
  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') })))))));
41
+ react_1.default.createElement("nav", { className: b('nav') },
42
+ react_1.default.createElement("ul", { className: b('rows') }, topItems === null || topItems === void 0 ? void 0 : topItems.map((link, index) => (react_1.default.createElement(MobileNavigationItem, { key: index, item: link, column: constants_1.ItemColumnName.Top, index: index, isOpened: isOpened, activeItemId: activeItemId, onClose: onClose, onActiveItemChange: onActiveItemChange }))))),
43
+ react_1.default.createElement("ul", { className: b('rows') }, bottomItems === null || bottomItems === void 0 ? void 0 : bottomItems.map((item, index) => (react_1.default.createElement(MobileNavigationItem, { key: index, item: item, column: constants_1.ItemColumnName.Bottom, index: index, isOpened: isOpened, activeItemId: activeItemId, onClose: onClose, onActiveItemChange: onActiveItemChange }))))))));
44
44
  };
45
45
  exports.default = MobileNavigation;
@@ -29,15 +29,4 @@ unpredictable css rules order in build */
29
29
  }
30
30
  .pc-navigation__links-item:not(:last-child) {
31
31
  margin-right: 20px;
32
- }
33
- .pc-navigation__slider-container {
34
- position: absolute;
35
- right: 0;
36
- bottom: 0;
37
- left: 0;
38
- }
39
- .pc-navigation__slider {
40
- width: 100%;
41
- height: 2px;
42
- background-color: var(--yc-color-text-link);
43
32
  }
@@ -1,18 +1,11 @@
1
- import React, { MouseEventHandler } from 'react';
2
- import { NavigationDropdownItem, NavigationItemModel } from '../../../models/navigation';
1
+ import React from 'react';
2
+ import { NavigationItemModel } from '../../../models/navigation';
3
3
  export interface NavigationProps {
4
4
  links: NavigationItemModel[];
5
- activeItemIndex: number;
6
- onActiveItemChange: (index: number) => void;
5
+ activeItemId?: string;
7
6
  className?: string;
8
7
  highlightActiveItem?: boolean;
9
- }
10
- export interface NavigationDropdownProps {
11
- data: NavigationDropdownItem;
12
- onClick: MouseEventHandler;
13
- isActive: boolean;
14
- position: number;
15
- hidePopup: () => void;
8
+ onActiveItemChange: (id?: string) => void;
16
9
  }
17
10
  declare const Navigation: React.FC<NavigationProps>;
18
11
  export default Navigation;
@@ -5,29 +5,18 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
5
5
  const react_1 = tslib_1.__importStar(require("react"));
6
6
  const utils_1 = require("../../../utils");
7
7
  const OverflowScroller_1 = tslib_1.__importDefault(require("../../../components/OverflowScroller/OverflowScroller"));
8
- const navigation_1 = require("../../../models/navigation");
9
- const NavigationPopup_1 = tslib_1.__importDefault(require("../NavigationPopup/NavigationPopup"));
10
- const NavigationItem_1 = tslib_1.__importDefault(require("../NavigationItem/NavigationItem"));
11
8
  const locationContext_1 = require("../../../context/locationContext");
9
+ const constants_1 = require("../../constants");
10
+ const NavigationListItem_1 = require("../NavigationListItem/NavigationListItem");
12
11
  const b = (0, utils_1.block)('navigation');
13
- const NavigationDropdown = ({ data, isActive, position, hidePopup, onClick, }) => {
14
- const { text, items } = data, popupProps = tslib_1.__rest(data, ["text", "items"]);
15
- return (react_1.default.createElement(react_1.Fragment, null,
16
- react_1.default.createElement(NavigationItem_1.default, { className: b('link'), onClick: onClick, isOpened: isActive, data: { text, type: navigation_1.NavigationItemType.Dropdown } }),
17
- isActive && (react_1.default.createElement(NavigationPopup_1.default, Object.assign({ left: position, onClose: hidePopup, items: items }, popupProps)))));
18
- };
19
- const Navigation = ({ className, onActiveItemChange, links, activeItemIndex, highlightActiveItem, }) => {
12
+ const Navigation = ({ className, onActiveItemChange, links, activeItemId, highlightActiveItem, }) => {
20
13
  const { asPath, pathname } = (0, react_1.useContext)(locationContext_1.LocationContext);
21
14
  const itemRefs = (0, react_1.useRef)([]);
22
15
  const [itemPositions, setItemPosition] = (0, react_1.useState)([]);
23
16
  const [lastLeftScroll, setLastLeftScroll] = (0, react_1.useState)(0);
24
17
  const hidePopup = (0, react_1.useCallback)(() => {
25
- onActiveItemChange(-1);
18
+ onActiveItemChange();
26
19
  }, [onActiveItemChange]);
27
- const getItemClickHandler = (0, react_1.useCallback)((index) => (e) => {
28
- e.stopPropagation();
29
- onActiveItemChange(index === activeItemIndex ? -1 : index);
30
- }, [activeItemIndex, onActiveItemChange]);
31
20
  const calculateItemPositions = (0, react_1.useCallback)(() => {
32
21
  if (itemRefs.current.length) {
33
22
  const currentItemPositions = itemRefs.current.map((itemRef) => (itemRef && itemRef.getBoundingClientRect().left) || 0);
@@ -57,13 +46,6 @@ const Navigation = ({ className, onActiveItemChange, links, activeItemIndex, hig
57
46
  }, [hidePopup, asPath, pathname]);
58
47
  return (react_1.default.createElement(OverflowScroller_1.default, { className: b(null, className), onScrollStart: hidePopup, onScrollEnd: calculateItemPositions },
59
48
  react_1.default.createElement("nav", null,
60
- react_1.default.createElement("ul", { className: b('links') }, links.map((link, index) => {
61
- const isActive = index === activeItemIndex;
62
- const onClick = getItemClickHandler(index);
63
- return (react_1.default.createElement("li", { ref: (el) => itemRefs.current.push(el), key: index, className: b('links-item') },
64
- link.type === navigation_1.NavigationItemType.Dropdown ? (react_1.default.createElement(NavigationDropdown, { data: link, onClick: onClick, isActive: isActive, position: itemPositions[index], hidePopup: hidePopup })) : (react_1.default.createElement(NavigationItem_1.default, { data: link, onClick: onClick })),
65
- highlightActiveItem && isActive && (react_1.default.createElement("div", { className: b('slider-container') },
66
- react_1.default.createElement("div", { className: b('slider') })))));
67
- })))));
49
+ react_1.default.createElement("ul", { className: b('links') }, links.map((link, index) => (react_1.default.createElement(NavigationListItem_1.NavigationListItem, { key: index, className: b('links-item'), item: link, itemRefs: itemRefs, index: index, activeItemId: activeItemId, highlightActiveItem: highlightActiveItem, hidePopup: hidePopup, itemPositions: itemPositions, column: constants_1.ItemColumnName.Left, onActiveItemChange: onActiveItemChange })))))));
68
50
  };
69
51
  exports.default = Navigation;
@@ -0,0 +1,11 @@
1
+ import React, { MouseEventHandler } from 'react';
2
+ import { NavigationDropdownItem } from '../../../models';
3
+ export interface NavigationDropdownProps {
4
+ data: NavigationDropdownItem;
5
+ onClick: MouseEventHandler;
6
+ isActive: boolean;
7
+ position: number;
8
+ hidePopup: () => void;
9
+ }
10
+ declare const NavigationDropdown: React.FC<NavigationDropdownProps>;
11
+ export default NavigationDropdown;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = tslib_1.__importStar(require("react"));
5
+ const models_1 = require("../../../models");
6
+ const NavigationItem_1 = tslib_1.__importDefault(require("../NavigationItem/NavigationItem"));
7
+ const NavigationPopup_1 = tslib_1.__importDefault(require("../NavigationPopup/NavigationPopup"));
8
+ const NavigationDropdown = ({ data, isActive, position, hidePopup, onClick, }) => {
9
+ const { text, icon, items } = data, popupProps = tslib_1.__rest(data, ["text", "icon", "items"]);
10
+ return (react_1.default.createElement(react_1.Fragment, null,
11
+ react_1.default.createElement(NavigationItem_1.default, { onClick: onClick, isOpened: isActive, data: { text, type: models_1.NavigationItemType.Dropdown, icon } }),
12
+ isActive && (react_1.default.createElement(NavigationPopup_1.default, Object.assign({ left: position, onClose: hidePopup, items: items }, popupProps)))));
13
+ };
14
+ exports.default = NavigationDropdown;