@gravity-ui/page-constructor 4.1.1 → 4.3.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 (84) hide show
  1. package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.js +7 -3
  2. package/build/cjs/blocks/FilterBlock/schema.d.ts +6 -0
  3. package/build/cjs/blocks/FilterBlock/schema.js +2 -2
  4. package/build/cjs/blocks/PromoFeaturesBlock/PromoFeaturesBlock.js +1 -1
  5. package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +50 -0
  6. package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.d.ts +2 -0
  7. package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.js +27 -0
  8. package/build/cjs/blocks/Questions/Questions.css +0 -48
  9. package/build/cjs/blocks/Questions/Questions.js +7 -27
  10. package/build/cjs/blocks/Questions/models.d.ts +10 -0
  11. package/build/cjs/blocks/Questions/models.js +13 -0
  12. package/build/cjs/components/BackLink/BackLink.d.ts +2 -1
  13. package/build/cjs/components/BackLink/BackLink.js +2 -2
  14. package/build/cjs/components/FileLink/FileLink.js +2 -2
  15. package/build/cjs/components/FullscreenImage/FullscreenImage.js +1 -1
  16. package/build/cjs/components/FullscreenImage/i18n/en.json +2 -1
  17. package/build/cjs/components/FullscreenImage/i18n/ru.json +2 -1
  18. package/build/cjs/components/Image/i18n/en.json +1 -1
  19. package/build/cjs/components/Image/i18n/ru.json +1 -1
  20. package/build/cjs/components/Link/Link.d.ts +2 -2
  21. package/build/cjs/components/Link/Link.js +6 -6
  22. package/build/cjs/components/Media/Media.js +1 -2
  23. package/build/cjs/components/Media/Video/Video.js +3 -3
  24. package/build/cjs/components/ReactPlayer/ReactPlayer.js +4 -3
  25. package/build/cjs/components/ReactPlayer/i18n/en.json +3 -0
  26. package/build/cjs/components/ReactPlayer/i18n/index.d.ts +2 -0
  27. package/build/cjs/components/ReactPlayer/i18n/index.js +8 -0
  28. package/build/cjs/components/ReactPlayer/i18n/ru.json +3 -0
  29. package/build/cjs/components/constants.d.ts +0 -4
  30. package/build/cjs/components/constants.js +1 -5
  31. package/build/cjs/grid/Col/Col.d.ts +2 -1
  32. package/build/cjs/grid/Col/Col.js +2 -2
  33. package/build/cjs/models/constructor-items/blocks.d.ts +4 -0
  34. package/build/cjs/models/constructor-items/common.d.ts +7 -3
  35. package/build/cjs/sub-blocks/Content/ContentList/ContentList.js +11 -1
  36. package/build/cjs/sub-blocks/LayoutItem/utils.d.ts +1 -0
  37. package/build/cjs/utils/blocks.d.ts +1 -1
  38. package/build/cjs/utils/blocks.js +2 -2
  39. package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.js +7 -3
  40. package/build/esm/blocks/FilterBlock/schema.d.ts +6 -0
  41. package/build/esm/blocks/FilterBlock/schema.js +2 -2
  42. package/build/esm/blocks/PromoFeaturesBlock/PromoFeaturesBlock.js +1 -1
  43. package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +50 -0
  44. package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.d.ts +3 -0
  45. package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.js +23 -0
  46. package/build/esm/blocks/Questions/Questions.css +0 -48
  47. package/build/esm/blocks/Questions/Questions.js +6 -26
  48. package/build/esm/blocks/Questions/models.d.ts +10 -0
  49. package/build/esm/blocks/Questions/models.js +10 -0
  50. package/build/esm/components/BackLink/BackLink.d.ts +2 -1
  51. package/build/esm/components/BackLink/BackLink.js +2 -2
  52. package/build/esm/components/FileLink/FileLink.js +2 -2
  53. package/build/esm/components/FullscreenImage/FullscreenImage.js +1 -1
  54. package/build/esm/components/FullscreenImage/i18n/en.json +2 -1
  55. package/build/esm/components/FullscreenImage/i18n/ru.json +2 -1
  56. package/build/esm/components/Image/i18n/en.json +1 -1
  57. package/build/esm/components/Image/i18n/ru.json +1 -1
  58. package/build/esm/components/Link/Link.d.ts +2 -2
  59. package/build/esm/components/Link/Link.js +7 -7
  60. package/build/esm/components/Media/Media.js +1 -2
  61. package/build/esm/components/Media/Video/Video.js +3 -3
  62. package/build/esm/components/ReactPlayer/ReactPlayer.js +4 -3
  63. package/build/esm/components/ReactPlayer/i18n/en.json +3 -0
  64. package/build/esm/components/ReactPlayer/i18n/index.d.ts +2 -0
  65. package/build/esm/components/ReactPlayer/i18n/index.js +5 -0
  66. package/build/esm/components/ReactPlayer/i18n/ru.json +3 -0
  67. package/build/esm/components/constants.d.ts +0 -4
  68. package/build/esm/components/constants.js +0 -4
  69. package/build/esm/grid/Col/Col.d.ts +2 -1
  70. package/build/esm/grid/Col/Col.js +2 -2
  71. package/build/esm/models/constructor-items/blocks.d.ts +4 -0
  72. package/build/esm/models/constructor-items/common.d.ts +7 -3
  73. package/build/esm/sub-blocks/Content/ContentList/ContentList.js +11 -1
  74. package/build/esm/sub-blocks/LayoutItem/utils.d.ts +1 -0
  75. package/build/esm/utils/blocks.d.ts +1 -1
  76. package/build/esm/utils/blocks.js +2 -2
  77. package/package.json +3 -3
  78. package/server/components/constants.d.ts +0 -4
  79. package/server/components/constants.js +1 -5
  80. package/server/models/constructor-items/blocks.d.ts +4 -0
  81. package/server/models/constructor-items/common.d.ts +7 -3
  82. package/server/utils/blocks.d.ts +1 -1
  83. package/server/utils/blocks.js +2 -2
  84. package/widget/index.js +1 -1
