@gravity-ui/blog-constructor 5.16.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +5 -5
  2. package/build/cjs/blocks/Banner/Banner.js +7 -9
  3. package/build/cjs/blocks/CTA/CTA.js +7 -9
  4. package/build/cjs/blocks/Feed/Feed.js +5 -12
  5. package/build/cjs/blocks/Header/Header.js +10 -14
  6. package/build/cjs/blocks/Media/Media.js +1 -0
  7. package/build/cjs/blocks/Meta/Meta.js +11 -15
  8. package/build/cjs/blocks/Suggest/Suggest.js +8 -11
  9. package/build/cjs/components/FeedHeader/components/Controls/Controls.css +19 -5
  10. package/build/cjs/components/FeedHeader/components/Controls/Controls.js +22 -27
  11. package/build/cjs/components/FeedHeader/components/Controls/customRenders.js +1 -1
  12. package/build/cjs/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.css +1 -1
  13. package/build/cjs/components/Paginator/Paginator.js +16 -19
  14. package/build/cjs/components/Paginator/components/NavigationButton.js +1 -1
  15. package/build/cjs/components/PostCard/PostCard.d.ts +3 -6
  16. package/build/cjs/components/PostCard/PostCard.js +2 -2
  17. package/build/cjs/components/PostInfo/PostInfo.d.ts +4 -10
  18. package/build/cjs/components/PostInfo/PostInfo.js +4 -4
  19. package/build/cjs/components/PostInfo/SuggestPostInfo.js +4 -1
  20. package/build/cjs/components/PostInfo/components/ReadingTime.js +1 -1
  21. package/build/cjs/components/PostInfo/components/Save.d.ts +4 -6
  22. package/build/cjs/components/PostInfo/components/Save.js +3 -6
  23. package/build/cjs/components/PostInfo/components/Sharing.d.ts +3 -5
  24. package/build/cjs/components/PostInfo/components/Sharing.js +4 -10
  25. package/build/cjs/components/Posts/Posts.js +3 -3
  26. package/build/cjs/components/PostsEmpty/PostsEmpty.js +2 -2
  27. package/build/cjs/components/PostsError/PostsError.js +3 -3
  28. package/build/cjs/components/PromptSignIn/PromptSignIn.js +2 -2
  29. package/build/cjs/components/Search/Search.js +1 -1
  30. package/build/cjs/constants.d.ts +2 -1
  31. package/build/cjs/constants.js +20 -19
  32. package/build/cjs/constructor/BlogConstructorProvider.js +1 -0
  33. package/build/cjs/containers/BlogPostPage/BlogPostPage.css +1 -1
  34. package/build/cjs/contexts/LocaleContext.js +2 -2
  35. package/build/cjs/counters/metrika.js +0 -3
  36. package/build/cjs/counters/utils.d.ts +1 -1
  37. package/build/cjs/counters/utils.js +7 -7
  38. package/build/cjs/i18n/index.d.ts +1 -3
  39. package/build/cjs/i18n/index.js +8 -10
  40. package/build/cjs/index.d.ts +0 -1
  41. package/build/cjs/index.js +1 -3
  42. package/build/cjs/models/common.d.ts +1 -1
  43. package/build/cjs/models/locale.d.ts +1 -4
  44. package/build/cjs/models/locale.js +1 -6
  45. package/build/cjs/utils/common.d.ts +15 -3
  46. package/build/cjs/utils/common.js +20 -19
  47. package/build/esm/blocks/Banner/Banner.js +8 -10
  48. package/build/esm/blocks/CTA/CTA.js +8 -10
  49. package/build/esm/blocks/Feed/Feed.js +8 -15
  50. package/build/esm/blocks/Header/Header.js +12 -16
  51. package/build/esm/blocks/Media/Media.js +1 -0
  52. package/build/esm/blocks/Meta/Meta.js +13 -17
  53. package/build/esm/blocks/Suggest/Suggest.js +9 -12
  54. package/build/esm/components/FeedHeader/components/Controls/Controls.css +19 -5
  55. package/build/esm/components/FeedHeader/components/Controls/Controls.js +25 -30
  56. package/build/esm/components/FeedHeader/components/Controls/customRenders.js +2 -2
  57. package/build/esm/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.css +1 -1
  58. package/build/esm/components/Paginator/Paginator.js +18 -21
  59. package/build/esm/components/Paginator/components/NavigationButton.js +2 -2
  60. package/build/esm/components/PostCard/PostCard.d.ts +3 -6
  61. package/build/esm/components/PostCard/PostCard.js +2 -2
  62. package/build/esm/components/PostInfo/PostInfo.d.ts +4 -10
  63. package/build/esm/components/PostInfo/PostInfo.js +4 -4
  64. package/build/esm/components/PostInfo/SuggestPostInfo.js +4 -1
  65. package/build/esm/components/PostInfo/components/ReadingTime.js +2 -2
  66. package/build/esm/components/PostInfo/components/Save.d.ts +4 -6
  67. package/build/esm/components/PostInfo/components/Save.js +3 -6
  68. package/build/esm/components/PostInfo/components/Sharing.d.ts +3 -5
  69. package/build/esm/components/PostInfo/components/Sharing.js +5 -11
  70. package/build/esm/components/Posts/Posts.js +4 -4
  71. package/build/esm/components/PostsEmpty/PostsEmpty.js +3 -3
  72. package/build/esm/components/PostsError/PostsError.js +4 -4
  73. package/build/esm/components/PromptSignIn/PromptSignIn.js +3 -3
  74. package/build/esm/components/Search/Search.js +2 -2
  75. package/build/esm/constants.d.ts +2 -1
  76. package/build/esm/constants.js +19 -18
  77. package/build/esm/constructor/BlogConstructorProvider.js +2 -1
  78. package/build/esm/containers/BlogPostPage/BlogPostPage.css +1 -1
  79. package/build/esm/contexts/LocaleContext.js +1 -1
  80. package/build/esm/counters/metrika.js +0 -3
  81. package/build/esm/counters/utils.d.ts +1 -1
  82. package/build/esm/counters/utils.js +6 -6
  83. package/build/esm/i18n/index.d.ts +1 -3
  84. package/build/esm/i18n/index.js +7 -9
  85. package/build/esm/index.d.ts +0 -1
  86. package/build/esm/index.js +0 -1
  87. package/build/esm/models/common.d.ts +1 -1
  88. package/build/esm/models/locale.d.ts +1 -4
  89. package/build/esm/models/locale.js +0 -5
  90. package/build/esm/utils/common.d.ts +15 -3
  91. package/build/esm/utils/common.js +18 -17
  92. package/package.json +15 -14
  93. package/server/data/contentFilter.d.ts +1 -1
  94. package/server/data/contentFilter.js +2 -1
  95. package/server/data/transformPageContent.d.ts +2 -2
  96. package/server/data/transformPost.d.ts +7 -2
  97. package/server/data/transformPost.js +1 -1
  98. package/server/index.d.ts +1 -1
  99. package/server/models/common.d.ts +1 -1
  100. package/server/models/locale.d.ts +1 -4
  101. package/server/models/locale.js +1 -6
  102. package/styles/storybook/common.scss +8 -0
  103. package/styles/storybook/index.scss +1 -1
  104. package/styles/styles.css +115 -0
  105. package/styles/styles.scss +1 -0
  106. package/build/cjs/configure.d.ts +0 -5
  107. package/build/cjs/configure.js +0 -8
  108. package/build/esm/configure.d.ts +0 -5
  109. package/build/esm/configure.js +0 -4
