@gravity-ui/page-constructor 2.0.2 → 2.1.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 (36) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/cjs/blocks/FilterBlock/FilterBlock.css +1 -5
  3. package/build/cjs/blocks/Tabs/Tabs.css +1 -5
  4. package/build/cjs/components/BlockHeader/BlockHeader.css +2 -2
  5. package/build/cjs/components/Button/Button.d.ts +1 -0
  6. package/build/cjs/components/Button/Button.js +1 -1
  7. package/build/cjs/components/Button/__tests__/Button.test.d.ts +1 -0
  8. package/build/cjs/components/Button/__tests__/Button.test.js +91 -0
  9. package/build/cjs/components/Button/utils.d.ts +1 -0
  10. package/build/cjs/components/Button/utils.js +2 -1
  11. package/build/cjs/components/Title/Title.css +20 -5
  12. package/build/cjs/components/Title/Title.d.ts +1 -1
  13. package/build/cjs/components/Title/Title.js +4 -2
  14. package/build/cjs/models/constructor-items/common.d.ts +5 -3
  15. package/build/cjs/utils/blocks.d.ts +1 -1
  16. package/build/cjs/utils/blocks.js +2 -0
  17. package/build/esm/blocks/FilterBlock/FilterBlock.css +1 -5
  18. package/build/esm/blocks/Tabs/Tabs.css +1 -5
  19. package/build/esm/components/BlockHeader/BlockHeader.css +2 -2
  20. package/build/esm/components/Button/Button.d.ts +1 -0
  21. package/build/esm/components/Button/Button.js +2 -2
  22. package/build/esm/components/Button/__tests__/Button.test.d.ts +1 -0
  23. package/build/esm/components/Button/__tests__/Button.test.js +88 -0
  24. package/build/esm/components/Button/utils.d.ts +1 -0
  25. package/build/esm/components/Button/utils.js +1 -0
  26. package/build/esm/components/Title/Title.css +20 -5
  27. package/build/esm/components/Title/Title.d.ts +1 -1
  28. package/build/esm/components/Title/Title.js +4 -2
  29. package/build/esm/models/constructor-items/common.d.ts +5 -3
  30. package/build/esm/utils/blocks.d.ts +1 -1
  31. package/build/esm/utils/blocks.js +2 -0
  32. package/package.json +1 -1
  33. package/server/models/constructor-items/common.d.ts +5 -3
  34. package/server/utils/blocks.d.ts +1 -1
  35. package/server/utils/blocks.js +2 -0
  36. package/styles/mixins.scss +10 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.0](https://github.com/gravity-ui/page-constructor/compare/v2.0.3...v2.1.0) (2023-03-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Title:** add size xs ([#207](https://github.com/gravity-ui/page-constructor/issues/207)) ([1fd8cf7](https://github.com/gravity-ui/page-constructor/commit/1fd8cf7aeaf4a6a993a3ffcce576a41d61c3b66b))
9
+
10
+ ## [2.0.3](https://github.com/gravity-ui/page-constructor/compare/v2.0.2...v2.0.3) (2023-03-27)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **Tabs:** wrap tabs on desktop ([#237](https://github.com/gravity-ui/page-constructor/issues/237)) ([68dd965](https://github.com/gravity-ui/page-constructor/commit/68dd965b8d5ad9439f8c59211232911695c30fd3))
16
+
3
17
  ## [2.0.2](https://github.com/gravity-ui/page-constructor/compare/v2.0.1...v2.0.2) (2023-03-24)
4
18
 
5
19
 
@@ -16,18 +16,14 @@ unpredictable css rules order in build */
16
16
  .pc-filter-block__tabs {
17
17
  margin-bottom: 0;
18
18
  display: flex;
19
- flex-wrap: nowrap;
19
+ flex-wrap: wrap;
20
20
  justify-content: flex-start;
21
- overflow: auto;
22
21
  }
23
22
  .pc-filter-block__tabs_centered {
24
- display: flex;
25
23
  justify-content: center;
26
- flex-wrap: wrap;
27
24
  }
28
25
  @media (max-width: 769px) {
29
26
  .pc-filter-block__tabs {
30
- display: flex;
31
27
  flex-wrap: nowrap;
32
28
  justify-content: flex-start;
33
29
  overflow: auto;
@@ -16,18 +16,14 @@ unpredictable css rules order in build */
16
16
  .pc-tabs-block__tabs {
17
17
  margin-bottom: 20px;
18
18
  display: flex;
19
- flex-wrap: nowrap;
19
+ flex-wrap: wrap;
20
20
  justify-content: flex-start;
21
- overflow: auto;
22
21
  }
23
22
  .pc-tabs-block__tabs_centered {
24
- display: flex;
25
23
  justify-content: center;
26
- flex-wrap: wrap;
27
24
  }
28
25
  @media (max-width: 769px) {
29
26
  .pc-tabs-block__tabs {
30
- display: flex;
31
27
  flex-wrap: nowrap;
32
28
  justify-content: flex-start;
33
29
  overflow: auto;
@@ -7,10 +7,10 @@ unpredictable css rules order in build */
7
7
  font-size: var(--yc-text-body-3-font-size);
8
8
  line-height: var(--yc-text-body-3-line-height);
9
9
  }
10
- .pc-block-header__description_titleSize_s {
10
+ .pc-block-header__description_titleSize_s, .pc-block-header__description_titleSize_xs {
11
11
  margin-top: 8px;
12
12
  }
13
- .pc-block-header__description_titleSize_s .yfm {
13
+ .pc-block-header__description_titleSize_s .yfm, .pc-block-header__description_titleSize_xs .yfm {
14
14
  font-size: var(--yc-text-body-2-font-size);
15
15
  line-height: var(--yc-text-body-2-line-height);
16
16
  }
@@ -3,6 +3,7 @@ export interface ButtonProps extends Omit<ButtonParams, 'url'> {
3
3
  className?: string;
4
4
  url?: string;
5
5
  onClick?: () => void;
6
+ qa?: string;
6
7
  }
7
8
  declare const Button: (props: ButtonProps) => JSX.Element;
8
9
  export default Button;
@@ -38,7 +38,7 @@ const Button = (props) => {
38
38
  let icon;
39
39
  let image = img && react_1.default.createElement("img", { className: b('image'), src: buttonImg.url, alt: buttonImg.alt });
40
40
  if (theme === 'github') {
41
- icon = react_1.default.createElement(uikit_1.Icon, { className: b('icon'), data: icons_1.Github, size: 24 });
41
+ icon = react_1.default.createElement(uikit_1.Icon, { className: b('icon'), data: icons_1.Github, size: 24, qa: utils_2.ICON_QA });
42
42
  image = undefined;
43
43
  }
44
44
  const buttonTheme = theme === 'scale' ? 'accent' : theme;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const react_1 = tslib_1.__importDefault(require("react"));
5
+ const react_2 = require("@testing-library/react");
6
+ const user_event_1 = tslib_1.__importDefault(require("@testing-library/user-event"));
7
+ const utils_1 = require("../utils");
8
+ const Button_1 = tslib_1.__importDefault(require("../Button"));
9
+ const qaId = 'button-component';
10
+ const buttonProps = {
11
+ text: 'Button Text',
12
+ url: 'https://github.com/gravity-ui/',
13
+ target: '_blank',
14
+ img: {
15
+ url: 'https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_1_light.svg',
16
+ position: 'left',
17
+ alt: 'alt-text',
18
+ },
19
+ };
20
+ const buttonViews = [
21
+ 'normal',
22
+ 'action',
23
+ 'outlined',
24
+ 'outlined-info',
25
+ 'outlined-danger',
26
+ 'raised',
27
+ 'flat',
28
+ 'flat-info',
29
+ 'flat-danger',
30
+ 'flat-secondary',
31
+ 'normal-contrast',
32
+ 'outlined-contrast',
33
+ 'flat-contrast',
34
+ 'github',
35
+ 'scale',
36
+ 'monochrome',
37
+ ];
38
+ describe('Button', () => {
39
+ test('render button by default', async () => {
40
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text }));
41
+ const button = react_2.screen.getByRole('button');
42
+ expect(button).toBeInTheDocument();
43
+ expect(button).toBeVisible();
44
+ expect(button).not.toBeDisabled();
45
+ });
46
+ test('should render <a /> tag', async () => {
47
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, url: buttonProps.url, target: buttonProps.target }));
48
+ const button = react_2.screen.getByRole('link');
49
+ expect(button).toBeVisible();
50
+ expect(button).toHaveAttribute('href', buttonProps.url);
51
+ expect(button).toHaveAttribute('target', buttonProps.target);
52
+ });
53
+ test('call onClick', async () => {
54
+ const user = user_event_1.default.setup();
55
+ const handleOnClick = jest.fn();
56
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, onClick: handleOnClick }));
57
+ const button = react_2.screen.getByRole('button');
58
+ await user.click(button);
59
+ expect(handleOnClick).toHaveBeenCalledTimes(1);
60
+ });
61
+ test.each(new Array('s', 'm', 'l', 'xl'))('render with given "%s" size', (size) => {
62
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, size: size, qa: qaId }));
63
+ const button = react_2.screen.getByTestId(qaId);
64
+ expect(button).toHaveClass(`pc-button-block_size_${size}`);
65
+ });
66
+ test.each(new Array(...buttonViews))('render with given "%s" view', (theme) => {
67
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, theme: theme, qa: qaId }));
68
+ const button = react_2.screen.getByTestId(qaId);
69
+ expect(button).toHaveClass(`pc-button-block_theme_${theme}`);
70
+ });
71
+ test('add className', () => {
72
+ const className = 'my-class';
73
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, className: className, qa: qaId }));
74
+ const button = react_2.screen.getByTestId(qaId);
75
+ expect(button).toHaveClass(className);
76
+ });
77
+ test('should render icon', () => {
78
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, img: buttonProps.img }));
79
+ const button = react_2.screen.getByRole('button');
80
+ const iconComponent = react_2.screen.getByRole('img');
81
+ expect(iconComponent).toBeVisible();
82
+ expect(button).toContainElement(iconComponent);
83
+ });
84
+ test('should render github icon', () => {
85
+ (0, react_2.render)(react_1.default.createElement(Button_1.default, { text: buttonProps.text, img: buttonProps.img, theme: "github" }));
86
+ const button = react_2.screen.getByRole('button');
87
+ const iconComponent = react_2.screen.getByTestId(utils_1.ICON_QA);
88
+ expect(iconComponent).toBeVisible();
89
+ expect(button).toContainElement(iconComponent);
90
+ });
91
+ });
@@ -1,4 +1,5 @@
1
1
  import { ButtonSize, ButtonView } from '@gravity-ui/uikit';