@@ -1,6 +1,6 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
2
  import { ButtonView, ButtonProps as UikitButtonProps } from '@gravity-ui/uikit';
3
- import { ThemeSupporting } from '../../utils/theme';
3
+ import { ThemeSupporting } from '../../utils';
4
4
  import { AnalyticsEventsBase, ClassNameProps, PixelEventType, QAProps } from '../common';
5
5
  export declare enum AuthorType {
6
6
  Column = "column",
@@ -61,6 +61,9 @@ export interface Stylable {
61
61
  export interface Animatable {
62
62
  animated?: boolean;
63
63
  }
64
+ export interface Tabbable {
65
+ tabIndex?: number;
66
+ }
64
67
  export interface Background {
65
68
  image?: string;
66
69
  color?: string;
@@ -106,7 +109,7 @@ export interface MediaVideoProps extends AnalyticsEventsBase {
106
109
  controls?: MediaVideoControlsType;
107
110
  metrika?: MetrikaVideo;
108
111
  }
109
- export interface LinkProps extends AnalyticsEventsBase, Stylable {
112
+ export interface LinkProps extends AnalyticsEventsBase, Stylable, Tabbable {
110
113
  url: string;
111
114
  text?: string;
112
115
  textSize?: TextSize;
@@ -117,7 +120,7 @@ export interface LinkProps extends AnalyticsEventsBase, Stylable {
117
120
  metrikaGoals?: MetrikaGoal;
118
121
  pixelEvents?: ButtonPixel;
119
122
  }
120
- export interface FileLinkProps extends ClassNameProps {
123
+ export interface FileLinkProps extends ClassNameProps, Tabbable {
121
124
  href: string;
122
125
  text: ReactNode;
123
126
  type?: FileLinkType;
@@ -157,6 +160,7 @@ export interface MediaVideoProps {
157
160
  playButton?: PlayButtonProps;
158
161
  controls?: MediaVideoControlsType;
159
162
  metrika?: MetrikaVideo;
163
+ ariaLabel?: string;
160
164
  }
161
165
  export type ThemedMediaVideoProps = ThemeSupporting<MediaVideoProps>;
162
166
  export interface MediaComponentVideoProps extends AnalyticsEventsBase {
@@ -9,6 +9,15 @@ const utils_1 = require("../../../components/Media/Image/utils");
9
9
  const theme_1 = require("../../../context/theme");
10
10
  const utils_2 = require("../../../utils");
11
11
  const b = (0, utils_2.block)('content-list');
12
+ function getHeadingLevel(size) {
13
+ switch (size) {
14
+ case 's':
15
+ return 'h4';
16
+ case 'l':
17
+ default:
18
+ return 'h3';
19
+ }
20
+ }
12
21
  const ContentList = ({ list, size }) => {
13
22
  const theme = (0, theme_1.useTheme)();
14
23
  return (react_1.default.createElement("div", { className: b({ size }) }, list === null || list === void 0 ? void 0 : list.map((item) => {
@@ -18,7 +27,8 @@ const ContentList = ({ list, size }) => {
18
27
  return (react_1.default.createElement("div", { className: b('item'), key: (0, uuid_1.v4)() },
19
28
  react_1.default.createElement(Image_1.default, Object.assign({}, iconData, { className: b('icon') })),
20
29
  react_1.default.createElement("div", null,
21
- title && react_1.default.createElement("h4", { className: b('title') }, title),
30
+ title &&
31
+ react_1.default.createElement(getHeadingLevel(size), { className: b('title') }, title),
22
32
  text && (react_1.default.createElement(components_1.YFMWrapper, { className: b('text'), content: text, modifiers: { constructor: true } })))));
23
33
  })));
24
34
  };
@@ -23,6 +23,7 @@ export declare const getLayoutItemLinks: (links: LayoutItemProps['content']['lin
23
23
  target?: string | undefined;
24
24
  }[] | undefined;
25
25
  className?: string | undefined;
26
+ tabIndex?: number | undefined;
26
27
  }[] | undefined;
27
28
  export declare const hasFullscreen: ({ dataLens, image }: MediaProps) => boolean;
28
29
  export declare const showFullscreenIcon: ({ youtube }: MediaProps) => boolean;
@@ -1,5 +1,5 @@
1
1
  import { ConstructorBlock, CustomConfig, PCShareSocialNetwork, TextSize } from '../models';
2
- export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h4" | "h5";
2
+ export declare function getHeaderTag(size: TextSize): "h1" | "h2" | "h3" | "h4";
3
3
  export declare function hasBlockTag(content: string): boolean;
4
4
  export declare function getBlockKey(block: ConstructorBlock, index: number): string;
5
5
  export declare const getCustomBlockTypes: ({ blocks, headers }?: CustomConfig) => string[];
@@ -44,9 +44,9 @@ function getHeaderTag(size) {
44
44
  case 'l':
45
45
  return 'h1';
46
46
  case 's':
47
- return 'h4';
47
+ return 'h3';
48
48
  case 'xs':
49
- return 'h5';
49
+ return 'h4';
50
50
  case 'm':
51
51
  default:
52
52
  return 'h2';
@@ -15,6 +15,7 @@ const DEFAULT_SIZES = {
15
15
  };
16
16
  export const ExtendedFeaturesBlock = ({ title, description, items, colSizes = DEFAULT_SIZES, animated, }) => {
17
17
  const theme = useTheme();
18
+ const itemTitleHeadingTag = title ? 'h3' : 'h2';
18
19
  return (React.createElement(AnimateBlock, { className: b(), animate: animated },
19
20
  React.createElement(Title, { title: title, subtitle: description, className: b('header') }),
20
21
  React.createElement("div", { className: b('items') },
@@ -28,9 +29,12 @@ export const ExtendedFeaturesBlock = ({ title, description, items, colSizes = DE
28
29
  return (React.createElement(Col, { className: b('item'), key: text || itemTitle, sizes: colSizes },
29
30
  iconData && React.createElement(Image, Object.assign({}, iconData, { className: b('icon') })),
30
31
  React.createElement("div", { className: b('container') },
31
- itemTitle && (React.createElement("h5", { className: b('item-title') },
32
- React.createElement(HTML, null, itemTitle),
33
- label && (React.createElement("span", { className: b('item-label') }, label)))),
32
+ itemTitle &&
33
+ React.createElement(itemTitleHeadingTag, {
34
+ className: b('item-title'),
35
+ }, React.createElement(React.Fragment, null,
36
+ React.createElement(HTML, null, itemTitle),
37
+ label && (React.createElement("span", { className: b('item-label') }, label)))),
34
38
  React.createElement(Content, { text: text, links: itemLinks, size: "s", colSizes: { all: 12, md: 12 }, buttons: buttons, additionalInfo: additionalInfo }))));
35
39
  })))));
36
40
  };
@@ -66,6 +66,9 @@ export declare const FilterProps: {
66
66
  type: string;
67
67
  enum: string[];
68
68
  };
69
+ centered: {
70
+ type: string;
71
+ };
69
72
  title: {
70
73
  oneOf: ({
71
74
  type: string;
@@ -173,6 +176,9 @@ export declare const FilterBlock: {
173
176
  type: string;
174
177
  enum: string[];
175
178
  };
179
+ centered: {
180
+ type: string;
181
+ };
176
182
  title: {
177
183
  oneOf: ({
178
184
  type: string;
@@ -27,7 +27,7 @@ export const FilterItemProps = {
27
27
  };
28
28
  export const FilterProps = {
29
29
  additionalProperties: false,
30
- required: ['filterTags', 'block'],
30
+ required: ['tags', 'items'],
31
31
  properties: Object.assign(Object.assign(Object.assign(Object.assign({}, BlockBaseProps), AnimatableProps), BlockHeaderProps), { allTag: {
32
32
  oneOf: [
33
33
  {
@@ -42,7 +42,7 @@ export const FilterProps = {
42
42
  }, colSizes: containerSizesObject, tags: filteredArray(FilterTagProps), items: filteredArray(FilterItemProps), tagButtonSize: {
43
43
  type: 'string',
44
44
  enum: ['s', 'm', 'l', 'xl'],
45
- } }),
45
+ }, centered: { type: 'boolean' } }),
46
46
  };
47
47
  export const FilterBlock = {
48
48
  'filter-block': FilterProps,
@@ -28,7 +28,7 @@ const PromoFeaturesBlock = (props) => {
28
28
  [themeMod]: Boolean(themeMod),
29
29
  }) },
30
30
  React.createElement("div", { className: b('card-info') },
31
- React.createElement("h4", { className: b('card-title') }, cardTitle),
31
+ React.createElement("h3", { className: b('card-title') }, cardTitle),
32
32
  React.createElement("div", { className: b('card-text') },
33
33
  React.createElement(YFMWrapper, { content: text, modifiers: { constructor: true } }))),
34
34
  media && React.createElement(Media, Object.assign({ className: b('card-media') }, media))));
@@ -0,0 +1,50 @@
1
+ .pc-QuestionsBlockItem__title {
2
+ margin: 0;
3
+ }
4
+
5
+ /* use this for style redefinitions to awoid problems with
6
+ unpredictable css rules order in build */
7
+ .pc-QuestionsBlockItem {
8
+ padding-bottom: 32px;
9
+ border-bottom: 1px solid var(--g-color-line-generic);
10
+ }
11
+ .pc-QuestionsBlockItem + .pc-QuestionsBlockItem {
12
+ padding-top: 32px;
13
+ }
14
+ .pc-QuestionsBlockItem__title {
15
+ font-size: var(--g-text-header-1-font-size);
16
+ line-height: var(--g-text-header-1-line-height);
17
+ color: var(--pc-text-header-color);
18
+ font-weight: var(--g-text-accent-font-weight);
19
+ position: relative;
20
+ padding-right: 24px;
21
+ cursor: pointer;
22
+ }
23
+ .pc-QuestionsBlockItem__title a {
24
+ outline: none;
25
+ color: var(--g-color-text-link);
26
+ text-decoration: none;
27
+ cursor: pointer;
28
+ }
29
+ .utilityfocus .pc-QuestionsBlockItem__title a:focus {
30
+ outline: 2px solid #ffdb4d;
31
+ }
32
+ .pc-QuestionsBlockItem__title a:hover, .pc-QuestionsBlockItem__title a:active {
33
+ --pc-text-header-color: var(--g-color-text-link-hover);
34
+ color: var(--g-color-text-link-hover);
35
+ }
36
+ .pc-QuestionsBlockItem__arrow {
37
+ position: absolute;
38
+ right: 0;
39
+ top: 0;
40
+ color: var(--g-color-text-primary);
41
+ }
42
+ .pc-QuestionsBlockItem__link {
43
+ font-size: var(--g-text-body-2-font-size);
44
+ line-height: var(--g-text-body-2-line-height);
45
+ }
46
+ .pc-QuestionsBlockItem__text {
47
+ font-size: var(--g-text-body-2-font-size);
48
+ line-height: var(--g-text-body-2-line-height);
49
+ margin-top: 12px;
50
+ }
@@ -0,0 +1,3 @@
1
+ import { QuestionBlockItemProps } from '../../../models';
2
+ import './QuestionBlockItem.css';
3
+ export declare const QuestionBlockItem: ({ title: itemTitle, text: itemText, link, listStyle, isOpened, onClick, }: QuestionBlockItemProps) => JSX.Element;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { useActionHandlers } from '@gravity-ui/uikit';
3
+ import { Foldable, HTML, ToggleArrow, YFMWrapper } from '../../../components';
4
+ import Link from '../../../components/Link/Link';
5
+ import { block } from '../../../utils';
6
+ import { FaqMicrodataValues } from '../models';
7
+ import './QuestionBlockItem.css';
8
+ const b = block('QuestionsBlockItem');
9
+ export const QuestionBlockItem = ({ title: itemTitle, text: itemText, link, listStyle = 'dash', isOpened, onClick, }) => {
10
+ const { onKeyDown } = useActionHandlers(onClick);
11
+ return (React.createElement("div", { className: b(), itemScope: true, itemProp: FaqMicrodataValues.QuestionProp, itemType: FaqMicrodataValues.QuestionType, role: 'listitem' },
12
+ React.createElement("h3", { className: b('title'), onClick: onClick, "aria-expanded": isOpened, role: 'button', tabIndex: 0, onKeyDown: onKeyDown },
13
+ React.createElement(HTML, { itemProp: FaqMicrodataValues.QuestionNameProp }, itemTitle),
14
+ React.createElement(ToggleArrow, { open: isOpened, size: 16, type: 'vertical', iconType: "navigation", className: b('arrow') })),
15
+ React.createElement(Foldable, { isOpened: isOpened },
16
+ React.createElement("div", { className: b('text'), itemScope: true, itemProp: FaqMicrodataValues.AnswerProp, itemType: FaqMicrodataValues.AnswerType, "aria-hidden": !isOpened },
17
+ React.createElement(YFMWrapper, { content: itemText, modifiers: {
18
+ constructor: true,
19
+ constructorListStyle: true,
20
+ constructorListStyleDash: listStyle === 'dash',
21
+ }, itemProp: FaqMicrodataValues.QuestionTextProp }),
22
+ link && React.createElement(Link, Object.assign({}, link, { tabIndex: isOpened ? 0 : -1, className: b('link') }))))));
23
+ };
@@ -1,7 +1,3 @@
1
- .pc-QuestionsBlock__item-title {
2
- margin: 0;
3
- }
4
-
5
1
  /* use this for style redefinitions to awoid problems with
6
2
  unpredictable css rules order in build */
7
3
  .pc-QuestionsBlock__title {
@@ -10,50 +6,6 @@ unpredictable css rules order in build */
10
6
  margin-bottom: 32px;
11
7
  margin-right: 64px;
12
8
  }
13
- .pc-QuestionsBlock__item {
14
- padding-bottom: 32px;
15
- border-bottom: 1px solid var(--g-color-line-generic);
16
- }
17
- .pc-QuestionsBlock__item + .pc-QuestionsBlock__item {
18
- padding-top: 32px;
19
- }
20
- .pc-QuestionsBlock__item-title {
21
- font-size: var(--g-text-header-1-font-size);
22
- line-height: var(--g-text-header-1-line-height);
23
- color: var(--pc-text-header-color);
24
- font-weight: var(--g-text-accent-font-weight);
25
- position: relative;
26
- padding-right: 24px;
27
- cursor: pointer;
28
- }
29
- .pc-QuestionsBlock__item-title a {
30
- outline: none;
31
- color: var(--g-color-text-link);
32
- text-decoration: none;
33
- cursor: pointer;
34
- }
35
- .utilityfocus .pc-QuestionsBlock__item-title a:focus {
36
- outline: 2px solid #ffdb4d;
37
- }
38
- .pc-QuestionsBlock__item-title a:hover, .pc-QuestionsBlock__item-title a:active {
39
- --pc-text-header-color: var(--g-color-text-link-hover);
40
- color: var(--g-color-text-link-hover);
41
- }
42
- .pc-QuestionsBlock__text {
43
- font-size: var(--g-text-body-2-font-size);
44
- line-height: var(--g-text-body-2-line-height);
45
- margin-top: 12px;
46
- }
47
- .pc-QuestionsBlock__arrow {
48
- position: absolute;
49
- right: 0;
50
- top: 0;
51
- color: var(--g-color-text-primary);
52
- }
53
- .pc-QuestionsBlock__link {
54
- font-size: var(--g-text-body-2-font-size);
55
- line-height: var(--g-text-body-2-line-height);
56
- }
57
9
  @media (max-width: 769px) {
58
10
  .pc-QuestionsBlock__title {
59
11
  margin-right: 0;
@@ -1,28 +1,18 @@
1
1
  import React, { useState } from 'react';
2
- import { Foldable, HTML, ToggleArrow, YFMWrapper } from '../../components';
3
- import Link from '../../components/Link/Link';
4
2
  import { Col, Row } from '../../grid';
5
3
  import { Content } from '../../sub-blocks';
6
4
  import { block } from '../../utils';
5
+ import { QuestionBlockItem } from './QuestionBlockItem/QuestionBlockItem';
6
+ import { FaqMicrodataValues } from './models';
7
7
  import './Questions.css';
8
8
  const b = block('QuestionsBlock');
9
- const FaqMicrodataValues = {
10
- PageType: 'https://schema.org/FAQPage',
11
- QuestionType: 'https://schema.org/Question',
12
- QuestionProp: 'mainEntity',
13
- QuestionNameProp: 'name',
14
- QuestionTextProp: 'text',
15
- AnswerType: 'https://schema.org/Answer',
16
- AnswerProp: 'acceptedAnswer',
17
- AnswerTextProp: 'text',
18
- };
19
9
  const QuestionsBlock = (props) => {
20
10
  const { title, text, additionalInfo, links, buttons, items } = props;
21
11
  const [opened, setOpened] = useState([0]);
22
12
  const toggleItem = (index) => {
23
13
  let newState;
24
14
  if (opened.includes(index)) {
25
- newState = opened.filter((intemIndex) => intemIndex !== index);
15
+ newState = opened.filter((itemIndex) => itemIndex !== index);
26
16
  }
27
17
  else {
28
18
  newState = [...opened, index];
@@ -34,20 +24,10 @@ const QuestionsBlock = (props) => {
34
24
  React.createElement(Col, { sizes: { all: 12, md: 4 } },
35
25
  React.createElement("div", { className: b('title') },
36
26
  React.createElement(Content, { title: title, text: text, additionalInfo: additionalInfo, links: links, buttons: buttons, colSizes: { all: 12, md: 12 } }))),
37
- React.createElement(Col, { sizes: { all: 12, md: 8 } }, items.map(({ title: itemTitle, text: itemText, link, listStyle = 'dash' }, index) => {
27
+ React.createElement(Col, { sizes: { all: 12, md: 8 }, role: 'list' }, items.map(({ title: itemTitle, text: itemText, link, listStyle = 'dash' }, index) => {
38
28
  const isOpened = opened.includes(index);
39
- return (React.createElement("div", { key: itemTitle, className: b('item'), itemScope: true, itemProp: FaqMicrodataValues.QuestionProp, itemType: FaqMicrodataValues.QuestionType },
40
- React.createElement("h4", { className: b('item-title'), onClick: () => toggleItem(index) },
41
- React.createElement(HTML, { itemProp: FaqMicrodataValues.QuestionNameProp }, itemTitle),
42
- React.createElement(ToggleArrow, { open: isOpened, size: 16, type: 'vertical', iconType: "navigation", className: b('arrow') })),
43
- React.createElement(Foldable, { isOpened: isOpened },
44
- React.createElement("div", { className: b('text'), itemScope: true, itemProp: FaqMicrodataValues.AnswerProp, itemType: FaqMicrodataValues.AnswerType },
45
- React.createElement(YFMWrapper, { content: itemText, modifiers: {
46
- constructor: true,
47
- constructorListStyle: true,
48
- constructorListStyleDash: listStyle === 'dash',
49
- }, itemProp: FaqMicrodataValues.QuestionTextProp }),
50
- link && React.createElement(Link, Object.assign({}, link, { className: b('link') }))))));
29
+ const onClick = () => toggleItem(index);
30
+ return (React.createElement(QuestionBlockItem, { key: itemTitle, title: itemTitle, text: itemText, link: link, listStyle: listStyle, isOpened: isOpened, onClick: onClick }));
51
31
  })))));
52
32
  };
53
33
  export default QuestionsBlock;
@@ -0,0 +1,10 @@
1
+ export declare const FaqMicrodataValues: {
2
+ readonly PageType: "https://schema.org/FAQPage";
3
+ readonly QuestionType: "https://schema.org/Question";
4
+ readonly QuestionProp: "mainEntity";
5
+ readonly QuestionNameProp: "name";
6
+ readonly QuestionTextProp: "text";
7
+ readonly AnswerType: "https://schema.org/Answer";
8
+ readonly AnswerProp: "acceptedAnswer";
9
+ readonly AnswerTextProp: "text";
10
+ };
@@ -0,0 +1,10 @@
1
+ export const FaqMicrodataValues = {
2
+ PageType: 'https://schema.org/FAQPage',
3
+ QuestionType: 'https://schema.org/Question',
4
+ QuestionProp: 'mainEntity',
5
+ QuestionNameProp: 'name',
6
+ QuestionTextProp: 'text',
7
+ AnswerType: 'https://schema.org/Answer',
8
+ AnswerProp: 'acceptedAnswer',
9
+ AnswerTextProp: 'text',
10
+ };
@@ -1,7 +1,8 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { ButtonSize } from '@gravity-ui/uikit';
3
+ import { Tabbable } from '../../models';
3
4
  export type Theme = 'default' | 'special';
4
- export interface BackLinkProps {
5
+ export interface BackLinkProps extends Tabbable {
5
6
  url: string;
6
7
  title: ReactNode;
7
8
  theme?: Theme;
@@ -6,7 +6,7 @@ import { ArrowSidebar } from '../../icons';
6
6
  import { DefaultEventNames } from '../../models';
7
7
  export default function BackLink(props) {
8
8
  const { history } = useContext(LocationContext);
9
- const { url, title, theme = 'default', size = 'l', className, shouldHandleBackAction = false, onClick, } = props;
9
+ const { url, title, theme = 'default', size = 'l', className, shouldHandleBackAction = false, onClick, tabIndex, } = props;
10
10
  const handleAnalytics = useAnalytics(DefaultEventNames.ShareButton, url);
11
11
  const backActionHandler = useCallback(async () => {
12
12
  handleAnalytics();
@@ -23,7 +23,7 @@ export default function BackLink(props) {
23
23
  history.push({ pathname: url });
24
24
  }
25
25
  }, [handleAnalytics, history, onClick, url]);
26
- return (React.createElement(Button, { className: className, view: theme === 'special' ? 'flat-contrast' : 'flat-secondary', size: size, href: shouldHandleBackAction ? undefined : url, onClick: shouldHandleBackAction ? backActionHandler : undefined },
26
+ return (React.createElement(Button, { className: className, view: theme === 'special' ? 'flat-contrast' : 'flat-secondary', size: size, href: shouldHandleBackAction ? undefined : url, onClick: shouldHandleBackAction ? backActionHandler : undefined, tabIndex: tabIndex },
27
27
  React.createElement(Icon, { data: ArrowSidebar, size: 24 }),
28
28
  React.createElement("span", null, title)));
29
29
  }
@@ -37,13 +37,13 @@ const LabelSizeMap = {
37
37
  };
38
38
  const FileLink = (props) => {
39
39
  const { hostname } = useContext(LocationContext);
40
- const { href, text, type = 'vertical', textSize = 'm', className, theme = 'default', onClick, } = props;
40
+ const { href, text, type = 'vertical', textSize = 'm', className, theme = 'default', onClick, tabIndex, } = props;
41
41
  const fileExt = getFileExt(href);
42
42
  const labelTheme = (FileExtensionThemes[fileExt] || 'unknown');
43
43
  const labelSize = LabelSizeMap[textSize];
44
44
  return (React.createElement("div", { className: b({ ext: fileExt, type, size: textSize, theme }, className) },
45
45
  React.createElement(Label, { className: b('file-label'), size: labelSize, theme: labelTheme }, fileExt),
46
46
  React.createElement("div", { className: b('link') },
47
- React.createElement("a", Object.assign({ href: href }, getLinkProps(href, hostname), { onClick: onClick }), text))));
47
+ React.createElement("a", Object.assign({ href: href, onClick: onClick, tabIndex: tabIndex }, getLinkProps(href, hostname)), text))));
48
48
  };
49
49
  export default FileLink;
@@ -23,7 +23,7 @@ const FullscreenImage = (props) => {
23
23
  React.createElement(Icon, { data: Fullscreen, width: FULL_SCREEN_ICON_SIZE, height: FULL_SCREEN_ICON_SIZE, className: b('icon') }))),
24
24
  isOpened && (React.createElement(Modal, { open: isOpened, onClose: closeModal, className: b('modal') },
25
25
  React.createElement("div", { className: b('modal-content') },
26
- React.createElement("div", { className: b('icon-wrapper', { visible: true }), onClick: closeModal },
26
+ React.createElement("div", { className: b('icon-wrapper', { visible: true }), onClick: closeModal, "aria-label": i18n('close') },
27
27
  React.createElement(Icon, { data: PreviewClose, width: CLOSE_ICON_SIZE, height: CLOSE_ICON_SIZE, className: b('icon', { hover: true }) })),
28
28
  React.createElement(Image, Object.assign({}, props, { className: b('modal-image', modalImageClass) })))))));
29
29
  };
@@ -1,3 +1,4 @@
1
1
  {
2
- "img-alt": "Full screen image"
2
+ "img-alt": "Full screen image",
3
+ "close": "Close"
3
4
  }
@@ -1,3 +1,4 @@
1
1
  {
2
- "img-alt": "Полноэкранное изображение"
2
+ "img-alt": "Полноэкранное изображение",
3
+ "close": "Закрыть"
3
4
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "img-alt": "Image alt"
2
+ "img-alt": ""
3
3
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "img-alt": "Альтернатива изображению"
2
+ "img-alt": ""
3
3
  }
@@ -1,5 +1,5 @@
1
- import { ClassNameProps, LinkProps, WithChildren } from '../../models';
1
+ import { ClassNameProps, LinkProps, Tabbable, WithChildren } from '../../models';
2
2
  import './Link.css';
3
- export type LinkFullProps = LinkProps & ClassNameProps;
3
+ export type LinkFullProps = LinkProps & ClassNameProps & Tabbable;
4
4
  declare const LinkBlock: (props: WithChildren<LinkFullProps>) => JSX.Element;
5
5
  export default LinkBlock;
@@ -1,11 +1,11 @@
1
1
  import React, { Fragment, useContext } from 'react';
2
2
  import { Icon } from '@gravity-ui/uikit';
3
- import { LocaleContext } from '../../context/localeContext/localeContext';
4
- import { LocationContext } from '../../context/locationContext/locationContext';
3
+ import { LocaleContext } from '../../context/localeContext';
4
+ import { LocationContext } from '../../context/locationContext';
5
5
  import { useAnalytics } from '../../hooks';
6
6
  import { useMetrika } from '../../hooks/useMetrika';
7
7
  import { Chevron } from '../../icons';
8
- import { DefaultEventNames } from '../../models';
8
+ import { DefaultEventNames, } from '../../models';
9
9
  import { block, getLinkProps, setUrlTld } from '../../utils';
10
10
  import BackLink from '../BackLink/BackLink';
11
11
  import FileLink from '../FileLink/FileLink';
@@ -25,7 +25,7 @@ function getArrowSize(size) {
25
25
  }
26
26
  }
27
27
  const LinkBlock = (props) => {
28
- const { text, url, arrow, metrikaGoals, pixelEvents, analyticsEvents, theme = 'file-link', colorTheme = 'light', textSize = 'm', className, target, children, } = props;
28
+ const { text, url, arrow, metrikaGoals, pixelEvents, analyticsEvents, theme = 'file-link', colorTheme = 'light', textSize = 'm', className, target, children, tabIndex, } = props;
29
29
  const handleMetrika = useMetrika();
30
30
  const handleAnalytics = useAnalytics(DefaultEventNames.Link, url);
31
31
  const { hostname } = useContext(LocationContext);
@@ -39,14 +39,14 @@ const LinkBlock = (props) => {
39
39
  const getLinkByType = () => {
40
40
  switch (theme) {
41
41
  case 'back':
42
- return React.createElement(BackLink, { title: children || text, url: href, onClick: onClick });
42
+ return (React.createElement(BackLink, { title: children || text, url: href, onClick: onClick, tabIndex: tabIndex }));
43
43
  case 'file-link':
44
44
  case 'underline':
45
- return (React.createElement(FileLink, { text: children || text, href: href, type: "horizontal", textSize: textSize, onClick: onClick }));
45
+ return (React.createElement(FileLink, { text: children || text, href: href, type: "horizontal", textSize: textSize, onClick: onClick, tabIndex: tabIndex }));
46
46
  case 'normal': {
47
47
  const linkProps = getLinkProps(url, hostname, target);
48
48
  const content = children || text;
49
- return (React.createElement("a", Object.assign({ className: b('link', { theme: colorTheme, 'has-arrow': arrow }), href: href, onClick: onClick }, linkProps), arrow ? (React.createElement(Fragment, null,
49
+ return (React.createElement("a", Object.assign({ className: b('link', { theme: colorTheme, 'has-arrow': arrow }), href: href, onClick: onClick, tabIndex: tabIndex }, linkProps), arrow ? (React.createElement(Fragment, null,
50
50
  React.createElement("span", { className: b('content') }, content),
51
51
  WORD_JOINER_SYM,
52
52
  React.createElement(Icon, { className: b('arrow'), data: Chevron, size: getArrowSize(textSize) }))) : (content)));
@@ -8,8 +8,7 @@ import Video from './Video/Video';
8
8
  import './Media.css';
9
9
  const b = block('Media');
10
10
  export const Media = (props) => {
11
- const { image, video, youtube, dataLens, color, height, previewImg, parallax = false, metrika, fullscreen, analyticsEvents, } = props;
12
- const { className, imageClassName, videoClassName, youtubeClassName, playVideo = true, isBackground, playButton, customBarControlsClassName, } = props;
11
+ const { image, video, youtube, dataLens, color, height, previewImg, parallax = false, metrika, fullscreen, analyticsEvents, className, imageClassName, videoClassName, youtubeClassName, playVideo = true, isBackground, playButton, customBarControlsClassName, } = props;
13
12
  const [hasVideoFallback, setHasVideoFallback] = useState(false);
14
13
  const content = useMemo(() => {
15
14
  let result = [];
@@ -28,8 +28,8 @@ const Video = (props) => {
28
28
  }
29
29
  }, [playVideo, video, setHasVideoFallback]);
30
30
  const reactPlayerBlock = useMemo(() => {
31
- const { src, loop, controls, muted, autoplay = true, elapsedTime, playButton } = video;
32
- return (React.createElement(ReactPlayerBlock, { className: b('react-player', videoClassName), src: src, previewImgUrl: previewImg, loop: Boolean(loop), controls: controls, muted: muted, autoplay: autoplay && playVideo, elapsedTime: elapsedTime, playButton: playButton || commonPlayButton, customBarControlsClassName: customBarControlsClassName, metrika: metrika, analyticsEvents: analyticsEvents, height: height }));
31
+ const { src, loop, controls, muted, autoplay = true, elapsedTime, playButton, ariaLabel, } = video;
32
+ return (React.createElement(ReactPlayerBlock, { className: b('react-player', videoClassName), src: src, previewImgUrl: previewImg, loop: Boolean(loop), controls: controls, muted: muted, autoplay: autoplay && playVideo, elapsedTime: elapsedTime, playButton: playButton || commonPlayButton, customBarControlsClassName: customBarControlsClassName, metrika: metrika, analyticsEvents: analyticsEvents, height: height, ariaLabel: ariaLabel }));
33
33
  }, [
34
34
  video,
35
35
  height,
@@ -46,7 +46,7 @@ const Video = (props) => {
46
46
  React.createElement("video", { disablePictureInPicture: true, playsInline: true,
47
47
  // @ts-ignore
48
48
  // eslint-disable-next-line react/no-unknown-property
49
- pip: "false", className: b('item'), ref: ref, preload: "metadata", muted: true }, getVideoTypesWithPriority(video.src).map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))) : null;
49
+ pip: "false", className: b('item'), ref: ref, preload: "metadata", muted: true, "aria-label": video.ariaLabel }, getVideoTypesWithPriority(video.src).map(({ src, type }, index) => (React.createElement("source", { key: index, src: src, type: type })))))) : null;
50
50
  }, [video, videoClassName, hasVideoFallback, height]);
51
51
  switch (video.type) {
52
52
  case MediaVideoType.Player:
@@ -10,6 +10,7 @@ import { PlayVideo } from '../../icons';
10
10
  import { DefaultEventNames, MediaVideoControlsType, PlayButtonThemes, PlayButtonType, PredefinedEventTypes, } from '../../models';
11
11
  import { block } from '../../utils';
12
12
  import CustomBarControls from './CustomBarControls';
13
+ import i18n from './i18n';
13
14
  import { checkYoutubeVideos } from './utils';
14
15
  import './ReactPlayer.css';
15
16
  const b = block('ReactPlayer');
@@ -18,7 +19,7 @@ const FPS = 60;
18
19
  export const ReactPlayerBlock = React.forwardRef((props, originRef) => {
19
20
  const isMobile = useContext(MobileContext);
20
21
  const { metrika } = useContext(MetrikaContext);
21
- const { src, previewImgUrl, loop = false, controls = MediaVideoControlsType.Default, muted: initiallyMuted = false, elapsedTime, playButton, className, customBarControlsClassName, showPreview, onClickPreview, metrika: videoMetrika, analyticsEvents, height, } = props;
22
+ const { src, previewImgUrl, loop = false, controls = MediaVideoControlsType.Default, muted: initiallyMuted = false, elapsedTime, playButton, className, customBarControlsClassName, showPreview, onClickPreview, metrika: videoMetrika, analyticsEvents, height, ariaLabel, } = props;
22
23
  const { type = PlayButtonType.Default, theme = PlayButtonThemes.Blue, text, className: buttonClassName, } = playButton || {};
23
24
  const autoPlay = Boolean(!isMobile && !previewImgUrl && props.autoplay);
24
25
  const mute = initiallyMuted || autoPlay;
@@ -102,7 +103,7 @@ export const ReactPlayerBlock = React.forwardRef((props, originRef) => {
102
103
  playButtonContent = React.createElement(Icon, { className: b('icon'), data: PlayVideo, size: 24 });
103
104
  break;
104
105
  }
105
- return (React.createElement("button", { className: b('button', { theme, text: Boolean(text) }, buttonClassName) }, playButtonContent));
106
+ return (React.createElement("button", { className: b('button', { theme, text: Boolean(text) }, buttonClassName), "aria-label": i18n('play') }, playButtonContent));
106
107
  }, [type, theme, text, buttonClassName]);
107
108
  const changeMute = useCallback((isMuted) => {
108
109
  if (isMuted && playerRef) {
@@ -192,7 +193,7 @@ export const ReactPlayerBlock = React.forwardRef((props, originRef) => {
192
193
  }, elapsedTimePercent: elapsedTimePercent }));
193
194
  }, [controls, isPlaying, customBarControlsClassName, changeMute]);
194
195
  return (React.createElement("div", { className: b({ wrapper: !currentHeight }, className), ref: ref, onClick: handleClick },
195
- React.createElement(ReactPlayer, { className: b('player'), url: videoSrc, muted: muted, controls: controls === MediaVideoControlsType.Default, height: currentHeight || '100%', width: width || '100%', light: previewImgUrl, playing: isPlaying, playIcon: playIcon, progressInterval: FPS, onClickPreview: handleClickPreview, onStart: onStart, onReady: setPlayerRef, onPlay: onPlay, onPause: onPause, onProgress: onProgress, onEnded: onEnded }),
196
+ React.createElement(ReactPlayer, { className: b('player'), url: videoSrc, muted: muted, controls: controls === MediaVideoControlsType.Default, height: currentHeight || '100%', width: width || '100%', light: previewImgUrl, playing: isPlaying, playIcon: playIcon, progressInterval: FPS, onClickPreview: handleClickPreview, onStart: onStart, onReady: setPlayerRef, onPlay: onPlay, onPause: onPause, onProgress: onProgress, onEnded: onEnded, "aria-label": ariaLabel }),
196
197
  renderCustomBarControls(muted, playedPercent)));
197
198
  });
198
199
  function getHeight(width) {
@@ -0,0 +1,3 @@
1
+ {
2
+ "play": "Play"
3
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: (key: string, params?: import("@gravity-ui/i18n").Params | undefined) => string;
2
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { registerKeyset } from '../../../utils/registerKeyset';
2
+ import en from './en.json';
3
+ import ru from './ru.json';
4
+ const COMPONENT = 'ReactPlayer';
5
+ export default registerKeyset({ en, ru }, COMPONENT);
@@ -0,0 +1,3 @@
1
+ {
2
+ "play": "Воспроизвести"
3
+ }