@@ -1,20 +1,18 @@
1
1
  import React from 'react';
2
2
  import { Content } from '@gravity-ui/page-constructor';
3
3
  import { Wrapper } from '../../components/Wrapper/Wrapper';
4
- import { BlogMetrikaGoalIds } from '../../constants';
5
4
  import { PaddingsDirections } from '../../models/paddings';
6
5
  import { block } from '../../utils/cn';
7
- import { getBlogElementMetrika, getQaAttributes, updateContentSizes } from '../../utils/common';
6
+ import { getMergedAnalyticsEvents, getQaAttributes, prepareAnalyticsEvent, updateContentSizes, } from '../../utils/common';
7
+ import { DefaultGoalIds } from '../../constants';
8
+ import { AnalyticsCounter } from '../../counters/utils';
8
9
  import './CTA.css';
9
10
  const b = block('cta');
11
+ const linkGoals = prepareAnalyticsEvent({
12
+ name: DefaultGoalIds.cta,
13
+ counter: AnalyticsCounter.CrossSite,
14
+ });
10
15
  export const CTA = ({ items, paddingTop, paddingBottom, qa }) => {
11
- /**
12
- * @deprecated Metrika will be deleted after launch of analyticsEvents
13
- */
14
- const metrikaGoal = {
15
- name: BlogMetrikaGoalIds.cta,
16
- isCrossSite: true,
17
- };
18
16
  const qaAttributes = getQaAttributes(qa, 'card');
19
17
  return (React.createElement(Wrapper, { paddings: {
20
18
  [PaddingsDirections.top]: paddingTop,
@@ -24,7 +22,7 @@ export const CTA = ({ items, paddingTop, paddingBottom, qa }) => {
24
22
  const contentData = updateContentSizes(content);
25
23
  (_a = contentData.links) === null || _a === void 0 ? void 0 : _a.forEach((link) => {
26
24
  // eslint-disable-next-line no-not-accumulator-reassign/no-not-accumulator-reassign
27
- link.metrikaGoals = getBlogElementMetrika(metrikaGoal, link.metrikaGoals);
25
+ link.analyticsEvents = getMergedAnalyticsEvents(linkGoals, link.analyticsEvents);
28
26
  });
29
27
  return (React.createElement("div", { key: index, className: b('card'), "data-qa": qaAttributes.card },
30
28
  React.createElement(Content, Object.assign({}, contentData, { qa: qaAttributes.content }))));
@@ -1,22 +1,15 @@
1
1
  import React, { useCallback, useContext, useEffect, useMemo, useReducer } from 'react';
2
2
  import { useAnalytics } from '@gravity-ui/page-constructor';
3
- /**
4
- * @deprecated Metrika will be deleted after launch of analyticsEvents
5
- */
6
3
  import { Icon } from '@gravity-ui/uikit';
7
4
  import { FeedHeader } from '../../components/FeedHeader/FeedHeader';
8
5
  import { Posts } from '../../components/Posts/Posts';
9
6
  import { PostsError } from '../../components/PostsError/PostsError';
10
- import { BlogMetrikaGoalIds } from '../../constants';
7
+ import { DefaultGoalIds } from '../../constants';
11
8
  import { FeedContext } from '../../contexts/FeedContext';
12
9
  import { RouterContext } from '../../contexts/RouterContext';
13
- /**
14
- * @deprecated Metrika will be deleted after launch of analyticsEvents
15
- */
16
- import metrika from '../../counters/metrika';
17
- import { MetrikaCounter } from '../../counters/utils';
10
+ import { AnalyticsCounter } from '../../counters/utils';
18
11
  import { DefaultEventNames } from '../../models/common';
19
- import { getFeedQueryParams, scrollOnPageChange } from '../../utils/common';
12
+ import { getFeedQueryParams, prepareAnalyticsEvent, scrollOnPageChange } from '../../utils/common';
20
13
  import { DEFAULT_PAGE, DEFAULT_ROWS_PER_PAGE } from '../constants';
21
14
  import { ActionTypes, reducer } from './reducer';
22
15
  const CONTAINER_ID = 'blog-cards';
@@ -27,6 +20,10 @@ export const Feed = ({ image }) => {
27
20
  const { posts, totalCount, tags, services, pinnedPost, getPosts, pageCountForShowSupportButtons, } = useContext(FeedContext);
28
21
  const router = useContext(RouterContext);
29
22
  const handleAnalytics = useAnalytics(DefaultEventNames.ShowMore);
23
+ const additionalAnalyticsEvent = prepareAnalyticsEvent({
24
+ name: DefaultGoalIds.showMore,
25
+ counter: AnalyticsCounter.CrossSite,
26
+ });
30
27
  const [{ errorLoad, errorShowMore, isFetching, isShowMoreVisible, lastLoadedCount, postCountOnPage, postsOnPage, pinnedPostOnPage, currentPage, queryParams, }, dispatch,] = useReducer(reducer, {
31
28
  errorLoad: false,
32
29
  errorShowMore: false,
@@ -101,11 +98,7 @@ export const Feed = ({ image }) => {
101
98
  });
102
99
  };
103
100
  const handleShowMore = async () => {
104
- /**
105
- * @deprecated Metrika will be deleted after launch of analyticsEvents
106
- */
107
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.showMore);
108
- handleAnalytics();
101
+ handleAnalytics(additionalAnalyticsEvent);
109
102
  const nextPage = currentPage + 1;
110
103
  try {
111
104
  setIsFetching(true);
@@ -2,25 +2,21 @@ import React, { useContext } from 'react';
2
2
  import { HeaderBlock } from '@gravity-ui/page-constructor';
3
3
  import { PostInfo } from '../../components/PostInfo/PostInfo';
4
4
  import { Wrapper } from '../../components/Wrapper/Wrapper';
5
- import { BlogMetrikaGoalIds } from '../../constants';
5
+ import { DefaultGoalIds } from '../../constants';
6
6
  import { LocaleContext } from '../../contexts/LocaleContext';
7
7
  import { PostPageContext } from '../../contexts/PostPageContext';
8
8
  import { PaddingsDirections } from '../../models/paddings';
9
- import { getBreadcrumbs, getBlogPath as getDefaultBlogPath } from '../../utils/common';
9
+ import { getBreadcrumbs, getBlogPath as getDefaultBlogPath, prepareAnalyticsEvent, } from '../../utils/common';
10
10
  import { SettingsContext } from '../../contexts/SettingsContext';
11
- /**
12
- * @deprecated Metrika will be deleted after launch of analyticsEvents
13
- */
14
- const metrikaGoals = {
15
- sharing: BlogMetrikaGoalIds.shareTop,
16
- save: BlogMetrikaGoalIds.saveTop,
11
+ import { AnalyticsCounter } from '../../counters/utils';
12
+ const analyticsEventsContainer = {
13
+ sharing: prepareAnalyticsEvent({ name: DefaultGoalIds.shareTop }),
14
+ save: prepareAnalyticsEvent({ name: DefaultGoalIds.saveTop }),
17
15
  };
18
- const breadcrumbsGoals = [
19
- {
20
- name: BlogMetrikaGoalIds.breadcrumbsTop,
21
- isCrossSite: true,
22
- },
23
- ];
16
+ const breadcrumbsGoals = prepareAnalyticsEvent({
17
+ name: DefaultGoalIds.breadcrumbsTop,
18
+ counter: AnalyticsCounter.CrossSite,
19
+ });
24
20
  export const Header = (props) => {
25
21
  const { theme, paddingTop, paddingBottom } = props;
26
22
  const { post } = useContext(PostPageContext);
@@ -32,11 +28,11 @@ export const Header = (props) => {
32
28
  if (theme === 'dark' && breadcrumbs) {
33
29
  breadcrumbs.theme = 'dark';
34
30
  }
35
- breadcrumbs.metrikaGoals = breadcrumbsGoals;
31
+ breadcrumbs.analyticsEvents = breadcrumbsGoals;
36
32
  return (React.createElement(Wrapper, { paddings: {
37
33
  [PaddingsDirections.top]: paddingTop,
38
34
  [PaddingsDirections.bottom]: paddingBottom,
39
35
  } },
40
36
  React.createElement(HeaderBlock, Object.assign({}, props, { title: title, description: description, breadcrumbs: breadcrumbs }),
41
- React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, theme: theme, qa: "blog-header-meta-container" }))));
37
+ React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, analyticsEventsContainer: analyticsEventsContainer, theme: theme, qa: "blog-header-meta-container" }))));
42
38
  };
@@ -16,6 +16,7 @@ export const Media = (_a) => {
16
16
  React.createElement(PCMedia, Object.assign({ className: b('content'), videoClassName: b('video'), imageClassName: b('image') }, mediaProps))),
17
17
  text && (React.createElement("div", { className: b('text-content') },
18
18
  React.createElement(YFMWrapper, { content: text, modifiers: {
19
+ blog: true,
19
20
  blogMedia: true,
20
21
  resetPaddings: true,
21
22
  } })))));
@@ -2,28 +2,24 @@ import React, { useContext } from 'react';
2
2
  import { HeaderBreadcrumbs, YFMWrapper } from '@gravity-ui/page-constructor';
3
3
  import { PostInfo } from '../../components/PostInfo/PostInfo';
4
4
  import { Wrapper } from '../../components/Wrapper/Wrapper';
5
- import { BlogMetrikaGoalIds } from '../../constants';
5
+ import { DefaultGoalIds } from '../../constants';
6
6
  import { LocaleContext } from '../../contexts/LocaleContext';
7
7
  import { SettingsContext } from '../../contexts/SettingsContext';
8
8
  import { PostPageContext } from '../../contexts/PostPageContext';
9
9
  import { PaddingsDirections } from '../../models/paddings';
10
10
  import { block } from '../../utils/cn';
11
- import { getBreadcrumbs, getBlogPath as getDefaultBlogPath, getQaAttributes, } from '../../utils/common';
11
+ import { getBreadcrumbs, getBlogPath as getDefaultBlogPath, getMergedAnalyticsEvents, getQaAttributes, prepareAnalyticsEvent, } from '../../utils/common';
12
+ import { AnalyticsCounter } from '../../counters/utils';
12
13
  import './Meta.css';
13
14
  const b = block('meta');
14
- /**
15
- * @deprecated Metrika will be deleted after launch of analyticsEvents
16
- */
17
- const metrikaGoals = {
18
- sharing: BlogMetrikaGoalIds.shareBottom,
19
- save: BlogMetrikaGoalIds.saveBottom,
15
+ const analyticsEventsContainer = {
16
+ sharing: prepareAnalyticsEvent({ name: DefaultGoalIds.shareBottom }),
17
+ save: prepareAnalyticsEvent({ name: DefaultGoalIds.saveBottom }),
20
18
  };
21
- const breadcrumbsGoals = [
22
- {
23
- name: BlogMetrikaGoalIds.breadcrumbsBottom,
24
- isCrossSite: true,
25
- },
26
- ];
19
+ const breadcrumbsGoals = prepareAnalyticsEvent({
20
+ name: DefaultGoalIds.breadcrumbsBottom,
21
+ counter: AnalyticsCounter.CrossSite,
22
+ });
27
23
  export const Meta = (props) => {
28
24
  const { paddingTop = 'l', paddingBottom = 'l', theme = 'light', qa } = props;
29
25
  const { post } = useContext(PostPageContext);
@@ -33,15 +29,15 @@ export const Meta = (props) => {
33
29
  const blogPath = getBlogPath(locale.pathPrefix || '');
34
30
  const { title, id, date, readingTime, tags } = post;
35
31
  const breadcrumbs = getBreadcrumbs({ tags, blogPath });
36
- breadcrumbs.metrikaGoals = breadcrumbsGoals;
32
+ breadcrumbs.analyticsEvents = getMergedAnalyticsEvents(breadcrumbsGoals);
37
33
  return (React.createElement(Wrapper, { paddings: {
38
34
  [PaddingsDirections.top]: paddingTop,
39
35
  [PaddingsDirections.bottom]: paddingBottom,
40
36
  }, qa: qaAttributes.wrapper },
41
- breadcrumbs && (React.createElement(HeaderBreadcrumbs, { items: breadcrumbs.items, className: b('breadcrumbs'), theme: theme, metrikaGoals: breadcrumbs.metrikaGoals })),
37
+ breadcrumbs && (React.createElement(HeaderBreadcrumbs, { items: breadcrumbs.items, className: b('breadcrumbs'), theme: theme })),
42
38
  title && (React.createElement(YFMWrapper, { content: title, modifiers: {
43
39
  blogBreadcrumbs: true,
44
40
  resetPaddings: true,
45
41
  } })),
46
- post && (React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, metrikaGoals: metrikaGoals, qa: qaAttributes.postInfo }))));
42
+ post && (React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, analyticsEventsContainer: analyticsEventsContainer, qa: qaAttributes.postInfo }))));
47
43
  };
