@gravity-ui/page-constructor 4.1.2 → 4.4.1
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.
- package/build/cjs/blocks/ExtendedFeatures/ExtendedFeatures.js +7 -3
- package/build/cjs/blocks/PromoFeaturesBlock/PromoFeaturesBlock.js +1 -1
- package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +50 -0
- package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.d.ts +2 -0
- package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.js +27 -0
- package/build/cjs/blocks/Questions/Questions.css +0 -48
- package/build/cjs/blocks/Questions/Questions.js +7 -27
- package/build/cjs/blocks/Questions/models.d.ts +10 -0
- package/build/cjs/blocks/Questions/models.js +13 -0
- package/build/cjs/components/BackLink/BackLink.d.ts +2 -1
- package/build/cjs/components/BackLink/BackLink.js +2 -2
- package/build/cjs/components/FileLink/FileLink.js +2 -2
- package/build/cjs/components/FullscreenImage/FullscreenImage.js +1 -1
- package/build/cjs/components/FullscreenImage/i18n/en.json +2 -1
- package/build/cjs/components/FullscreenImage/i18n/ru.json +2 -1
- package/build/cjs/components/HTML/HTML.d.ts +3 -1
- package/build/cjs/components/HTML/HTML.js +2 -1
- package/build/cjs/components/Image/i18n/en.json +1 -1
- package/build/cjs/components/Image/i18n/ru.json +1 -1
- package/build/cjs/components/Link/Link.d.ts +2 -2
- package/build/cjs/components/Link/Link.js +6 -6
- package/build/cjs/components/Media/Media.js +1 -2
- package/build/cjs/components/Media/Video/Video.js +3 -3
- package/build/cjs/components/ReactPlayer/ReactPlayer.js +4 -3
- package/build/cjs/components/ReactPlayer/i18n/en.json +3 -0
- package/build/cjs/components/ReactPlayer/i18n/index.d.ts +2 -0
- package/build/cjs/components/ReactPlayer/i18n/index.js +8 -0
- package/build/cjs/components/ReactPlayer/i18n/ru.json +3 -0
- package/build/cjs/components/Table/Table.js +11 -5
- package/build/cjs/components/YFMWrapper/YFMWrapper.d.ts +3 -3
- package/build/cjs/components/YFMWrapper/YFMWrapper.js +1 -1
- package/build/cjs/components/constants.d.ts +0 -4
- package/build/cjs/components/constants.js +1 -5
- package/build/cjs/grid/Col/Col.d.ts +3 -4
- package/build/cjs/grid/Col/Col.js +2 -2
- package/build/cjs/models/constructor-items/blocks.d.ts +8 -0
- package/build/cjs/models/constructor-items/common.d.ts +11 -4
- package/build/cjs/sub-blocks/Content/ContentList/ContentList.js +11 -1
- package/build/cjs/sub-blocks/LayoutItem/utils.d.ts +1 -0
- package/build/cjs/utils/blocks.d.ts +1 -1
- package/build/cjs/utils/blocks.js +2 -2
- package/build/esm/blocks/ExtendedFeatures/ExtendedFeatures.js +7 -3
- package/build/esm/blocks/PromoFeaturesBlock/PromoFeaturesBlock.js +1 -1
- package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +50 -0
- package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.d.ts +3 -0
- package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.js +23 -0
- package/build/esm/blocks/Questions/Questions.css +0 -48
- package/build/esm/blocks/Questions/Questions.js +6 -26
- package/build/esm/blocks/Questions/models.d.ts +10 -0
- package/build/esm/blocks/Questions/models.js +10 -0
- package/build/esm/components/BackLink/BackLink.d.ts +2 -1
- package/build/esm/components/BackLink/BackLink.js +2 -2
- package/build/esm/components/FileLink/FileLink.js +2 -2
- package/build/esm/components/FullscreenImage/FullscreenImage.js +1 -1
- package/build/esm/components/FullscreenImage/i18n/en.json +2 -1
- package/build/esm/components/FullscreenImage/i18n/ru.json +2 -1
- package/build/esm/components/HTML/HTML.d.ts +3 -1
- package/build/esm/components/HTML/HTML.js +2 -1
- package/build/esm/components/Image/i18n/en.json +1 -1
- package/build/esm/components/Image/i18n/ru.json +1 -1
- package/build/esm/components/Link/Link.d.ts +2 -2
- package/build/esm/components/Link/Link.js +7 -7
- package/build/esm/components/Media/Media.js +1 -2
- package/build/esm/components/Media/Video/Video.js +3 -3
- package/build/esm/components/ReactPlayer/ReactPlayer.js +4 -3
- package/build/esm/components/ReactPlayer/i18n/en.json +3 -0
- package/build/esm/components/ReactPlayer/i18n/index.d.ts +2 -0
- package/build/esm/components/ReactPlayer/i18n/index.js +5 -0
- package/build/esm/components/ReactPlayer/i18n/ru.json +3 -0
- package/build/esm/components/Table/Table.js +11 -5
- package/build/esm/components/YFMWrapper/YFMWrapper.d.ts +3 -3
- package/build/esm/components/YFMWrapper/YFMWrapper.js +1 -1
- package/build/esm/components/constants.d.ts +0 -4
- package/build/esm/components/constants.js +0 -4
- package/build/esm/grid/Col/Col.d.ts +3 -4
- package/build/esm/grid/Col/Col.js +2 -2
- package/build/esm/models/constructor-items/blocks.d.ts +8 -0
- package/build/esm/models/constructor-items/common.d.ts +11 -4
- package/build/esm/sub-blocks/Content/ContentList/ContentList.js +11 -1
- package/build/esm/sub-blocks/LayoutItem/utils.d.ts +1 -0
- package/build/esm/utils/blocks.d.ts +1 -1
- package/build/esm/utils/blocks.js +2 -2
- package/package.json +3 -3
- package/server/components/constants.d.ts +0 -4
- package/server/components/constants.js +1 -5
- package/server/models/constructor-items/blocks.d.ts +8 -0
- package/server/models/constructor-items/common.d.ts +11 -4
- package/server/utils/blocks.d.ts +1 -1
- package/server/utils/blocks.js +2 -2
- package/widget/index.js +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React, { CSSProperties } from 'react';
|
|
2
|
-
import { QAProps, Refable } from '../../models
|
|
3
|
-
import { WithChildren } from '../../models/react';
|
|
2
|
+
import { QAProps, Refable, Roleable, WithChildren } from '../../models';
|
|
4
3
|
import { GridColumnClassParams } from '../types';
|
|
5
|
-
export interface GridColumnProps extends GridColumnClassParams, Refable<HTMLDivElement>, QAProps {
|
|
4
|
+
export interface GridColumnProps extends GridColumnClassParams, Refable<HTMLDivElement>, QAProps, Roleable {
|
|
6
5
|
style?: CSSProperties;
|
|
7
6
|
children?: React.ReactNode;
|
|
8
7
|
}
|
|
9
|
-
export declare const Col: React.ForwardRefExoticComponent<Pick<WithChildren<GridColumnProps>, "style" | "children" | "sizes" | "className" | "hidden" | "qa" | "reset" | "visible" | "offsets" | "orders" | "alignSelf" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export declare const Col: React.ForwardRefExoticComponent<Pick<WithChildren<GridColumnProps>, "style" | "children" | "sizes" | "className" | "hidden" | "role" | "qa" | "reset" | "visible" | "offsets" | "orders" | "alignSelf" | "justifyContent"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -5,7 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
6
6
|
const utils_1 = require("../utils");
|
|
7
7
|
exports.Col = (0, react_1.forwardRef)((props, ref) => {
|
|
8
|
-
const { children, style, qa } = props, rest = tslib_1.__rest(props, ["children", "style", "qa"]);
|
|
9
|
-
return (react_1.default.createElement("div", { ref: ref, className: (0, utils_1.getColClass)(rest), style: style, "data-qa": qa }, children));
|
|
8
|
+
const { children, style, qa, role } = props, rest = tslib_1.__rest(props, ["children", "style", "qa", "role"]);
|
|
9
|
+
return (react_1.default.createElement("div", { ref: ref, className: (0, utils_1.getColClass)(rest), style: style, "data-qa": qa, role: role }, children));
|
|
10
10
|
});
|
|
11
11
|
exports.Col.displayName = 'Col';
|
|
@@ -141,6 +141,10 @@ export interface QuestionItem {
|
|
|
141
141
|
export interface QuestionsProps extends Omit<ContentBlockProps, 'colSizes' | 'centered' | 'size' | 'theme'> {
|
|
142
142
|
items: QuestionItem[];
|
|
143
143
|
}
|
|
144
|
+
export interface QuestionBlockItemProps extends QuestionItem {
|
|
145
|
+
isOpened: boolean;
|
|
146
|
+
onClick: () => void;
|
|
147
|
+
}
|
|
144
148
|
export interface BannerBlockProps extends BannerCardProps, Animatable {
|
|
145
149
|
}
|
|
146
150
|
export interface CompaniesBlockProps extends Animatable {
|
|
@@ -185,6 +189,10 @@ export interface TableProps {
|
|
|
185
189
|
legend?: string[];
|
|
186
190
|
justify?: Justify[];
|
|
187
191
|
marker?: LegendTableMarkerType;
|
|
192
|
+
/**
|
|
193
|
+
* Only as accessible name, not displayed explicitly
|
|
194
|
+
*/
|
|
195
|
+
caption?: string;
|
|
188
196
|
}
|
|
189
197
|
export interface TableBlockProps {
|
|
190
198
|
title: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CSSProperties, ReactNode } from 'react';
|
|
1
|
+
import React, { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { ButtonView, ButtonProps as UikitButtonProps } from '@gravity-ui/uikit';
|
|
3
|
-
import { ThemeSupporting } from '../../utils
|
|
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,12 @@ export interface Stylable {
|
|
|
61
61
|
export interface Animatable {
|
|
62
62
|
animated?: boolean;
|
|
63
63
|
}
|
|
64
|
+
export interface Tabbable {
|
|
65
|
+
tabIndex?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface Roleable {
|
|
68
|
+
role?: React.AriaRole;
|
|
69
|
+
}
|
|
64
70
|
export interface Background {
|
|
65
71
|
image?: string;
|
|
66
72
|
color?: string;
|
|
@@ -106,7 +112,7 @@ export interface MediaVideoProps extends AnalyticsEventsBase {
|
|
|
106
112
|
controls?: MediaVideoControlsType;
|
|
107
113
|
metrika?: MetrikaVideo;
|
|
108
114
|
}
|
|
109
|
-
export interface LinkProps extends AnalyticsEventsBase, Stylable {
|
|
115
|
+
export interface LinkProps extends AnalyticsEventsBase, Stylable, Tabbable {
|
|
110
116
|
url: string;
|
|
111
117
|
text?: string;
|
|
112
118
|
textSize?: TextSize;
|
|
@@ -117,7 +123,7 @@ export interface LinkProps extends AnalyticsEventsBase, Stylable {
|
|
|
117
123
|
metrikaGoals?: MetrikaGoal;
|
|
118
124
|
pixelEvents?: ButtonPixel;
|
|
119
125
|
}
|
|
120
|
-
export interface FileLinkProps extends ClassNameProps {
|
|
126
|
+
export interface FileLinkProps extends ClassNameProps, Tabbable {
|
|
121
127
|
href: string;
|
|
122
128
|
text: ReactNode;
|
|
123
129
|
type?: FileLinkType;
|
|
@@ -157,6 +163,7 @@ export interface MediaVideoProps {
|
|
|
157
163
|
playButton?: PlayButtonProps;
|
|
158
164
|
controls?: MediaVideoControlsType;
|
|
159
165
|
metrika?: MetrikaVideo;
|
|
166
|
+
ariaLabel?: string;
|
|
160
167
|
}
|
|
161
168
|
export type ThemedMediaVideoProps = ThemeSupporting<MediaVideoProps>;
|
|
162
169
|
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 &&
|
|
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" | "
|
|
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[];
|
|
@@ -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 &&
|
|
32
|
-
React.createElement(
|
|
33
|
-
|
|
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
|
};
|
|
@@ -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("
|
|
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,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((
|
|
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
|
-
|
|
40
|
-
|
|
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)
|
|
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
|
};
|
|
@@ -5,12 +5,14 @@ export interface HTMLProps {
|
|
|
5
5
|
block?: boolean;
|
|
6
6
|
className?: string;
|
|
7
7
|
itemProp?: string;
|
|
8
|
+
id?: string;
|
|
8
9
|
}
|
|
9
|
-
declare const HTML: ({ children, block, className, itemProp }: WithChildren<HTMLProps>) => React.DetailedReactHTMLElement<{
|
|
10
|
+
declare const HTML: ({ children, block, className, itemProp, id }: WithChildren<HTMLProps>) => React.DetailedReactHTMLElement<{
|
|
10
11
|
dangerouslySetInnerHTML: {
|
|
11
12
|
__html: string | (string & React.ReactElement<any, string | React.JSXElementConstructor<any>>) | (string & React.ReactFragment) | (string & React.ReactPortal);
|
|
12
13
|
};
|
|
13
14
|
className: string | undefined;
|
|
14
15
|
itemProp: string | undefined;
|
|
16
|
+
id: string | undefined;
|
|
15
17
|
}, HTMLElement> | null;
|
|
16
18
|
export default HTML;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { hasBlockTag } from '../../utils';
|
|
3
|
-
const HTML = ({ children, block = false, className, itemProp }) => {
|
|
3
|
+
const HTML = ({ children, block = false, className, itemProp, id }) => {
|
|
4
4
|
if (!children) {
|
|
5
5
|
return null;
|
|
6
6
|
}
|
|
@@ -8,6 +8,7 @@ const HTML = ({ children, block = false, className, itemProp }) => {
|
|
|
8
8
|
dangerouslySetInnerHTML: { __html: children },
|
|
9
9
|
className,
|
|
10
10
|
itemProp,
|
|
11
|
+
id,
|
|
11
12
|
});
|
|
12
13
|
};
|
|
13
14
|
export default HTML;
|
|
@@ -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
|
|
4
|
-
import { LocationContext } from '../../context/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:
|