@gravity-ui/blog-constructor 5.10.0 → 5.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/build/cjs/blocks/Meta/Meta.js +4 -3
  2. package/build/cjs/components/PostInfo/PostInfo.js +5 -3
  3. package/build/cjs/components/PostInfo/components/Date.d.ts +3 -3
  4. package/build/cjs/components/PostInfo/components/Date.js +2 -2
  5. package/build/cjs/components/PostInfo/components/ReadingTime.d.ts +3 -2
  6. package/build/cjs/components/PostInfo/components/ReadingTime.js +1 -1
  7. package/build/cjs/components/PostInfo/components/Save.js +1 -1
  8. package/build/cjs/containers/BlogPage/BlogPage.d.ts +3 -2
  9. package/build/cjs/containers/BlogPage/BlogPage.js +4 -3
  10. package/build/cjs/containers/BlogPostPage/BlogPostPage.d.ts +3 -2
  11. package/build/cjs/containers/BlogPostPage/BlogPostPage.js +4 -3
  12. package/build/cjs/contexts/PostPageContext.d.ts +6 -5
  13. package/build/cjs/hooks/useExtendedComponentMap.d.ts +24 -0
  14. package/build/cjs/hooks/useExtendedComponentMap.js +9 -0
  15. package/build/cjs/models/blocks.d.ts +1 -1
  16. package/build/cjs/utils/common.d.ts +2 -0
  17. package/build/esm/blocks/Meta/Meta.js +5 -4
  18. package/build/esm/components/PostInfo/PostInfo.js +5 -3
  19. package/build/esm/components/PostInfo/components/Date.d.ts +3 -3
  20. package/build/esm/components/PostInfo/components/Date.js +2 -2
  21. package/build/esm/components/PostInfo/components/ReadingTime.d.ts +3 -2
  22. package/build/esm/components/PostInfo/components/ReadingTime.js +1 -1
  23. package/build/esm/components/PostInfo/components/Save.js +1 -1
  24. package/build/esm/containers/BlogPage/BlogPage.d.ts +3 -2
  25. package/build/esm/containers/BlogPage/BlogPage.js +4 -3
  26. package/build/esm/containers/BlogPostPage/BlogPostPage.d.ts +3 -2
  27. package/build/esm/containers/BlogPostPage/BlogPostPage.js +4 -3
  28. package/build/esm/contexts/PostPageContext.d.ts +6 -5
  29. package/build/esm/hooks/useExtendedComponentMap.d.ts +24 -0
  30. package/build/esm/hooks/useExtendedComponentMap.js +4 -0
  31. package/build/esm/models/blocks.d.ts +1 -1
  32. package/build/esm/utils/common.d.ts +2 -0
  33. package/package.json +3 -3
  34. package/server/models/blocks.d.ts +1 -1
@@ -27,21 +27,22 @@ const breadcrumbsGoals = [
27
27
  },
28
28
  ];
29
29
  const Meta = (props) => {
30
- const { paddingTop = 'l', paddingBottom = 'l', theme = 'light' } = props;
30
+ const { paddingTop = 'l', paddingBottom = 'l', theme = 'light', qa } = props;
31
31
  const { post } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
32
32
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
33
+ const qaAttributes = (0, common_1.getQaAttributes)(qa, 'post-info');
33
34
  const { title, id, date, readingTime, tags } = post;
34
35
  const breadcrumbs = (0, common_1.getBreadcrumbs)({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
35
36
  breadcrumbs.metrikaGoals = breadcrumbsGoals;
36
37
  return (react_1.default.createElement(Wrapper_1.Wrapper, { paddings: {
37
38
  [paddings_1.PaddingsDirections.top]: paddingTop,
38
39
  [paddings_1.PaddingsDirections.bottom]: paddingBottom,
39
- }, qa: "blog-meta-content" },
40
+ }, qa: qaAttributes.wrapper },
40
41
  breadcrumbs && (react_1.default.createElement(page_constructor_1.HeaderBreadcrumbs, { items: breadcrumbs.items, className: b('breadcrumbs'), theme: theme, metrikaGoals: breadcrumbs.metrikaGoals })),
41
42
  title && (react_1.default.createElement(page_constructor_1.YFMWrapper, { content: title, modifiers: {
42
43
  blogBreadcrumbs: true,
43
44
  resetPaddings: true,
44
45
  } })),
45
- post && (react_1.default.createElement(PostInfo_1.PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, qa: "blog-meta-block" }))));
46
+ post && (react_1.default.createElement(PostInfo_1.PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, qa: qaAttributes.postInfo }))));
46
47
  };
47
48
  exports.Meta = Meta;
@@ -9,6 +9,7 @@ const Date_1 = require("./components/Date");
9
9
  const ReadingTime_1 = require("./components/ReadingTime");
10
10
  const Save_1 = require("./components/Save");
11
11
  const Sharing_1 = require("./components/Sharing");
12
+ const common_1 = require("../../utils/common");
12
13
  const b = (0, cn_1.block)('post-info');
13
14
  /**
14
15
  * Blog post info panel component
@@ -24,10 +25,11 @@ const b = (0, cn_1.block)('post-info');
24
25
  */