@@ -2,19 +2,16 @@ import React, { useContext } from 'react';
2
2
  import { SliderBlock } from '@gravity-ui/page-constructor';
3
3
  import { PostCard } from '../../components/PostCard/PostCard';
4
4
  import { Wrapper } from '../../components/Wrapper/Wrapper';
5
- import { BlogMetrikaGoalIds } from '../../constants';
6
5
  import { PostPageContext } from '../../contexts/PostPageContext';
7
- import { Keyset, i18 } from '../../i18n';
6
+ import { Keyset, i18n } from '../../i18n';
8
7
  import { PaddingsDirections } from '../../models/paddings';
9
- /**
10
- * @deprecated Metrika will be deleted after launch of analyticsEvents
11
- */
12
- const metrikaGoals = [
13
- {
14
- name: BlogMetrikaGoalIds.suggest,
15
- isCrossSite: true,
16
- },
17
- ];
8
+ import { prepareAnalyticsEvent } from '../../utils/common';
9
+ import { DefaultGoalIds } from '../../constants';
10
+ import { AnalyticsCounter } from '../../counters/utils';
11
+ const suggestGoals = prepareAnalyticsEvent({
12
+ name: DefaultGoalIds.suggest,
13
+ counter: AnalyticsCounter.CrossSite,
14
+ });
18
15
  /**
19
16
  * Suggested posts block
20
17
  *
@@ -33,5 +30,5 @@ export const Suggest = ({ paddingTop = 'l', paddingBottom = 'l' }) => {
33
30
  [PaddingsDirections.top]: paddingTop,
34
31
  [PaddingsDirections.bottom]: paddingBottom,
35
32
  } },
36
- React.createElement(SliderBlock, { slidesToShow: { xl: 3, lg: 2, sm: 1 }, title: { text: i18(Keyset.TitleSuggest) }, lazyLoad: false }, suggestedPosts.map((post) => (React.createElement(PostCard, { key: post.id, metrikaGoals: metrikaGoals, post: post }))))));
33
+ React.createElement(SliderBlock, { slidesToShow: { xl: 3, lg: 2, sm: 1 }, title: { text: i18n(Keyset.TitleSuggest) }, lazyLoad: false }, suggestedPosts.map((post) => (React.createElement(PostCard, { key: post.id, analyticsEvents: suggestGoals, post: post }))))));
37
34
  };
@@ -36,10 +36,10 @@ unpredictable css rules order in build */
36
36
  .bc-feed-controls__popup.bc-feed-controls__popup .g-select-list::-webkit-scrollbar {
37
37
  display: none;
38
38
  }