2
+ export declare const ICON_QA = "button-icon";
2
3
  export type OldButtonTheme = 'normal' | 'action' | 'flat' | 'light' | 'clear' | 'raised' | 'pseudo' | 'link' | 'accent' | 'websearch' | 'flat-special' | 'normal-special' | 'normal-dark' | 'pseudo-special';
3
4
  export type OldButtonSize = 'xs' | 'ns' | 's' | 'm' | 'l' | 'n' | 'head' | 'promo';
4
5
  export declare const toCommonView: (theme: OldButtonTheme) => ButtonView;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toCommonSize = exports.toCommonView = void 0;
3
+ exports.toCommonSize = exports.toCommonView = exports.ICON_QA = void 0;
4
+ exports.ICON_QA = 'button-icon';
4
5
  const themeMap = {
5
6
  normal: 'normal',
6
7
  action: 'action',
@@ -1,4 +1,4 @@
1
- .pc-title-block_size_l, .pc-title-block_size_m, .pc-title-block_size_s {
1
+ .pc-title-block_size_l, .pc-title-block_size_m, .pc-title-block_size_s, .pc-title-block_size_xs {
2
2
  margin: 0;
3
3
  }
4
4
 
@@ -10,6 +10,12 @@ unpredictable css rules order in build */
10
10
  .pc-title-block_justify_end {
11
11
  text-align: right;
12
12
  }
13
+ .pc-title-block_size_xs {
14
+ font-size: var(--yc-text-body-3-font-size);
15
+ line-height: var(--yc-text-body-3-line-height);
16
+ color: var(--pc-text-header-color);
17
+ font-weight: var(--yc-text-accent-font-weight);
18
+ }
13
19
  .pc-title-block_size_s {
14
20
  font-size: var(--yc-text-header-1-font-size);
15
21
  line-height: var(--yc-text-header-1-line-height);
@@ -44,10 +50,13 @@ unpredictable css rules order in build */
44
50
  }
45
51
  }
46
52
  .pc-title-block__arrow {
47
- margin: 8px 0 0 4px;
53
+ margin-top: 10px;
54
+ }
55
+ .pc-title-block__arrow_size_xs {
56
+ margin-top: 7px;
48
57
  }
49
58
  .pc-title-block__arrow_size_s {
50
- margin: 4px 0 0 4px;
59
+ margin-top: 5px;
51
60
  }
52
61
  .pc-title-block__link {
53
62
  color: inherit;
@@ -62,7 +71,10 @@ unpredictable css rules order in build */
62
71
  cursor: pointer;
63
72
  }
64
73
  .pc-title-block__link:hover .pc-title-block__arrow {
65
- margin-left: 12px;
74
+ margin-left: 10px;
75
+ }
76
+ .pc-title-block__link:hover .pc-title-block__arrow_size_xs {
77
+ margin-left: 6px;
66
78
  }
67
79
  .pc-title-block__link:hover .pc-title-block__arrow_size_s {
68
80
  margin-left: 8px;
@@ -90,7 +102,10 @@ unpredictable css rules order in build */
90
102
  margin-top: 0;
91
103
  }
92
104
  @media (max-width: 577px) {
93
- .pc-title-block_size_l {
105
+ .pc-title-block_size_l:not(.pc-title-block_reset-margin) {
94
106
  margin-top: 48px;
95
107
  }
108
+ .pc-title-block__arrow_size_m, .pc-title-block__arrow_size_l {
109
+ margin-top: 9px;
110
+ }
96
111
  }
@@ -1,5 +1,5 @@
1
1
  import { TextSize, TitleProps } from '../../models';
2
- export declare function getArrowSize(size: TextSize, isMobile: boolean): 16 | 20 | 24;
2
+ export declare function getArrowSize(size: TextSize, isMobile: boolean): 16 | 13 | 20 | 24 | 22 | 26 | 38;
3
3
  export interface TitleFullProps extends TitleProps {
4
4
  className?: string;
5
5
  onClick?: () => void;
@@ -11,12 +11,14 @@ const mobileContext_1 = require("../../context/mobileContext");
11
11
  const b = (0, utils_1.block)('title-block');
12
12
  function getArrowSize(size, isMobile) {
13
13
  switch (size) {
14
+ case 'xs':
15
+ return 13;
14
16
  case 's':
15
17
  return 16;
16
18
  case 'm':
17
- return isMobile ? 20 : 24;
19
+ return isMobile ? 22 : 24;
18
20
  case 'l':
19
- return isMobile ? 20 : 24;
21
+ return isMobile ? 26 : 38;
20
22
  default:
21
23
  return 20;
22
24
  }
@@ -38,7 +38,7 @@ export declare enum MediaVideoControlsType {
38
38
  Custom = "custom"
39
39
  }
40
40
  export type TextTheme = 'light' | 'dark';
41
- export type TextSize = 's' | 'm' | 'l';
41
+ export type TextSize = 'xs' | 's' | 'm' | 'l';
42
42
  export type DividerSize = '0' | 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl' | 'xxxl';
43
43
  export type HeaderWidth = 's' | 'm' | 'l';
44
44
  export type HeaderImageSize = 's' | 'm';
@@ -130,20 +130,22 @@ export interface FileLinkProps extends ClassNameProps {
130
130
  theme?: ContentTheme;
131
131
  onClick?: () => void;
132
132
  }
133
+ export type ButtonTheme = ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
133
134
  export interface ButtonProps extends AnalyticsEventsBase {
134
135
  text: string;
135
136
  url: string;
136
137
  primary?: boolean;
137
138
  size?: ButtonSize;
138
- theme?: ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
139
+ theme?: ButtonTheme;
139
140
  img?: ButtonImageProps | string;
140
141
  metrikaGoals?: MetrikaGoal;
141
142
  pixelEvents?: ButtonPixel;
142
143
  target?: string;
143
144
  }
145
+ export type ButtonImagePosition = 'left' | 'right';
144
146
  export interface ButtonImageProps {
145
147
  url: string;
146
- position?: 'left' | 'right';
148
+ position?: ButtonImagePosition;
147
149
  alt?: string;
148
150
  }
149
151
  export interface PlayButtonProps extends ClassNameProps {
@@ -1,6 +1,6 @@
1
1
  import { ConstructorBlock } from '../models/constructor';
2
2
  import { TextSize, CustomConfig, PCShareSocialNetwork } from '../models';
3
- export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4";
3
+ export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4" | "h5";
4
4
  export declare function getBlockKey(block: ConstructorBlock, index: number): string;
5
5
  export declare const getCustomBlockTypes: ({ blocks, headers }?: CustomConfig) => string[];
6
6
  export declare const getCustomItems: ({ blocks, headers, subBlocks }?: CustomConfig) => {
@@ -8,6 +8,8 @@ function getHeaderTag(size) {
8
8
  return 'h1';
9
9
  case 's':
10
10
  return 'h4';
11
+ case 'xs':
12
+ return 'h5';
11
13
  case 'm':
12
14
  default:
13
15
  return 'h2';
@@ -16,18 +16,14 @@ unpredictable css rules order in build */
16
16
  .pc-filter-block__tabs {
17
17
  margin-bottom: 0;
18
18
  display: flex;
19
- flex-wrap: nowrap;
19
+ flex-wrap: wrap;
20
20
  justify-content: flex-start;
21
- overflow: auto;
22
21
  }
23
22
  .pc-filter-block__tabs_centered {
24
- display: flex;
25
23
  justify-content: center;
26
- flex-wrap: wrap;
27
24
  }
28
25
  @media (max-width: 769px) {
29
26
  .pc-filter-block__tabs {
30
- display: flex;
31
27
  flex-wrap: nowrap;
32
28
  justify-content: flex-start;
33
29
  overflow: auto;
@@ -16,18 +16,14 @@ unpredictable css rules order in build */
16
16
  .pc-tabs-block__tabs {
17
17
  margin-bottom: 20px;
18
18
  display: flex;
19
- flex-wrap: nowrap;
19
+ flex-wrap: wrap;
20
20
  justify-content: flex-start;
21
- overflow: auto;
22
21
  }
23
22
  .pc-tabs-block__tabs_centered {
24
- display: flex;
25
23
  justify-content: center;
26
- flex-wrap: wrap;
27
24
  }
28
25
  @media (max-width: 769px) {
29
26
  .pc-tabs-block__tabs {
30
- display: flex;
31
27
  flex-wrap: nowrap;
32
28
  justify-content: flex-start;
33
29
  overflow: auto;
@@ -7,10 +7,10 @@ unpredictable css rules order in build */
7
7
  font-size: var(--yc-text-body-3-font-size);
8
8
  line-height: var(--yc-text-body-3-line-height);
9
9
  }
10
- .pc-block-header__description_titleSize_s {
10
+ .pc-block-header__description_titleSize_s, .pc-block-header__description_titleSize_xs {
11
11
  margin-top: 8px;
12
12
  }
13
- .pc-block-header__description_titleSize_s .yfm {
13
+ .pc-block-header__description_titleSize_s .yfm, .pc-block-header__description_titleSize_xs .yfm {
14
14
  font-size: var(--yc-text-body-2-font-size);
15
15
  line-height: var(--yc-text-body-2-line-height);
16
16
  }
@@ -4,6 +4,7 @@ export interface ButtonProps extends Omit<ButtonParams, 'url'> {
4
4
  className?: string;
5
5
  url?: string;
6
6
  onClick?: () => void;
7
+ qa?: string;
7
8
  }
8
9
  declare const Button: (props: ButtonProps) => JSX.Element;
9
10
  export default Button;
@@ -3,7 +3,7 @@ import React, { useCallback, useContext } from 'react';
3
3
  import { Platform, Button as CommonButton, Icon, StoreBadge } from '@gravity-ui/uikit';
4
4
  import { block, setUrlTld } from '../../utils';
5
5
  import { DefaultEventNames } from '../../models';
6
- import { toCommonSize, toCommonView } from './utils';
6
+ import { toCommonSize, toCommonView, ICON_QA } from './utils';
7
7
  import { LocaleContext } from '../../context/localeContext/localeContext';
8
8
  import { useMetrika } from '../../hooks/useMetrika';
9
9
  import { useAnalytics } from '../../hooks';
@@ -37,7 +37,7 @@ const Button = (props) => {
37
37
  let icon;
38
38
  let image = img && React.createElement("img", { className: b('image'), src: buttonImg.url, alt: buttonImg.alt });
39
39
  if (theme === 'github') {
40
- icon = React.createElement(Icon, { className: b('icon'), data: Github, size: 24 });
40
+ icon = React.createElement(Icon, { className: b('icon'), data: Github, size: 24, qa: ICON_QA });
41
41
  image = undefined;
42
42
  }
43
43
  const buttonTheme = theme === 'scale' ? 'accent' : theme;
@@ -0,0 +1,88 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { ICON_QA } from '../utils';
5
+ import Button from '../Button';
6
+ const qaId = 'button-component';
7
+ const buttonProps = {
8
+ text: 'Button Text',
9
+ url: 'https://github.com/gravity-ui/',
10
+ target: '_blank',
11
+ img: {
12
+ url: 'https://storage.yandexcloud.net/cloud-www-assets/constructor/storybook/images/icon_1_light.svg',
13
+ position: 'left',
14
+ alt: 'alt-text',
15
+ },
16
+ };
17
+ const buttonViews = [
18
+ 'normal',
19
+ 'action',
20
+ 'outlined',
21
+ 'outlined-info',
22
+ 'outlined-danger',
23
+ 'raised',
24
+ 'flat',
25
+ 'flat-info',
26
+ 'flat-danger',
27
+ 'flat-secondary',
28
+ 'normal-contrast',
29
+ 'outlined-contrast',
30
+ 'flat-contrast',
31
+ 'github',
32
+ 'scale',
33
+ 'monochrome',
34
+ ];
35
+ describe('Button', () => {
36
+ test('render button by default', async () => {
37
+ render(React.createElement(Button, { text: buttonProps.text }));
38
+ const button = screen.getByRole('button');
39
+ expect(button).toBeInTheDocument();
40
+ expect(button).toBeVisible();
41
+ expect(button).not.toBeDisabled();
42
+ });
43
+ test('should render <a /> tag', async () => {
44
+ render(React.createElement(Button, { text: buttonProps.text, url: buttonProps.url, target: buttonProps.target }));
45
+ const button = screen.getByRole('link');
46
+ expect(button).toBeVisible();
47
+ expect(button).toHaveAttribute('href', buttonProps.url);
48
+ expect(button).toHaveAttribute('target', buttonProps.target);
49
+ });
50
+ test('call onClick', async () => {
51
+ const user = userEvent.setup();
52
+ const handleOnClick = jest.fn();
53
+ render(React.createElement(Button, { text: buttonProps.text, onClick: handleOnClick }));
54
+ const button = screen.getByRole('button');
55
+ await user.click(button);
56
+ expect(handleOnClick).toHaveBeenCalledTimes(1);
57
+ });
58
+ test.each(new Array('s', 'm', 'l', 'xl'))('render with given "%s" size', (size) => {
59
+ render(React.createElement(Button, { text: buttonProps.text, size: size, qa: qaId }));
60
+ const button = screen.getByTestId(qaId);
61
+ expect(button).toHaveClass(`pc-button-block_size_${size}`);
62
+ });
63
+ test.each(new Array(...buttonViews))('render with given "%s" view', (theme) => {
64
+ render(React.createElement(Button, { text: buttonProps.text, theme: theme, qa: qaId }));
65
+ const button = screen.getByTestId(qaId);
66
+ expect(button).toHaveClass(`pc-button-block_theme_${theme}`);
67
+ });
68
+ test('add className', () => {
69
+ const className = 'my-class';
70
+ render(React.createElement(Button, { text: buttonProps.text, className: className, qa: qaId }));
71
+ const button = screen.getByTestId(qaId);
72
+ expect(button).toHaveClass(className);
73
+ });
74
+ test('should render icon', () => {
75
+ render(React.createElement(Button, { text: buttonProps.text, img: buttonProps.img }));
76
+ const button = screen.getByRole('button');
77
+ const iconComponent = screen.getByRole('img');
78
+ expect(iconComponent).toBeVisible();
79
+ expect(button).toContainElement(iconComponent);
80
+ });
81
+ test('should render github icon', () => {
82
+ render(React.createElement(Button, { text: buttonProps.text, img: buttonProps.img, theme: "github" }));
83
+ const button = screen.getByRole('button');
84
+ const iconComponent = screen.getByTestId(ICON_QA);
85
+ expect(iconComponent).toBeVisible();
86
+ expect(button).toContainElement(iconComponent);
87
+ });
88
+ });
@@ -1,4 +1,5 @@
1
1
  import { ButtonSize, ButtonView } from '@gravity-ui/uikit';
2
+ export declare const ICON_QA = "button-icon";
2
3
  export type OldButtonTheme = 'normal' | 'action' | 'flat' | 'light' | 'clear' | 'raised' | 'pseudo' | 'link' | 'accent' | 'websearch' | 'flat-special' | 'normal-special' | 'normal-dark' | 'pseudo-special';
3
4
  export type OldButtonSize = 'xs' | 'ns' | 's' | 'm' | 'l' | 'n' | 'head' | 'promo';
4
5
  export declare const toCommonView: (theme: OldButtonTheme) => ButtonView;
@@ -1,3 +1,4 @@
1
+ export const ICON_QA = 'button-icon';
1
2
  const themeMap = {
2
3
  normal: 'normal',
3
4
  action: 'action',
@@ -1,4 +1,4 @@
1
- .pc-title-block_size_l, .pc-title-block_size_m, .pc-title-block_size_s {
1
+ .pc-title-block_size_l, .pc-title-block_size_m, .pc-title-block_size_s, .pc-title-block_size_xs {
2
2
  margin: 0;
3
3
  }
4
4
 
@@ -10,6 +10,12 @@ unpredictable css rules order in build */
10
10
  .pc-title-block_justify_end {
11
11
  text-align: right;
12
12
  }
13
+ .pc-title-block_size_xs {
14
+ font-size: var(--yc-text-body-3-font-size);
15
+ line-height: var(--yc-text-body-3-line-height);
16
+ color: var(--pc-text-header-color);
17
+ font-weight: var(--yc-text-accent-font-weight);
18
+ }
13
19
  .pc-title-block_size_s {
14
20
  font-size: var(--yc-text-header-1-font-size);
15
21
  line-height: var(--yc-text-header-1-line-height);
@@ -44,10 +50,13 @@ unpredictable css rules order in build */
44
50
  }
45
51
  }
46
52
  .pc-title-block__arrow {
47
- margin: 8px 0 0 4px;
53
+ margin-top: 10px;
54
+ }
55
+ .pc-title-block__arrow_size_xs {
56
+ margin-top: 7px;
48
57
  }
49
58
  .pc-title-block__arrow_size_s {
50
- margin: 4px 0 0 4px;
59
+ margin-top: 5px;
51
60
  }
52
61
  .pc-title-block__link {
53
62
  color: inherit;
@@ -62,7 +71,10 @@ unpredictable css rules order in build */
62
71
  cursor: pointer;
63
72
  }
64
73
  .pc-title-block__link:hover .pc-title-block__arrow {
65
- margin-left: 12px;
74
+ margin-left: 10px;
75
+ }
76
+ .pc-title-block__link:hover .pc-title-block__arrow_size_xs {
77
+ margin-left: 6px;
66
78
  }
67
79
  .pc-title-block__link:hover .pc-title-block__arrow_size_s {
68
80
  margin-left: 8px;
@@ -90,7 +102,10 @@ unpredictable css rules order in build */
90
102
  margin-top: 0;
91
103
  }
92
104
  @media (max-width: 577px) {
93
- .pc-title-block_size_l {
105
+ .pc-title-block_size_l:not(.pc-title-block_reset-margin) {
94
106
  margin-top: 48px;
95
107
  }
108
+ .pc-title-block__arrow_size_m, .pc-title-block__arrow_size_l {
109
+ margin-top: 9px;
110
+ }
96
111
  }
@@ -1,6 +1,6 @@
1
1
  import { TextSize, TitleProps } from '../../models';
2
2
  import './Title.css';
3
- export declare function getArrowSize(size: TextSize, isMobile: boolean): 16 | 20 | 24;
3
+ export declare function getArrowSize(size: TextSize, isMobile: boolean): 16 | 13 | 20 | 24 | 22 | 26 | 38;
4
4
  export interface TitleFullProps extends TitleProps {
5
5
  className?: string;
6
6
  onClick?: () => void;
@@ -8,12 +8,14 @@ import './Title.css';
8
8
  const b = block('title-block');
9
9
  export function getArrowSize(size, isMobile) {
10
10
  switch (size) {
11
+ case 'xs':
12
+ return 13;
11
13
  case 's':
12
14
  return 16;
13
15
  case 'm':
14
- return isMobile ? 20 : 24;
16
+ return isMobile ? 22 : 24;
15
17
  case 'l':
16
- return isMobile ? 20 : 24;
18
+ return isMobile ? 26 : 38;
17
19
  default:
18
20
  return 20;
19
21
  }
@@ -38,7 +38,7 @@ export declare enum MediaVideoControlsType {
38
38
  Custom = "custom"
39
39
  }
40
40
  export type TextTheme = 'light' | 'dark';
41
- export type TextSize = 's' | 'm' | 'l';
41
+ export type TextSize = 'xs' | 's' | 'm' | 'l';
42
42
  export type DividerSize = '0' | 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl' | 'xxxl';
43
43
  export type HeaderWidth = 's' | 'm' | 'l';
44
44
  export type HeaderImageSize = 's' | 'm';
@@ -130,20 +130,22 @@ export interface FileLinkProps extends ClassNameProps {
130
130
  theme?: ContentTheme;
131
131
  onClick?: () => void;
132
132
  }
133
+ export type ButtonTheme = ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
133
134
  export interface ButtonProps extends AnalyticsEventsBase {
134
135
  text: string;
135
136
  url: string;
136
137
  primary?: boolean;
137
138
  size?: ButtonSize;
138
- theme?: ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
139
+ theme?: ButtonTheme;
139
140
  img?: ButtonImageProps | string;
140
141
  metrikaGoals?: MetrikaGoal;
141
142
  pixelEvents?: ButtonPixel;
142
143
  target?: string;
143
144
  }
145
+ export type ButtonImagePosition = 'left' | 'right';
144
146
  export interface ButtonImageProps {
145
147
  url: string;
146
- position?: 'left' | 'right';
148
+ position?: ButtonImagePosition;
147
149
  alt?: string;
148
150
  }
149
151
  export interface PlayButtonProps extends ClassNameProps {
@@ -1,6 +1,6 @@
1
1
  import { ConstructorBlock } from '../models/constructor';
2
2
  import { TextSize, CustomConfig, PCShareSocialNetwork } from '../models';
3
- export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4";
3
+ export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4" | "h5";
4
4
  export declare function getBlockKey(block: ConstructorBlock, index: number): string;
5
5
  export declare const getCustomBlockTypes: ({ blocks, headers }?: CustomConfig) => string[];
6
6
  export declare const getCustomItems: ({ blocks, headers, subBlocks }?: CustomConfig) => {
@@ -5,6 +5,8 @@ export function getHeaderTag(size) {
5
5
  return 'h1';
6
6
  case 's':
7
7
  return 'h4';
8
+ case 'xs':
9
+ return 'h5';
8
10
  case 'm':
9
11
  default:
10
12
  return 'h2';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/page-constructor",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "Gravity UI Page Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@ export declare enum MediaVideoControlsType {
38
38
  Custom = "custom"
39
39
  }
40
40
  export type TextTheme = 'light' | 'dark';
41
- export type TextSize = 's' | 'm' | 'l';
41
+ export type TextSize = 'xs' | 's' | 'm' | 'l';
42
42
  export type DividerSize = '0' | 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl' | 'xxxl';
43
43
  export type HeaderWidth = 's' | 'm' | 'l';
44
44
  export type HeaderImageSize = 's' | 'm';
@@ -130,20 +130,22 @@ export interface FileLinkProps extends ClassNameProps {
130
130
  theme?: ContentTheme;
131
131
  onClick?: () => void;
132
132
  }
133
+ export type ButtonTheme = ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
133
134
  export interface ButtonProps extends AnalyticsEventsBase {
134
135
  text: string;
135
136
  url: string;
136
137
  primary?: boolean;
137
138
  size?: ButtonSize;
138
- theme?: ButtonView | 'github' | 'app-store' | 'google-play' | 'scale' | 'monochrome';
139
+ theme?: ButtonTheme;
139
140
  img?: ButtonImageProps | string;
140
141
  metrikaGoals?: MetrikaGoal;
141
142
  pixelEvents?: ButtonPixel;
142
143
  target?: string;
143
144
  }
145
+ export type ButtonImagePosition = 'left' | 'right';
144
146
  export interface ButtonImageProps {
145
147
  url: string;
146
- position?: 'left' | 'right';
148
+ position?: ButtonImagePosition;
147
149
  alt?: string;
148
150
  }
149
151
  export interface PlayButtonProps extends ClassNameProps {
@@ -1,6 +1,6 @@
1
1
  import { ConstructorBlock } from '../models/constructor';
2
2
  import { TextSize, CustomConfig, PCShareSocialNetwork } from '../models';
3
- export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4";
3
+ export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4" | "h5";
4
4
  export declare function getBlockKey(block: ConstructorBlock, index: number): string;
5
5
  export declare const getCustomBlockTypes: ({ blocks, headers }?: CustomConfig) => string[];
6
6
  export declare const getCustomItems: ({ blocks, headers, subBlocks }?: CustomConfig) => {
@@ -8,6 +8,8 @@ function getHeaderTag(size) {
8
8
  return 'h1';
9
9
  case 's':
10
10
  return 'h4';
11
+ case 'xs':
12
+ return 'h5';
11
13
  case 'm':
12
14
  default:
13
15
  return 'h2';
@@ -141,15 +141,17 @@
141
141
  }
142
142
 
143
143
  @mixin label($size: m) {
144
- @include text-size(body-1);
144
+ @if $size == m {
145
+ @include text-size(body-1);
145
146
 
146
- $label-height: 20px;
147
+ $label-height: 20px;
147
148
 
148
- display: inline-block;
149
- padding: 0 8px;
150
- border-radius: 2px;
151
- height: $label-height;
152
- line-height: $label-height;
149
+ display: inline-block;
150
+ padding: 0 8px;
151
+ border-radius: 2px;
152
+ height: $label-height;
153
+ line-height: $label-height;
154
+ }
153
155
 
154
156
  @if $size == s {
155
157
  @include text-size(caption-2);
@@ -518,18 +520,14 @@ unpredictable css rules order in build */
518
520
 
519
521
  @mixin tab-panel() {
520
522
  display: flex;
521
- flex-wrap: nowrap;
523
+ flex-wrap: wrap;
522
524
  justify-content: flex-start;
523
- overflow: auto;
524
525
 
525
526
  &_centered {
526
- display: flex;
527
527
  justify-content: center;
528
- flex-wrap: wrap;
529
528
  }
530
529
 
531
530
  @media (max-width: map-get($gridBreakpoints, 'md')) {
532
- display: flex;
533
531
  flex-wrap: nowrap;
534
532
  justify-content: flex-start;
535
533
  overflow: auto;