25
26
  const PostInfo = ({ date, readingTime, postId, theme = 'light', metrikaGoals, qa, }) => {
26
27
  const { likes } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
28
+ const qaAttributes = (0, common_1.getQaAttributes)(qa, 'date', 'reading-time', 'save');
27
29
  return (react_1.default.createElement("div", { className: b('container', { theme }) },
28
- date && react_1.default.createElement(Date_1.Date, { date: date }),
29
- readingTime && react_1.default.createElement(ReadingTime_1.ReadingTime, { readingTime: readingTime }),
30
+ date && react_1.default.createElement(Date_1.Date, { date: date, qa: qaAttributes.date }),
31
+ readingTime && react_1.default.createElement(ReadingTime_1.ReadingTime, { readingTime: readingTime, qa: qaAttributes.readingTime }),
30
32
  react_1.default.createElement(Sharing_1.Sharing, { metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.sharing, theme: theme }),
31
- likes && (react_1.default.createElement(Save_1.Save, { postId: postId, title: likes.likesCount, hasUserLike: likes.hasUserLike, handleUserLike: likes.handleUserLike, metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.save, theme: theme, qa: qa }))));
33
+ likes && (react_1.default.createElement(Save_1.Save, { postId: postId, title: likes.likesCount, hasUserLike: likes.hasUserLike, handleUserLike: likes.handleUserLike, metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.save, theme: theme, qa: qaAttributes.save }))));
32
34
  };
33
35
  exports.PostInfo = PostInfo;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import { PostCardSize } from '../../../models/common';