39
- .bc-feed-controls__popup.bc-feed-controls__popup .g-select-list .yc-list {
39
+ .bc-feed-controls__popup.bc-feed-controls__popup .g-select-list .g-list {
40
40
  max-height: calc(500px - var(--g-text-body-3-line-height) - 12px);
41
41
  }
42
- .bc-feed-controls__popup.bc-feed-controls__popup .yc-list__item {
42
+ .bc-feed-controls__popup.bc-feed-controls__popup .g-list__item {
43
43
  margin: 4px;
44
44
  border-radius: 8px;
45
45
  }
@@ -48,12 +48,28 @@ unpredictable css rules order in build */
48
48
  max-height: inherit;
49
49
  }
50
50
 
51
+ .bc-feed-controls__popup_isMobile .bc-feed-controls__popup-filter {
52
+ position: relative;
53
+ border: none;
54
+ }
55
+ .bc-feed-controls__popup_isMobile .bc-feed-controls__popup-filter::before {
56
+ content: "";
57
+ position: absolute;
58
+ left: 50%;
59
+ bottom: 0px;
60
+ border-bottom: 2px solid var(--g-color-line-generic);
61
+ border-bottom-right-radius: 0;
62
+ border-bottom-left-radius: 0;
63
+ width: 100vw;
64
+ height: 2px;
65
+ transform: translateX(-50%);
66
+ }
51
67
  .bc-feed-controls__popup-filter {
52
68
  font-size: var(--g-text-body-2-font-size);
53
69
  line-height: var(--g-text-body-2-line-height);
54
70
  padding: 4px 12px;
55
71
  border: none;
56
- border-bottom: 1px solid var(--yc-color-line-generic);
72
+ border-bottom: 1px solid var(--g-color-line-generic);
57
73
  border-bottom-right-radius: 0;
58
74
  border-bottom-left-radius: 0;
59
75
  }
@@ -63,8 +79,6 @@ unpredictable css rules order in build */
63
79
  .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly {
64
80
  --g-button-background-color: var(--pc-monochrome-button-background-color);
65
81
  --g-button-background-color-hover: var(--pc-monochrome-button-background-color-hover);
66
- --yc-button-background-color: var(--pc-monochrome-button-background-color);
67
- --yc-button-background-color-hover: var(--pc-monochrome-button-background-color-hover);
68
82
  }
69
83
  .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly, .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly:link, .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly:visited, .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly:active, .bc-feed-controls__saved-only-button_savedOnly.bc-feed-controls__saved-only-button_savedOnly:focus {
70
84
  color: var(--pc-monochrome-button-color);
@@ -1,19 +1,16 @@
1
1
  import React, { useContext, useMemo, useState } from 'react';
2
2
  import { useAnalytics } from '@gravity-ui/page-constructor';
3
3
  import { Button, Icon, Select } from '@gravity-ui/uikit';
4
- /**
5
- * @deprecated Metrika will be deleted after launch of analyticsEvents
6
- */
7
- import { BlogMetrikaGoalIds } from '../../../../constants';
4
+ import { DefaultGoalIds } from '../../../../constants';
8
5
  import { LikesContext } from '../../../../contexts/LikesContext';
9
6
  import { MobileContext } from '../../../../contexts/MobileContext';
10
- import metrika from '../../../../counters/metrika';
11
- import { MetrikaCounter } from '../../../../counters/utils';
12
- import { Keyset, i18 } from '../../../../i18n';
7
+ import { AnalyticsCounter } from '../../../../counters/utils';
8
+ import { Keyset, i18n } from '../../../../i18n';
13
9
  import { Save } from '../../../../icons/Save';
14
10
  import { DefaultEventNames } from '../../../../models/common';
15
11
  import { block } from '../../../../utils/cn';
16
12
  import { Search } from '../../../Search/Search';
13
+ import { prepareAnalyticsEvent } from '../../../../utils/common';
17
14
  import { renderFilter, renderOption, renderSwitcher } from './customRenders';
18
15
  import './Controls.css';
19
16
  const b = block('feed-controls');
@@ -51,13 +48,11 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
51
48
  });
52
49
  };
53
50
  const handleTagSelect = (selectedTags) => {
54
- /**
55
- * @deprecated Metrika will be deleted after launch of analyticsEvents
56
- */
57
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.tag, {
58
- theme: selectedTags[0],
51
+ const event = prepareAnalyticsEvent({
52
+ name: DefaultGoalIds.tag,
53
+ counter: AnalyticsCounter.CrossSite,
59
54
  });
60
- handleAnalyticsTag(null, {
55
+ handleAnalyticsTag(event, {
61
56
  theme: selectedTags[0],
62
57
  });
63
58
  const isEmptyTag = selectedTags.some((tag) => tag === 'empty');
@@ -70,18 +65,18 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
70
65
  });
71
66
  };
72
67
  const handleServicesSelect = (selectedServices) => {
73
- const forMetrikaServices = services.filter((service) => {
68
+ const forAnalyticsServices = services.filter((service) => {
74
69
  return selectedServices.includes(service.value);
75
70
  });
76
- const metrikaAsString = forMetrikaServices.map((service) => service.content).join(',');
77
- /**
78
- * @deprecated Metrika will be deleted after launch of analyticsEvents
79
- */
80
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.service, {
81
- service: metrikaAsString,
71
+ const servicesAsStringForAnalytics = forAnalyticsServices
72
+ .map((service) => service.content)
73
+ .join(',');
74
+ const event = prepareAnalyticsEvent({
75
+ name: DefaultGoalIds.service,
76
+ counter: AnalyticsCounter.CrossSite,
82
77
  });
83
- handleAnalyticsService(null, {
84
- service: metrikaAsString,
78
+ handleAnalyticsService(event, {
79
+ service: servicesAsStringForAnalytics,
85
80
  });
86
81
  const servicesAsString = selectedServices.join(',');
87
82
  handleLoadData({
@@ -89,27 +84,27 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
89
84
  query: { services: servicesAsString, page: DEFAULT_PAGE },
90
85
  });
91
86
  };
92
- const tagsItems = useMemo(() => [{ value: 'empty', content: i18(Keyset.AllTags) }, ...tags], [tags]);
87
+ const tagsItems = useMemo(() => [{ value: 'empty', content: i18n(Keyset.AllTags) }, ...tags], [tags]);
93
88
  const servicesItems = useMemo(() => (servicesInitial ? [...servicesInitial.split(',')] : []), [servicesInitial]);
94
89
  return (React.createElement("div", { className: b('header') },
95
- React.createElement("h1", { className: b('header-item', { title: true }) }, i18(Keyset.Title)),
90
+ React.createElement("h1", { className: b('header-item', { title: true }) }, i18n(Keyset.Title)),
96
91
  React.createElement("div", { className: b('header-item', { filters: true }) },
97
92
  React.createElement("div", { className: b('filter-item') },
98
- React.createElement(Search, { className: b('search'), placeholder: i18(Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
93
+ React.createElement(Search, { className: b('search'), placeholder: i18n(Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
99
94
  React.createElement("div", { className: b('filter-item') },
100
- React.createElement(Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: i18(Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: renderSwitcher({
95
+ React.createElement(Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: i18n(Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: renderSwitcher({
101
96
  initial: [tagInitial],
102
97
  list: tagsItems,
103
- defaultLabel: i18(Keyset.AllTags),
98
+ defaultLabel: i18n(Keyset.AllTags),
104
99
  }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption })),
105
100
  services.length > 0 ? (React.createElement("div", { className: b('filter-item') },
106
- React.createElement(Select, { className: b('select'), size: "xl", multiple: true, filterable: true, hasClear: true, disablePortal: true, options: services, defaultValue: servicesItems, popupClassName: b('popup', { isMobile }), onUpdate: handleServicesSelect, placeholder: i18(Keyset.AllServices), renderControl: renderSwitcher({
101
+ React.createElement(Select, { className: b('select'), size: "xl", multiple: true, filterable: true, hasClear: true, disablePortal: true, options: services, defaultValue: servicesItems, popupClassName: b('popup', { isMobile }), onUpdate: handleServicesSelect, placeholder: i18n(Keyset.AllServices), renderControl: renderSwitcher({
107
102
  initial: servicesItems,
108
103
  list: services,
109
- defaultLabel: i18(Keyset.AllServices),
104
+ defaultLabel: i18n(Keyset.AllServices),
110
105
  }), virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption, renderFilter: renderFilter }))) : null,
111
106
  hasLikes ? (React.createElement("div", { className: b('filter-item', { 'width-auto': true }) },
112
107
  React.createElement(Button, { view: 'outlined', className: b('saved-only-button', { savedOnly }), size: "xl", onClick: handleSavedOnly },
113
108
  React.createElement(Icon, { data: Save, size: ICON_SIZE, className: b('icon', { savedOnly }) }),
114
- i18(Keyset.ActionSavedOnly)))) : null)));
109
+ i18n(Keyset.ActionSavedOnly)))) : null)));
115
110
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { TextInput } from '@gravity-ui/uikit';
3
- import { Keyset, i18 } from '../../../../i18n';
3
+ import { Keyset, i18n } from '../../../../i18n';
4
4
  import { block } from '../../../../utils/cn';
5
5
  import { CustomSelectOption, } from '../CustomSelectOption/CustomSelectOption';
6
6
  import { CustomSwitcher } from '../CustomSwitcher/CustomSwitcher';
@@ -9,5 +9,5 @@ const b = block('feed-controls');
9
9
  export const renderSwitcher = ({ initial, list, defaultLabel }) =>
10
10
  // eslint-disable-next-line react/display-name
11
11
  ({ onClick, ref, onKeyDown, open, renderClear }) => (React.createElement(CustomSwitcher, { initial: initial, defaultLabel: defaultLabel, list: list, controlRef: ref, onClick: onClick, onKeyDown: onKeyDown, renderClear: renderClear, open: open }));
12
- export const renderFilter = ({ value, onChange, onKeyDown }) => (React.createElement(TextInput, { controlProps: { size: 1 }, value: value, view: "clear", placeholder: i18(Keyset.Search), onUpdate: onChange, onKeyDown: onKeyDown, className: b('popup-filter') }));
12
+ export const renderFilter = ({ value, onChange, onKeyDown }) => (React.createElement(TextInput, { controlProps: { size: 1 }, value: value, view: "clear", placeholder: i18n(Keyset.Search), onUpdate: onChange, onKeyDown: onKeyDown, className: b('popup-filter') }));
13
13
  export const renderOption = (option) => (React.createElement(CustomSelectOption, { data: option }));
@@ -24,7 +24,7 @@ unpredictable css rules order in build */
24
24
  .bc-feed-custom-switcher__custom-switcher:focus:not(:focus-visible) {
25
25
  outline: 0;
26
26
  }
27
- .bc-feed-custom-switcher__custom-switcher + .yc-popup.yc-popup_open {
27
+ .bc-feed-custom-switcher__custom-switcher + .g-popup.g-popup_open {
28
28
  position: absolute !important;
29
29
  inset: auto !important;
30
30
  transform: translate3d(0, 4px, 0) !important;
@@ -1,18 +1,15 @@
1
1
  import { __rest } from "tslib";
2
2
  import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { useAnalytics } from '@gravity-ui/page-constructor';
4
- import { BlogMetrikaGoalIds } from '../../constants';
5
- /**
6
- * @deprecated Metrika will be deleted after launch of analyticsEvents
7
- */
8
- import metrika from '../../counters/metrika';
9
- import { MetrikaCounter } from '../../counters/utils';
4
+ import { DefaultGoalIds } from '../../constants';
5
+ import { AnalyticsCounter } from '../../counters/utils';
10
6
  import { DefaultEventNames } from '../../models/common';
11
7
  import { block } from '../../utils/cn';
12
8
  import { NavigationButton } from './components/NavigationButton';
13
9
  import { PaginatorItem } from './components/PaginatorItem';
14
10
  import { ArrowType } from './types';
15
11
  import { getPageConfigs, getPagesCount } from './utils';
12
+ import { prepareAnalyticsEvent } from '../../utils/common';
16
13
  import _ from 'lodash';
17
14
  import './Paginator.css';
18
15
  const b = block('paginator');
@@ -37,19 +34,19 @@ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
37
34
  const handleArrowClick = (type) => {
38
35
  let newPage = page;
39
36
  if (type === 'prev' && page > 1) {
40
- /**
41
- * @deprecated Metrika will be deleted after launch of analyticsEvents
42
- */
43
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.home);
44
- handleAnalyticsHome();
37
+ const event = prepareAnalyticsEvent({
38
+ name: DefaultGoalIds.home,
39
+ counter: AnalyticsCounter.CrossSite,
40
+ });
41
+ handleAnalyticsHome(event);
45
42
  newPage = 1;
46
43
  }
47
44
  else if (type === 'next' && page < pagesCount) {
48
- /**
49
- * @deprecated Metrika will be deleted after launch of analyticsEvents
50
- */
51
- handleAnalyticsNext();
52
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.next);
45
+ const event = prepareAnalyticsEvent({
46
+ name: DefaultGoalIds.next,
47
+ counter: AnalyticsCounter.CrossSite,
48
+ });
49
+ handleAnalyticsNext(event);
53
50
  newPage = page + 1;
54
51
  }
55
52
  if (newPage !== page) {
@@ -58,11 +55,11 @@ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
58
55
  };
59
56
  const handlePageClick = (index) => {
60
57
  if (index !== page && typeof index === 'number') {
61
- /**
62
- * @deprecated Metrika will be deleted after launch of analyticsEvents
63
- */
64
- metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.page, { page: index });
65
- handleAnalyticsPage(null, { page: String(index) });
58
+ const event = prepareAnalyticsEvent({
59
+ name: DefaultGoalIds.page,
60
+ counter: AnalyticsCounter.CrossSite,
61
+ });
62
+ handleAnalyticsPage(event, { page: String(index) });
66
63
  handlePageChange(index);
67
64
  }
68
65
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Keyset, i18 } from '../../../i18n';
2
+ import { Keyset, i18n } from '../../../i18n';
3
3
  import { block } from '../../../utils/cn';
4
4
  import { ArrowType } from '../types';
5
5
  import '../Paginator.css';
6
6
  const b = block('paginator');
7
- export const NavigationButton = ({ arrowType, disabled }) => disabled ? null : (React.createElement("div", { className: b('icon') }, arrowType === ArrowType.Prev ? i18(Keyset.ButtonBegin) : i18(Keyset.ButtonFarther)));
7
+ export const NavigationButton = ({ arrowType, disabled }) => disabled ? null : (React.createElement("div", { className: b('icon') }, arrowType === ArrowType.Prev ? i18n(Keyset.ButtonBegin) : i18n(Keyset.ButtonFarther)));
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { MetrikaGoal } from '@gravity-ui/page-constructor';
2
+ import { AnalyticsEventsProp } from '@gravity-ui/page-constructor';
3
3
  import { PostCardSize, PostCardTitleHeadingLevel, PostData } from '../../models/common';
4
4
  import './PostCard.css';
5
5
  type PostCardProps = {
@@ -8,10 +8,7 @@ type PostCardProps = {
8
8
  showTag?: boolean;
9
9
  size?: PostCardSize;
10
10
  titleHeadingLevel?: PostCardTitleHeadingLevel;
11
- /**
12
- * @deprecated Metrika will be deleted after launch of analyticsEvents
13
- */
14
- metrikaGoals?: MetrikaGoal;
11
+ analyticsEvents?: AnalyticsEventsProp;
15
12
  };
16
- export declare const PostCard: ({ post, metrikaGoals, fullWidth, size, showTag, titleHeadingLevel, }: PostCardProps) => React.JSX.Element;
13
+ export declare const PostCard: ({ post, fullWidth, size, showTag, titleHeadingLevel, analyticsEvents, }: PostCardProps) => React.JSX.Element;
17
14
  export {};
@@ -8,7 +8,7 @@ import { SuggestPostInfo } from '../PostInfo/SuggestPostInfo';
8
8
  import { useAriaAttributes } from '../../hooks/useAriaAttributes';
9
9
  import './PostCard.css';
10
10
  const b = block('post-card');
11
- export const PostCard = ({ post, metrikaGoals, fullWidth = false, size = PostCardSize.SMALL, showTag = false, titleHeadingLevel = PostCardTitleHeadingLevel.H3, }) => {
11
+ export const PostCard = ({ post, fullWidth = false, size = PostCardSize.SMALL, showTag = false, titleHeadingLevel = PostCardTitleHeadingLevel.H3, analyticsEvents, }) => {
12
12
  var _a;
13
13
  const { title: postTitle, htmlTitle, textTitle, blogPostId, id, date, readingTime, hasUserLike, likes, image, description, tags, url, } = post;
14
14
  const title = postTitle || textTitle || htmlTitle;
@@ -34,7 +34,7 @@ export const PostCard = ({ post, metrikaGoals, fullWidth = false, size = PostCar
34
34
  readingTime && readingTimeId,
35
35
  ],
36
36
  });
37
- return (React.createElement(CardBase, { url: url, metrikaGoals: metrikaGoals, className: b('card', { fullWidth }), extraProps: ariaAttributes },
37
+ return (React.createElement(CardBase, { url: url, analyticsEvents: analyticsEvents, className: b('card', { fullWidth }), extraProps: ariaAttributes },
38
38
  React.createElement(CardBase.Header, { image: image, className: b('header', { fullWidth }) },
39
39
  React.createElement("div", { className: b('image-container'), "data-qa": "blog-suggest-header" })),
40
40
  React.createElement(CardBase.Content, null,
@@ -1,19 +1,13 @@
1
1
  import React from 'react';
2
+ import { AnalyticsEventsProp } from '@gravity-ui/page-constructor';
2
3
  import { PostData, QAProps } from '../../models/common';
3
4
  import './PostInfo.css';
4
- export type BlogMetrikaGoals = {
5
- sharing?: string;
6
- save?: string;
7
- };
8
5
  type PostInfoProps = QAProps & {
9
6
  postId: PostData['id'];
10
7
  readingTime: PostData['readingTime'];
11
8
  date: PostData['date'];
12
9
  theme?: 'light' | 'dark';
13
- /**
14
- * @deprecated Metrika will be deleted after launch of analyticsEvents
15
- */
16
- metrikaGoals?: BlogMetrikaGoals;
10
+ analyticsEventsContainer?: Record<string, AnalyticsEventsProp>;
17
11
  };
18
12
  /**
19
13
  * Blog post info panel component
@@ -22,10 +16,10 @@ type PostInfoProps = QAProps & {
22
16
  * @param readingTime - post reading time
23
17
  * @param date - post create date
24
18
  * @param theme - theme name
25
- * @param metrikaGoals - metrika goals name
26
19
  * @param qa - test-attr
20
+ * @param analyticsEventsContainer - a map of records with a single or collection of objects detailing analytics events
27
21
  *
28
22
  * @returns jsx
29
23
  */
30
- export declare const PostInfo: ({ date, readingTime, postId, theme, metrikaGoals, qa, }: PostInfoProps) => React.JSX.Element;
24
+ export declare const PostInfo: ({ date, readingTime, postId, theme, qa, analyticsEventsContainer, }: PostInfoProps) => React.JSX.Element;
31
25
  export {};
@@ -15,17 +15,17 @@ const b = block('post-info');
15
15
  * @param readingTime - post reading time
16
16
  * @param date - post create date
17
17
  * @param theme - theme name
18
- * @param metrikaGoals - metrika goals name
19
18
  * @param qa - test-attr
19
+ * @param analyticsEventsContainer - a map of records with a single or collection of objects detailing analytics events
20
20
  *
21
21
  * @returns jsx
22
22
  */
23
- export const PostInfo = ({ date, readingTime, postId, theme = 'light', metrikaGoals, qa, }) => {
23
+ export const PostInfo = ({ date, readingTime, postId, theme = 'light', qa, analyticsEventsContainer, }) => {
24
24
  const { likes } = useContext(PostPageContext);
25
25
  const qaAttributes = getQaAttributes(qa, 'date', 'reading-time', 'save');
26
26
  return (React.createElement("div", { className: b('container', { theme }) },
27
27
  date && React.createElement(Date, { date: date, qa: qaAttributes.date }),
28
28
  readingTime && React.createElement(ReadingTime, { readingTime: readingTime, qa: qaAttributes.readingTime }),
29
- React.createElement(Sharing, { metrikaGoal: metrikaGoals === null || metrikaGoals === void 0 ? void 0 : metrikaGoals.sharing, theme: theme }),
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
+ React.createElement(Sharing, { theme: theme, analyticsEvents: analyticsEventsContainer === null || analyticsEventsContainer === void 0 ? void 0 : analyticsEventsContainer.sharing }),
30
+ likes && (React.createElement(Save, { postId: postId, title: likes.likesCount, hasUserLike: likes.hasUserLike, handleUserLike: likes.handleUserLike, analyticsEvents: analyticsEventsContainer === null || analyticsEventsContainer === void 0 ? void 0 : analyticsEventsContainer.save, theme: theme, qa: qaAttributes.save }))));
31
31
  };
@@ -5,8 +5,11 @@ import { block } from '../../utils/cn';
5
5
  import { Date } from './components/Date';
6
6
  import { ReadingTime } from './components/ReadingTime';
7
7
  import { Save } from './components/Save';
8
+ import { prepareAnalyticsEvent } from '../../utils/common';
9
+ import { DefaultGoalIds } from '../../constants';
8
10
  import './PostInfo.css';
9
11
  const b = block('post-info');
12
+ const saveEvents = prepareAnalyticsEvent({ name: DefaultGoalIds.saveSuggest });
10
13
  /**
11
14
  * Suggest blog card info component
12
15
  *
@@ -34,5 +37,5 @@ export const SuggestPostInfo = ({ postId, date, readingTime, likes, size = PostC
34
37
  React.createElement("div", { className: b('suggest-container') },
35
38
  date && React.createElement(Date, { date: date, size: size, id: dateId }),
36
39
  readingTime && (React.createElement(ReadingTime, { readingTime: readingTime, size: size, id: readingTimeId }))),
37
- likes && postId && (React.createElement(Save, { postId: postId, title: likesCount, hasUserLike: hasUserLike, handleUserLike: handleLike, size: size, qa: qa }))));
40
+ likes && postId && (React.createElement(Save, { postId: postId, title: likesCount, analyticsEvents: saveEvents, hasUserLike: hasUserLike, handleUserLike: handleLike, size: size, qa: qa }))));
38
41
  };