3
- type DateProps = {
2
+ import { PostCardSize, QAProps } from '../../../models/common';
3
+ type DateProps = QAProps & {
4
4
  date: string | number;
5
5
  size?: PostCardSize;
6
6
  id?: string;
7
7
  };
8
- export declare const Date: ({ date, size, id }: DateProps) => React.JSX.Element;
8
+ export declare const Date: ({ date, size, id, qa }: DateProps) => React.JSX.Element;
9
9
  export {};
@@ -8,8 +8,8 @@ const common_1 = require("../../../models/common");
8
8
  const cn_1 = require("../../../utils/cn");
9
9
  const date_1 = require("../../../utils/date");
10
10
  const b = (0, cn_1.block)('post-info');
11
- const Date = ({ date, size = common_1.PostCardSize.SMALL, id }) => {
11
+ const Date = ({ date, size = common_1.PostCardSize.SMALL, id, qa }) => {
12
12
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
13
- return (react_1.default.createElement("div", { className: b('item', { size }), id: id }, (0, date_1.format)(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
13
+ return (react_1.default.createElement("div", { className: b('item', { size }), id: id, "data-qa": qa }, (0, date_1.format)(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
14
14
  };
15
15
  exports.Date = Date;
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- type ReadingTimeProps = {
2
+ import { QAProps } from '../../../models/common';
3
+ type ReadingTimeProps = QAProps & {
3
4
  readingTime: number;
4
5
  size?: 's' | 'm';
5
6
  id?: string;
6
7
  };
7
- export declare const ReadingTime: ({ readingTime, size, id }: ReadingTimeProps) => React.JSX.Element;
8
+ export declare const ReadingTime: ({ readingTime, size, id, qa }: ReadingTimeProps) => React.JSX.Element;
8
9
  export {};
@@ -9,7 +9,7 @@ const Time_1 = require("../../../icons/Time");
9
9
  const cn_1 = require("../../../utils/cn");
10
10
  const b = (0, cn_1.block)('post-info');
11
11
  const ICON_SIZE = 16;
12
- const ReadingTime = ({ readingTime, size = 's', id }) => (react_1.default.createElement("div", { className: b('item', { size }), id: id },
12
+ const ReadingTime = ({ readingTime, size = 's', id, qa }) => (react_1.default.createElement("div", { className: b('item', { size }), id: id, "data-qa": qa },
13
13
  react_1.default.createElement("span", { className: b('icon') },
14
14
  react_1.default.createElement(uikit_1.Icon, { data: Time_1.Time, size: ICON_SIZE, className: b('icon-color') })),
15
15
  (0, i18n_1.i18)(i18n_1.Keyset.ContextReadingTime, { count: readingTime })));
@@ -48,7 +48,7 @@ const Save = ({ title, postId, hasUserLike, handleUserLike, metrikaGoal, size, t
48
48
  handleUserLike();
49
49
  metrika_1.default.reachGoal(utils_1.MetrikaCounter.CrossSite, metrikaGoal);
50
50
  handleAnalytics();
51
- }, "data-qa": `${qa ? qa + '-' : ''}save` },
51
+ }, "data-qa": qa },
52
52
  react_1.default.createElement("div", { className: b('content', { cursor: isLikeable, theme }) },
53
53
  react_1.default.createElement("span", { className: b('icon') },
54
54
  react_1.default.createElement(uikit_1.Icon, { data: hasUserLike ? SaveFilled_1.SaveFilled : Save_1.Save, size: ICON_SIZE, className: b({ filled: Boolean(hasUserLike) }) })),
@@ -1,5 +1,5 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
- import { NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
2
+ import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
3
  import { GetPostsType, MetaProps, PostsProps, Service, SetQueryType, Tag, ToggleLikeCallbackType } from '../../models/common';
4
4
  export type BlogPageProps = {
5
5
  content: PageContent;
@@ -13,8 +13,9 @@ export type BlogPageProps = {
13
13
  metaData?: MetaProps;
14
14
  setQuery?: SetQueryType;
15
15
  settings?: PageConstructorProviderProps;
16
+ custom?: CustomConfig;
16
17
  pageCountForShowSupportButtons?: number;
17
18
  isSignedInUser?: boolean;
18
19
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
19
20
  };
20
- export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser, onClickSignIn, }: BlogPageProps) => React.JSX.Element;
21
+ export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, custom, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser, onClickSignIn, }: BlogPageProps) => React.JSX.Element;
@@ -7,12 +7,13 @@ const page_constructor_1 = require("@gravity-ui/page-constructor");
7
7
  const MetaWrapper_1 = require("../../components/MetaWrapper/MetaWrapper");
8
8
  const PromptSignIn_1 = require("../../components/PromptSignIn/PromptSignIn");
9
9
  const usePromptSignInProps_1 = require("../../components/PromptSignIn/hooks/usePromptSignInProps");
10
- const blocksMap_1 = tslib_1.__importDefault(require("../../constructor/blocksMap"));
11
10
  const FeedContext_1 = require("../../contexts/FeedContext");
12
11
  const LikesContext_1 = require("../../contexts/LikesContext");
13
- const BlogPage = ({ content, posts, tags, services, getPosts, metaData, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser = false, onClickSignIn, }) => {
12
+ const useExtendedComponentMap_1 = require("../../hooks/useExtendedComponentMap");
13
+ const BlogPage = ({ content, posts, tags, services, getPosts, metaData, custom, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser = false, onClickSignIn, }) => {
14
14
  const _a = (0, usePromptSignInProps_1.usePromptSignInProps)(onClickSignIn), { requireSignIn } = _a, promptSignInProps = tslib_1.__rest(_a, ["requireSignIn"]);
15
15
  const likesContextData = (0, react_1.useMemo)(() => ({ toggleLike, hasLikes, isSignedInUser, requireSignIn }), [toggleLike, hasLikes, isSignedInUser, requireSignIn]);
16
+ const actualComponentMap = (0, useExtendedComponentMap_1.useExtendedComponentMap)(custom);
16
17
  return (react_1.default.createElement(LikesContext_1.LikesContext.Provider, { value: likesContextData },
17
18
  react_1.default.createElement(FeedContext_1.FeedContext.Provider, { value: {
18
19
  posts: posts.posts,
@@ -25,7 +26,7 @@ const BlogPage = ({ content, posts, tags, services, getPosts, metaData, hasLikes
25
26
  } },
26
27
  react_1.default.createElement(page_constructor_1.PageConstructorProvider, Object.assign({}, settings),
27
28
  metaData ? react_1.default.createElement(MetaWrapper_1.MetaWrapper, Object.assign({}, metaData)) : null,
28
- react_1.default.createElement(page_constructor_1.PageConstructor, { content: content, custom: blocksMap_1.default, navigation: navigation }))),
29
+ react_1.default.createElement(page_constructor_1.PageConstructor, { content: content, custom: actualComponentMap, navigation: navigation }))),
29
30
  react_1.default.createElement(PromptSignIn_1.PromptSignIn, Object.assign({}, promptSignInProps))));
30
31
  };
31
32
  exports.BlogPage = BlogPage;
@@ -1,6 +1,6 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
- import { NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
+ import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
4
4
  import { MetaProps, PostData, ToggleLikeCallbackType } from '../../models/common';
5
5
  export interface BlogPostPageProps {
6
6
  suggestedPosts: PostData[];
@@ -14,8 +14,9 @@ export interface BlogPostPageProps {
14
14
  post: PostData;
15
15
  settings?: PageConstructorProviderProps;
16
16
  navigation?: NavigationData;
17
+ custom?: CustomConfig;
17
18
  shareOptions?: ShareOptions[];
18
19
  isSignedInUser?: boolean;
19
20
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
20
21
  }
21
- export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
22
+ export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
@@ -7,11 +7,11 @@ const page_constructor_1 = require("@gravity-ui/page-constructor");
7
7
  const MetaWrapper_1 = require("../../components/MetaWrapper/MetaWrapper");
8
8
  const PromptSignIn_1 = require("../../components/PromptSignIn/PromptSignIn");
9
9
  const usePromptSignInProps_1 = require("../../components/PromptSignIn/hooks/usePromptSignInProps");
10
- const blocksMap_1 = tslib_1.__importDefault(require("../../constructor/blocksMap"));
11
10
  const LikesContext_1 = require("../../contexts/LikesContext");
12
11
  const PostPageContext_1 = require("../../contexts/PostPageContext");
12
+ const useExtendedComponentMap_1 = require("../../hooks/useExtendedComponentMap");
13
13
  const useLikes_1 = require("../../hooks/useLikes");
14
- const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
14
+ const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
15
15
  const { hasUserLike, likesCount, handleLike } = (0, useLikes_1.useLikes)({
16
16
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
17
17
  count: likes === null || likes === void 0 ? void 0 : likes.likesCount,
@@ -25,6 +25,7 @@ const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings
25
25
  isSignedInUser,
26
26
  requireSignIn,
27
27
  }), [likes, isSignedInUser, requireSignIn]);
28
+ const actualComponentMap = (0, useExtendedComponentMap_1.useExtendedComponentMap)(custom);
28
29
  return (react_1.default.createElement(LikesContext_1.LikesContext.Provider, { value: likesContextData },
29
30
  react_1.default.createElement(PostPageContext_1.PostPageContext.Provider, { value: {
30
31
  post,
@@ -40,7 +41,7 @@ const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings
40
41
  } },
41
42
  react_1.default.createElement(page_constructor_1.PageConstructorProvider, Object.assign({}, settings),
42
43
  metaData ? react_1.default.createElement(MetaWrapper_1.MetaWrapper, Object.assign({}, metaData)) : null,
43
- react_1.default.createElement(page_constructor_1.PageConstructor, { content: content, custom: blocksMap_1.default, navigation: navigation }))),
44
+ react_1.default.createElement(page_constructor_1.PageConstructor, { content: content, custom: actualComponentMap, navigation: navigation }))),
44
45
  react_1.default.createElement(PromptSignIn_1.PromptSignIn, Object.assign({}, promptSignInProps))));
45
46
  };
46
47
  exports.BlogPostPage = BlogPostPage;
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
3
  import { PostData } from '../models/common';
4
+ export type LikesRoutineType = {
5
+ handleUserLike: () => void;
6
+ hasUserLike: boolean;
7
+ likesCount: number;
8
+ };
4
9
  export interface PostPageContextProps {
5
10
  post: PostData;
6
11
  suggestedPosts: PostData[];
7
- likes?: {
8
- handleUserLike: () => void;
9
- hasUserLike: boolean;
10
- likesCount: number;
11
- };
12
+ likes?: LikesRoutineType;
12
13
  shareOptions?: ShareOptions[];
13
14
  }
14
15
  export declare const PostPageContext: React.Context<PostPageContextProps>;
@@ -0,0 +1,24 @@
1
+ import { CustomConfig } from '@gravity-ui/page-constructor';
2
+ export declare const useExtendedComponentMap: (custom: CustomConfig | undefined) => {
3
+ blocks: {
4
+ "blog-yfm-block": (props: import("../models/blocks").YFMProps) => import("react").JSX.Element;
5
+ "blog-layout-block": ({ fullWidth, mobileOrder, children, paddingTop, paddingBottom, }: import("react").PropsWithChildren<import("../models/blocks").LayoutProps>) => import("react").JSX.Element;
6
+ "blog-media-block": ({ text, paddingTop, paddingBottom, ...mediaProps }: import("../models/blocks").MediaProps) => import("react").JSX.Element;
7
+ "blog-banner-block": ({ color, imageSize, image, paddingTop, paddingBottom, qa, ...content }: import("../models/blocks").BannerProps) => import("react").JSX.Element;
8
+ "blog-cta-block": ({ items, paddingTop, paddingBottom, qa }: import("../models/blocks").CTAProps) => import("react").JSX.Element;
9
+ "blog-colored-text-block": ({ background, paddingTop, paddingBottom, qa, ...content }: import("../models/blocks").ColoredTextProps) => import("react").JSX.Element;
10
+ "blog-author-block": (props: import("../models/blocks").AuthorProps) => import("react").JSX.Element | null;
11
+ "blog-suggest-block": ({ paddingTop, paddingBottom }: import("../models/blocks").SuggestProps) => import("react").JSX.Element | null;
12
+ "blog-meta-block": (props: import("../models/blocks").MetaProps) => import("react").JSX.Element;
13
+ "blog-feed-block": ({ image }: import("../models/blocks").FeedProps) => import("react").JSX.Element;
14
+ };
15
+ headers: {
16
+ "blog-header-block": (props: import("../models/blocks").HeaderProps) => import("react").JSX.Element;
17
+ };
18
+ subBlocks?: import("@gravity-ui/page-constructor").CustomItems | undefined;
19
+ navigation?: import("@gravity-ui/page-constructor").CustomItems | undefined;
20
+ loadable?: import("@gravity-ui/page-constructor").LoadableConfig | undefined;
21
+ decorators?: {
22
+ block?: ((props: import("@gravity-ui/page-constructor").BlockDecorationProps) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>)[] | undefined;
23
+ } | undefined;
24
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useExtendedComponentMap = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = require("react");
6
+ const page_constructor_1 = require("@gravity-ui/page-constructor");
7
+ const blocksMap_1 = tslib_1.__importDefault(require("../constructor/blocksMap"));
8
+ const useExtendedComponentMap = (custom) => (0, react_1.useMemo)(() => (Object.assign(Object.assign({}, custom), { blocks: Object.assign(Object.assign({}, blocksMap_1.default.blocks), (0, page_constructor_1.getCustomItems)(['blocks'], custom)), headers: Object.assign(Object.assign({}, blocksMap_1.default.headers), (0, page_constructor_1.getCustomItems)(['headers'], custom)) })), [custom]);
9
+ exports.useExtendedComponentMap = useExtendedComponentMap;
@@ -30,7 +30,7 @@ export type LayoutProps = {
30
30
  export type MediaProps = ClassNameProps & PaddingsYFMProps & Partial<Pick<PCMediaProps, 'youtube' | 'previewImg' | 'image' | 'video' | 'dataLens'>> & {
31
31
  text?: string;
32
32
  };
33
- export type MetaProps = {
33
+ export type MetaProps = QAProps & {
34
34
  locale: string;
35
35
  theme?: TextTheme;
36
36
  } & PaddingsYFMProps;
@@ -24,7 +24,9 @@ export declare const updateContentSizes: ({ size, colSizes, theme, ...contentDat
24
24
  } | Partial<Record<import("@gravity-ui/page-constructor").GridColumnSize, number>>;
25
25
  theme: import("@gravity-ui/page-constructor").ContentTheme;
26
26
  title?: string | import("@gravity-ui/page-constructor").TitleItemBaseProps | undefined;
27
+ titleId?: string | undefined;
27
28
  text?: string | undefined;
29
+ textId?: string | undefined;
28
30
  additionalInfo?: string | undefined;
29
31
  links?: import("@gravity-ui/page-constructor").LinkProps[] | undefined;
30
32
  buttons?: import("@gravity-ui/page-constructor").ButtonProps[] | undefined;
@@ -7,7 +7,7 @@ import { LocaleContext } from '../../contexts/LocaleContext';
7
7
  import { PostPageContext } from '../../contexts/PostPageContext';
8
8
  import { PaddingsDirections } from '../../models/paddings';
9
9
  import { block } from '../../utils/cn';
10
- import { getBreadcrumbs } from '../../utils/common';
10
+ import { getBreadcrumbs, getQaAttributes } from '../../utils/common';
11
11
  import './Meta.css';
12
12
  const b = block('meta');
13
13
  /**
@@ -24,20 +24,21 @@ const breadcrumbsGoals = [
24
24
  },
25
25
  ];
26
26
  export const Meta = (props) => {
27
- const { paddingTop = 'l', paddingBottom = 'l', theme = 'light' } = props;
27
+ const { paddingTop = 'l', paddingBottom = 'l', theme = 'light', qa } = props;
28
28
  const { post } = useContext(PostPageContext);
29
29
  const { locale } = useContext(LocaleContext);
30
+ const qaAttributes = getQaAttributes(qa, 'post-info');
30
31
  const { title, id, date, readingTime, tags } = post;
31
32
  const breadcrumbs = getBreadcrumbs({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
32
33
  breadcrumbs.metrikaGoals = breadcrumbsGoals;
33
34
  return (React.createElement(Wrapper, { paddings: {
34
35
  [PaddingsDirections.top]: paddingTop,
35
36
  [PaddingsDirections.bottom]: paddingBottom,
36
- }, qa: "blog-meta-content" },
37
+ }, qa: qaAttributes.wrapper },
37
38
  breadcrumbs && (React.createElement(HeaderBreadcrumbs, { items: breadcrumbs.items, className: b('breadcrumbs'), theme: theme, metrikaGoals: breadcrumbs.metrikaGoals })),
38
39
  title && (React.createElement(YFMWrapper, { content: title, modifiers: {
39
40
  blogBreadcrumbs: true,
40
41
  resetPaddings: true,
41
42
  } })),
42
- post && (React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, qa: "blog-meta-block" }))));
43
+ post && (React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, qa: qaAttributes.postInfo }))));
43
44
  };
@@ -5,6 +5,7 @@ import { Date } from './components/Date';
5
5
  import { ReadingTime } from './components/ReadingTime';
6
6
  import { Save } from './components/Save';
7
7
  import { Sharing } from './components/Sharing';
8
+ import { getQaAttributes } from '../../utils/common';
8
9
  import './PostInfo.css';
9
10
  const b = block('post-info');
10
11
  /**
@@ -21,9 +22,10 @@ const b = block('post-info');
21
22
  */
22
23
  export const PostInfo = ({ date, readingTime, postId, theme = 'light', metrikaGoals, qa, }) => {
23
24
  const { likes } = useContext(PostPageContext);
25
+ const qaAttributes = getQaAttributes(qa, 'date', 'reading-time', 'save');
24
26
  return (React.createElement("div", { className: b('container', { theme }) },
25
- date && React.createElement(Date, { date: date }),
26
- readingTime && React.createElement(ReadingTime, { readingTime: readingTime }),
27
+ date && React.createElement(Date, { date: date, qa: qaAttributes.date }),
28
+ readingTime && React.createElement(ReadingTime, { readingTime: readingTime, qa: qaAttributes.readingTime }),
27
29
  React.createElement(Sharing, { metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.sharing, theme: theme }),
28
- likes && (React.createElement(Save, { postId: postId, title: likes.likesCount, hasUserLike: likes.hasUserLike, handleUserLike: likes.handleUserLike, metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.save, theme: theme, qa: qa }))));
30
+ likes && (React.createElement(Save, { postId: postId, title: likes.likesCount, hasUserLike: likes.hasUserLike, handleUserLike: likes.handleUserLike, metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.save, theme: theme, qa: qaAttributes.save }))));
29
31
  };
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import { PostCardSize } from '../../../models/common';
2
+ import { PostCardSize, QAProps } from '../../../models/common';
3
3
  import '../PostInfo.css';
4
- type DateProps = {
4
+ type DateProps = QAProps & {
5
5
  date: string | number;
6
6
  size?: PostCardSize;
7
7
  id?: string;
8
8
  };
9
- export declare const Date: ({ date, size, id }: DateProps) => React.JSX.Element;
9
+ export declare const Date: ({ date, size, id, qa }: DateProps) => React.JSX.Element;
10
10
  export {};
@@ -5,7 +5,7 @@ import { block } from '../../../utils/cn';
5
5
  import { format } from '../../../utils/date';
6
6
  import '../PostInfo.css';
7
7
  const b = block('post-info');
8
- export const Date = ({ date, size = PostCardSize.SMALL, id }) => {
8
+ export const Date = ({ date, size = PostCardSize.SMALL, id, qa }) => {
9
9
  const { locale } = useContext(LocaleContext);
10
- return (React.createElement("div", { className: b('item', { size }), id: id }, format(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
10
+ return (React.createElement("div", { className: b('item', { size }), id: id, "data-qa": qa }, format(date, 'longDate', locale === null || locale === void 0 ? void 0 : locale.code)));
11
11
  };
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
+ import { QAProps } from '../../../models/common';
2
3
  import '../PostInfo.css';
3
- type ReadingTimeProps = {
4
+ type ReadingTimeProps = QAProps & {
4
5
  readingTime: number;
5
6
  size?: 's' | 'm';
6
7
  id?: string;
7
8
  };
8
- export declare const ReadingTime: ({ readingTime, size, id }: ReadingTimeProps) => React.JSX.Element;
9
+ export declare const ReadingTime: ({ readingTime, size, id, qa }: ReadingTimeProps) => React.JSX.Element;
9
10
  export {};
@@ -6,7 +6,7 @@ import { block } from '../../../utils/cn';
6
6
  import '../PostInfo.css';
7
7
  const b = block('post-info');
8
8
  const ICON_SIZE = 16;
9
- export const ReadingTime = ({ readingTime, size = 's', id }) => (React.createElement("div", { className: b('item', { size }), id: id },
9
+ export const ReadingTime = ({ readingTime, size = 's', id, qa }) => (React.createElement("div", { className: b('item', { size }), id: id, "data-qa": qa },
10
10
  React.createElement("span", { className: b('icon') },
11
11
  React.createElement(Icon, { data: Time, size: ICON_SIZE, className: b('icon-color') })),
12
12
  i18(Keyset.ContextReadingTime, { count: readingTime })));
@@ -45,7 +45,7 @@ export const Save = ({ title, postId, hasUserLike, handleUserLike, metrikaGoal,
45
45
  handleUserLike();
46
46
  metrika.reachGoal(MetrikaCounter.CrossSite, metrikaGoal);
47
47
  handleAnalytics();
48
- }, "data-qa": `${qa ? qa + '-' : ''}save` },
48
+ }, "data-qa": qa },
49
49
  React.createElement("div", { className: b('content', { cursor: isLikeable, theme }) },
50
50
  React.createElement("span", { className: b('icon') },
51
51
  React.createElement(Icon, { data: hasUserLike ? SaveFilled : SaveIcon, size: ICON_SIZE, className: b({ filled: Boolean(hasUserLike) }) })),
@@ -1,5 +1,5 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
- import { NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
2
+ import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
3
  import { GetPostsType, MetaProps, PostsProps, Service, SetQueryType, Tag, ToggleLikeCallbackType } from '../../models/common';
4
4
  import './BlogPage.css';
5
5
  export type BlogPageProps = {
@@ -14,8 +14,9 @@ export type BlogPageProps = {
14
14
  metaData?: MetaProps;
15
15
  setQuery?: SetQueryType;
16
16
  settings?: PageConstructorProviderProps;
17
+ custom?: CustomConfig;
17
18
  pageCountForShowSupportButtons?: number;
18
19
  isSignedInUser?: boolean;
19
20
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
20
21
  };
21
- export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser, onClickSignIn, }: BlogPageProps) => React.JSX.Element;
22
+ export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, custom, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser, onClickSignIn, }: BlogPageProps) => React.JSX.Element;
@@ -4,13 +4,14 @@ import { PageConstructor, PageConstructorProvider, } from '@gravity-ui/page-cons
4
4
  import { MetaWrapper } from '../../components/MetaWrapper/MetaWrapper';
5
5
  import { PromptSignIn } from '../../components/PromptSignIn/PromptSignIn';
6
6
  import { usePromptSignInProps } from '../../components/PromptSignIn/hooks/usePromptSignInProps';
7
- import componentMap from '../../constructor/blocksMap';
8
7
  import { FeedContext } from '../../contexts/FeedContext';
9
8
  import { LikesContext } from '../../contexts/LikesContext';
9
+ import { useExtendedComponentMap } from '../../hooks/useExtendedComponentMap';
10
10
  import './BlogPage.css';
11
- export const BlogPage = ({ content, posts, tags, services, getPosts, metaData, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser = false, onClickSignIn, }) => {
11
+ export const BlogPage = ({ content, posts, tags, services, getPosts, metaData, custom, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser = false, onClickSignIn, }) => {
12
12
  const _a = usePromptSignInProps(onClickSignIn), { requireSignIn } = _a, promptSignInProps = __rest(_a, ["requireSignIn"]);
13
13
  const likesContextData = useMemo(() => ({ toggleLike, hasLikes, isSignedInUser, requireSignIn }), [toggleLike, hasLikes, isSignedInUser, requireSignIn]);
14
+ const actualComponentMap = useExtendedComponentMap(custom);
14
15
  return (React.createElement(LikesContext.Provider, { value: likesContextData },
15
16
  React.createElement(FeedContext.Provider, { value: {
16
17
  posts: posts.posts,
@@ -23,6 +24,6 @@ export const BlogPage = ({ content, posts, tags, services, getPosts, metaData, h
23
24
  } },
24
25
  React.createElement(PageConstructorProvider, Object.assign({}, settings),
25
26
  metaData ? React.createElement(MetaWrapper, Object.assign({}, metaData)) : null,
26
- React.createElement(PageConstructor, { content: content, custom: componentMap, navigation: navigation }))),
27
+ React.createElement(PageConstructor, { content: content, custom: actualComponentMap, navigation: navigation }))),
27
28
  React.createElement(PromptSignIn, Object.assign({}, promptSignInProps))));
28
29
  };
@@ -1,6 +1,6 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
- import { NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
+ import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
4
4
  import { MetaProps, PostData, ToggleLikeCallbackType } from '../../models/common';
5
5
  import './BlogPostPage.css';
6
6
  export interface BlogPostPageProps {
@@ -15,8 +15,9 @@ export interface BlogPostPageProps {
15
15
  post: PostData;
16
16
  settings?: PageConstructorProviderProps;
17
17
  navigation?: NavigationData;
18
+ custom?: CustomConfig;
18
19
  shareOptions?: ShareOptions[];
19
20
  isSignedInUser?: boolean;
20
21
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
21
22
  }
22
- export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
23
+ export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
@@ -4,12 +4,12 @@ import { PageConstructor, PageConstructorProvider, } from '@gravity-ui/page-cons
4
4
  import { MetaWrapper } from '../../components/MetaWrapper/MetaWrapper';
5
5
  import { PromptSignIn } from '../../components/PromptSignIn/PromptSignIn';
6
6
  import { usePromptSignInProps } from '../../components/PromptSignIn/hooks/usePromptSignInProps';
7
- import componentMap from '../../constructor/blocksMap';
8
7
  import { LikesContext } from '../../contexts/LikesContext';
9
8
  import { PostPageContext } from '../../contexts/PostPageContext';
9
+ import { useExtendedComponentMap } from '../../hooks/useExtendedComponentMap';
10
10
  import { useLikes } from '../../hooks/useLikes';
11
11
  import './BlogPostPage.css';
12
- export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
12
+ export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
13
13
  const { hasUserLike, likesCount, handleLike } = useLikes({
14
14
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
15
15
  count: likes === null || likes === void 0 ? void 0 : likes.likesCount,
@@ -23,6 +23,7 @@ export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, s
23
23
  isSignedInUser,
24
24
  requireSignIn,
25
25
  }), [likes, isSignedInUser, requireSignIn]);
26
+ const actualComponentMap = useExtendedComponentMap(custom);
26
27
  return (React.createElement(LikesContext.Provider, { value: likesContextData },
27
28
  React.createElement(PostPageContext.Provider, { value: {
28
29
  post,
@@ -38,6 +39,6 @@ export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, s
38
39
  } },
39
40
  React.createElement(PageConstructorProvider, Object.assign({}, settings),
40
41
  metaData ? React.createElement(MetaWrapper, Object.assign({}, metaData)) : null,
41
- React.createElement(PageConstructor, { content: content, custom: componentMap, navigation: navigation }))),
42
+ React.createElement(PageConstructor, { content: content, custom: actualComponentMap, navigation: navigation }))),
42
43
  React.createElement(PromptSignIn, Object.assign({}, promptSignInProps))));
43
44
  };
@@ -1,14 +1,15 @@
1
1
  import React from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
3
  import { PostData } from '../models/common';
4
+ export type LikesRoutineType = {
5
+ handleUserLike: () => void;
6
+ hasUserLike: boolean;
7
+ likesCount: number;
8
+ };
4
9
  export interface PostPageContextProps {
5
10
  post: PostData;
6
11
  suggestedPosts: PostData[];
7
- likes?: {
8
- handleUserLike: () => void;
9
- hasUserLike: boolean;
10
- likesCount: number;
11
- };
12
+ likes?: LikesRoutineType;
12
13
  shareOptions?: ShareOptions[];
13
14
  }
14
15
  export declare const PostPageContext: React.Context<PostPageContextProps>;
@@ -0,0 +1,24 @@
1
+ import { CustomConfig } from '@gravity-ui/page-constructor';
2
+ export declare const useExtendedComponentMap: (custom: CustomConfig | undefined) => {
3
+ blocks: {
4
+ "blog-yfm-block": (props: import("../models/blocks").YFMProps) => import("react").JSX.Element;
5
+ "blog-layout-block": ({ fullWidth, mobileOrder, children, paddingTop, paddingBottom, }: import("react").PropsWithChildren<import("../models/blocks").LayoutProps>) => import("react").JSX.Element;
6
+ "blog-media-block": ({ text, paddingTop, paddingBottom, ...mediaProps }: import("../models/blocks").MediaProps) => import("react").JSX.Element;
7
+ "blog-banner-block": ({ color, imageSize, image, paddingTop, paddingBottom, qa, ...content }: import("../models/blocks").BannerProps) => import("react").JSX.Element;
8
+ "blog-cta-block": ({ items, paddingTop, paddingBottom, qa }: import("../models/blocks").CTAProps) => import("react").JSX.Element;
9
+ "blog-colored-text-block": ({ background, paddingTop, paddingBottom, qa, ...content }: import("../models/blocks").ColoredTextProps) => import("react").JSX.Element;
10
+ "blog-author-block": (props: import("../models/blocks").AuthorProps) => import("react").JSX.Element | null;
11
+ "blog-suggest-block": ({ paddingTop, paddingBottom }: import("../models/blocks").SuggestProps) => import("react").JSX.Element | null;
12
+ "blog-meta-block": (props: import("../models/blocks").MetaProps) => import("react").JSX.Element;
13
+ "blog-feed-block": ({ image }: import("../models/blocks").FeedProps) => import("react").JSX.Element;
14
+ };
15
+ headers: {
16
+ "blog-header-block": (props: import("../models/blocks").HeaderProps) => import("react").JSX.Element;
17
+ };
18
+ subBlocks?: import("@gravity-ui/page-constructor").CustomItems | undefined;
19
+ navigation?: import("@gravity-ui/page-constructor").CustomItems | undefined;
20
+ loadable?: import("@gravity-ui/page-constructor").LoadableConfig | undefined;
21
+ decorators?: {
22
+ block?: ((props: import("@gravity-ui/page-constructor").BlockDecorationProps) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>)[] | undefined;
23
+ } | undefined;
24
+ };
@@ -0,0 +1,4 @@
1
+ import { useMemo } from 'react';
2
+ import { getCustomItems } from '@gravity-ui/page-constructor';
3
+ import componentMap from '../constructor/blocksMap';
4
+ export const useExtendedComponentMap = (custom) => useMemo(() => (Object.assign(Object.assign({}, custom), { blocks: Object.assign(Object.assign({}, componentMap.blocks), getCustomItems(['blocks'], custom)), headers: Object.assign(Object.assign({}, componentMap.headers), getCustomItems(['headers'], custom)) })), [custom]);
@@ -30,7 +30,7 @@ export type LayoutProps = {
30
30
  export type MediaProps = ClassNameProps & PaddingsYFMProps & Partial<Pick<PCMediaProps, 'youtube' | 'previewImg' | 'image' | 'video' | 'dataLens'>> & {
31
31
  text?: string;
32
32
  };
33
- export type MetaProps = {
33
+ export type MetaProps = QAProps & {
34
34
  locale: string;
35
35
  theme?: TextTheme;
36
36
  } & PaddingsYFMProps;
@@ -24,7 +24,9 @@ export declare const updateContentSizes: ({ size, colSizes, theme, ...contentDat
24
24
  } | Partial<Record<import("@gravity-ui/page-constructor").GridColumnSize, number>>;
25
25
  theme: import("@gravity-ui/page-constructor").ContentTheme;
26
26
  title?: string | import("@gravity-ui/page-constructor").TitleItemBaseProps | undefined;
27
+ titleId?: string | undefined;
27
28
  text?: string | undefined;
29
+ textId?: string | undefined;
28
30
  additionalInfo?: string | undefined;
29
31
  links?: import("@gravity-ui/page-constructor").LinkProps[] | undefined;
30
32
  buttons?: import("@gravity-ui/page-constructor").ButtonProps[] | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/blog-constructor",
3
- "version": "5.10.0",
3
+ "version": "5.12.0",
4
4
  "description": "Gravity UI Blog Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -81,11 +81,11 @@
81
81
  "@commitlint/config-conventional": "^17.4.3",
82
82
  "@doc-tools/transform": "^3.11.0",
83
83
  "@gravity-ui/eslint-config": "^3.1.1",
84
- "@gravity-ui/page-constructor": "^4.31.1",
84
+ "@gravity-ui/page-constructor": "^4.37.2",
85
85
  "@gravity-ui/prettier-config": "^1.1.0",
86
86
  "@gravity-ui/stylelint-config": "^4.0.1",
87
87
  "@gravity-ui/tsconfig": "^1.0.0",
88
- "@gravity-ui/uikit": "^5.18.1",
88
+ "@gravity-ui/uikit": "^5.20.0",
89
89
  "@jest/environment": "^29.7.0",
90
90
  "@storybook/addon-essentials": "^7.0.27",
91
91
  "@storybook/cli": "^7.0.27",
@@ -30,7 +30,7 @@ export type LayoutProps = {
30
30
  export type MediaProps = ClassNameProps & PaddingsYFMProps & Partial<Pick<PCMediaProps, 'youtube' | 'previewImg' | 'image' | 'video' | 'dataLens'>> & {
31
31
  text?: string;
32
32
  };
33
- export type MetaProps = {
33
+ export type MetaProps = QAProps & {
34
34
  locale: string;
35
35
  theme?: TextTheme;
36
36
  } & PaddingsYFMProps;