@gravity-ui/blog-constructor 5.14.0 → 5.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/README.md +2 -2
  2. package/build/cjs/blocks/Feed/Feed.js +1 -1
  3. package/build/cjs/blocks/Header/Header.js +4 -1
  4. package/build/cjs/blocks/Meta/Meta.js +4 -1
  5. package/build/cjs/components/FeedHeader/components/Controls/Controls.css +4 -0
  6. package/build/cjs/components/FeedHeader/components/Controls/Controls.js +4 -2
  7. package/build/cjs/components/Paginator/Paginator.d.ts +1 -1
  8. package/build/cjs/components/Paginator/Paginator.js +13 -2
  9. package/build/cjs/components/Paginator/components/PaginatorItem.d.ts +1 -1
  10. package/build/cjs/components/Paginator/components/PaginatorItem.js +9 -5
  11. package/build/cjs/components/Paginator/types.d.ts +4 -1
  12. package/build/cjs/components/Paginator/utils.d.ts +1 -1
  13. package/build/cjs/components/Paginator/utils.js +2 -1
  14. package/build/cjs/components/Posts/Posts.d.ts +3 -2
  15. package/build/cjs/components/Posts/Posts.js +2 -2
  16. package/build/cjs/contexts/SettingsContext.d.ts +1 -0
  17. package/build/cjs/utils/common.d.ts +3 -4
  18. package/build/cjs/utils/common.js +9 -14
  19. package/build/esm/blocks/Feed/Feed.js +1 -1
  20. package/build/esm/blocks/Header/Header.js +5 -2
  21. package/build/esm/blocks/Meta/Meta.js +5 -2
  22. package/build/esm/components/FeedHeader/components/Controls/Controls.css +4 -0
  23. package/build/esm/components/FeedHeader/components/Controls/Controls.js +4 -2
  24. package/build/esm/components/Paginator/Paginator.d.ts +1 -1
  25. package/build/esm/components/Paginator/Paginator.js +13 -2
  26. package/build/esm/components/Paginator/components/PaginatorItem.d.ts +1 -1
  27. package/build/esm/components/Paginator/components/PaginatorItem.js +10 -6
  28. package/build/esm/components/Paginator/types.d.ts +4 -1
  29. package/build/esm/components/Paginator/utils.d.ts +1 -1
  30. package/build/esm/components/Paginator/utils.js +2 -1
  31. package/build/esm/components/Posts/Posts.d.ts +3 -2
  32. package/build/esm/components/Posts/Posts.js +2 -2
  33. package/build/esm/contexts/SettingsContext.d.ts +1 -0
  34. package/build/esm/utils/common.d.ts +3 -4
  35. package/build/esm/utils/common.js +8 -12
  36. package/package.json +2 -2
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @gravity-ui/blog-constructor · [![npm package](https://img.shields.io/npm/v/@gravity-ui/blog-constructor)](https://www.npmjs.com/package/@gravity-ui/blog-constructor) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/blog-constructor/ci.yml?branch=main&label=CI)](https://github.com/gravity-ui/blog-constructor/actions/workflows/ci.yml?query=branch:main) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/blog-constructor/release.yml?branch=main&label=Release)](https://github.com/gravity-ui/blog-constructor/actions/workflows/release.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.yandexcloud.dev/blog-constructor/)
1
+ # @gravity-ui/blog-constructor · [![npm package](https://img.shields.io/npm/v/@gravity-ui/blog-constructor)](https://www.npmjs.com/package/@gravity-ui/blog-constructor) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/blog-constructor/ci.yml?branch=main&label=CI)](https://github.com/gravity-ui/blog-constructor/actions/workflows/ci.yml?query=branch:main) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/blog-constructor/release.yml?branch=main&label=Release)](https://github.com/gravity-ui/blog-constructor/actions/workflows/release.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/blog-constructor/)
2
2
 
3
3
  ## Install
4
4
 
@@ -10,7 +10,7 @@ npm install @gravity-ui/blog-constructor
10
10
 
11
11
  `Blog-constructor` is a library based on the [Page-constructor](https://github.com/gravity-ui/page-constructor) library for creating blog format web pages. Blog-constructor uses the [`custom`](https://github.com/gravity-ui/page-constructor#custom-blocks) prop from page-constructor to add the components needed for the blog.
12
12
 
13
- ### Documentation - [storybook](https://preview.yandexcloud.dev/blog-constructor/)
13
+ ### Documentation - [storybook](https://preview.gravity-ui.com/blog-constructor/)
14
14
 
15
15
  ### Getting started
16
16
 
@@ -164,6 +164,6 @@ const Feed = ({ image }) => {
164
164
  url: image,
165
165
  disableCompress: true,
166
166
  } }),
167
- errorLoad ? (react_1.default.createElement(PostsError_1.PostsError, { onButtonClick: handleOnErrorReload })) : (react_1.default.createElement(Posts_1.Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
167
+ errorLoad ? (react_1.default.createElement(PostsError_1.PostsError, { onButtonClick: handleOnErrorReload })) : (react_1.default.createElement(Posts_1.Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, queryParams: queryParams, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
168
168
  };
169
169
  exports.Feed = Feed;
@@ -11,6 +11,7 @@ const LocaleContext_1 = require("../../contexts/LocaleContext");
11
11
  const PostPageContext_1 = require("../../contexts/PostPageContext");
12
12
  const paddings_1 = require("../../models/paddings");
13
13
  const common_1 = require("../../utils/common");
14
+ const SettingsContext_1 = require("../../contexts/SettingsContext");
14
15
  /**
15
16
  * @deprecated Metrika will be deleted after launch of analyticsEvents
16
17
  */
@@ -28,8 +29,10 @@ const Header = (props) => {
28
29
  const { theme, paddingTop, paddingBottom } = props;
29
30
  const { post } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
30
31
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
32
+ const { getBlogPath = common_1.getBlogPath } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
33
+ const blogPath = getBlogPath(locale.pathPrefix || '');
31
34
  const { description, title, id, date, readingTime, tags } = post;
32
- const breadcrumbs = (0, common_1.getBreadcrumbs)({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
35
+ const breadcrumbs = (0, common_1.getBreadcrumbs)({ tags, blogPath });
33
36
  if (theme === 'dark' && breadcrumbs) {
34
37
  breadcrumbs.theme = 'dark';
35
38
  }
@@ -8,6 +8,7 @@ const PostInfo_1 = require("../../components/PostInfo/PostInfo");
8
8
  const Wrapper_1 = require("../../components/Wrapper/Wrapper");
9
9
  const constants_1 = require("../../constants");
10
10
  const LocaleContext_1 = require("../../contexts/LocaleContext");
11
+ const SettingsContext_1 = require("../../contexts/SettingsContext");
11
12
  const PostPageContext_1 = require("../../contexts/PostPageContext");
12
13
  const paddings_1 = require("../../models/paddings");
13
14
  const cn_1 = require("../../utils/cn");
@@ -31,8 +32,10 @@ const Meta = (props) => {
31
32
  const { post } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
32
33
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
33
34
  const qaAttributes = (0, common_1.getQaAttributes)(qa, 'post-info');
35
+ const { getBlogPath = common_1.getBlogPath } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
36
+ const blogPath = getBlogPath(locale.pathPrefix || '');
34
37
  const { title, id, date, readingTime, tags } = post;
35
- const breadcrumbs = (0, common_1.getBreadcrumbs)({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
38
+ const breadcrumbs = (0, common_1.getBreadcrumbs)({ tags, blogPath });
36
39
  breadcrumbs.metrikaGoals = breadcrumbsGoals;
37
40
  return (react_1.default.createElement(Wrapper_1.Wrapper, { paddings: {
38
41
  [paddings_1.PaddingsDirections.top]: paddingTop,
@@ -44,6 +44,10 @@ unpredictable css rules order in build */
44
44
  border-radius: 8px;
45
45
  }
46
46
 
47
+ .bc-feed-controls__popup_isMobile.bc-feed-controls__popup_isMobile {
48
+ max-height: inherit;
49
+ }
50
+
47
51
  .bc-feed-controls__popup-filter {
48
52
  font-size: var(--g-text-body-2-font-size);
49
53
  line-height: var(--g-text-body-2-line-height);
@@ -10,6 +10,7 @@ const uikit_1 = require("@gravity-ui/uikit");
10
10
  */
11
11
  const constants_1 = require("../../../../constants");
12
12
  const LikesContext_1 = require("../../../../contexts/LikesContext");
13
+ const MobileContext_1 = require("../../../../contexts/MobileContext");
13
14
  const metrika_1 = tslib_1.__importDefault(require("../../../../counters/metrika"));
14
15
  const utils_1 = require("../../../../counters/utils");
15
16
  const i18n_1 = require("../../../../i18n");
@@ -30,6 +31,7 @@ const Controls = ({ handleLoadData, tags = [], services = [], queryParams, }) =>
30
31
  const { savedOnly: savedOnlyInitial, search: searchInitial, tags: tagInitial, services: servicesInitial, } = queryParams || {};
31
32
  const [savedOnly, setSavedOnly] = (0, react_1.useState)(savedOnlyInitial === 'true');
32
33
  const [search, setSearch] = (0, react_1.useState)(searchInitial);
34
+ const isMobile = (0, react_1.useContext)(MobileContext_1.MobileContext);
33
35
  const handleSavedOnly = () => {
34
36
  handleAnalyticsSaveOnly();
35
37
  setSavedOnly(!savedOnly);
@@ -98,13 +100,13 @@ const Controls = ({ handleLoadData, tags = [], services = [], queryParams, }) =>
98
100
  react_1.default.createElement("div", { className: b('filter-item') },
99
101
  react_1.default.createElement(Search_1.Search, { className: b('search'), placeholder: (0, i18n_1.i18)(i18n_1.Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
100
102
  react_1.default.createElement("div", { className: b('filter-item') },
101
- react_1.default.createElement(uikit_1.Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: (0, i18n_1.i18)(i18n_1.Keyset.AllTags), popupClassName: b('popup'), renderControl: (0, customRenders_1.renderSwitcher)({
103
+ react_1.default.createElement(uikit_1.Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: (0, i18n_1.i18)(i18n_1.Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: (0, customRenders_1.renderSwitcher)({
102
104
  initial: [tagInitial],
103
105
  list: tagsItems,
104
106
  defaultLabel: (0, i18n_1.i18)(i18n_1.Keyset.AllTags),
105
107
  }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: customRenders_1.renderOption })),
106
108
  services.length > 0 ? (react_1.default.createElement("div", { className: b('filter-item') },
107
- react_1.default.createElement(uikit_1.Select, { className: b('select'), size: "xl", multiple: true, filterable: true, hasClear: true, disablePortal: true, options: services, defaultValue: servicesItems, popupClassName: b('popup'), onUpdate: handleServicesSelect, placeholder: (0, i18n_1.i18)(i18n_1.Keyset.AllServices), renderControl: (0, customRenders_1.renderSwitcher)({
109
+ react_1.default.createElement(uikit_1.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: (0, i18n_1.i18)(i18n_1.Keyset.AllServices), renderControl: (0, customRenders_1.renderSwitcher)({
108
110
  initial: servicesItems,
109
111
  list: services,
110
112
  defaultLabel: (0, i18n_1.i18)(i18n_1.Keyset.AllServices),
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import { PaginatorProps } from './types';
3
- export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons, }: PaginatorProps) => React.JSX.Element | null;
3
+ export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, queryParams, pageCountForShowSupportButtons, }: PaginatorProps) => React.JSX.Element | null;
@@ -16,10 +16,14 @@ const NavigationButton_1 = require("./components/NavigationButton");
16
16
  const PaginatorItem_1 = require("./components/PaginatorItem");
17
17
  const types_1 = require("./types");
18
18
  const utils_2 = require("./utils");
19
+ const lodash_1 = tslib_1.__importDefault(require("lodash"));
19
20
  const b = (0, cn_1.block)('paginator');
20
21
  const DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS = 6;
21
- const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
22
+ const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, queryParams, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
22
23
  const [pagesCount, setPagesCount] = (0, react_1.useState)((0, utils_2.getPagesCount)({ itemsPerPage, totalItems, maxPages }));
24
+ const nonPagedQuery = (0, react_1.useMemo)(() => {
25
+ return lodash_1.default.omit(queryParams, ['page']);
26
+ }, [queryParams]);
23
27
  (0, react_1.useEffect)(() => {
24
28
  const count = (0, utils_2.getPagesCount)({ itemsPerPage, totalItems, maxPages });
25
29
  setPagesCount(count);
@@ -64,11 +68,17 @@ const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPage
64
68
  handlePageChange(index);
65
69
  }
66
70
  };
67
- const paginatorItems = (0, utils_2.getPageConfigs)({ page, pagesCount, handlePageClick });
71
+ const paginatorItems = (0, utils_2.getPageConfigs)({
72
+ page,
73
+ pagesCount,
74
+ queryParams: nonPagedQuery,
75
+ handlePageClick,
76
+ });
68
77
  if (page > 1 && isShowSupportButtons) {
69
78
  paginatorItems.unshift({
70
79
  key: types_1.ArrowType.Prev,
71
80
  dataKey: types_1.ArrowType.Prev,
81
+ queryParams: nonPagedQuery,
72
82
  mods: { type: types_1.ArrowType.Prev },
73
83
  onClick: handleArrowClick,
74
84
  index: 0,
@@ -78,6 +88,7 @@ const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPage
78
88
  if (page < pagesCount && isShowSupportButtons) {
79
89
  paginatorItems.push({
80
90
  key: types_1.ArrowType.Next,
91
+ queryParams: nonPagedQuery,
81
92
  dataKey: types_1.ArrowType.Next,
82
93
  mods: { type: types_1.ArrowType.Next },
83
94
  index: page + 1,
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import { PaginatorItemProps } from '../types';
3
- export declare const PaginatorItem: ({ dataKey, mods, content, onClick, loading, index, }: PaginatorItemProps) => React.JSX.Element;
3
+ export declare const PaginatorItem: ({ dataKey, mods, content, queryParams, onClick, loading, index, }: PaginatorItemProps) => React.JSX.Element;
@@ -9,13 +9,17 @@ const SettingsContext_1 = require("../../../contexts/SettingsContext");
9
9
  const cn_1 = require("../../../utils/cn");
10
10
  const common_1 = require("../../../utils/common");
11
11
  const b = (0, cn_1.block)('paginator');
12
- const PaginatorItem = ({ dataKey, mods, content, onClick, loading = false, index, }) => {
12
+ const PaginatorItem = ({ dataKey, mods, content, queryParams, onClick, loading = false, index, }) => {
13
13
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
14
- const { addNavigationLinkForPages } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
15
- const urlPath = (0, common_1.getBlogPath)((locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '');
14
+ const { addNavigationLinkForPages, getBlogPath = common_1.getBlogPath } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
15
+ const urlPath = getBlogPath((locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '');
16
16
  const itemKey = Number(dataKey) > 0 ? Number(dataKey) : dataKey;
17
- const navTag = index > 1 ? `?page=${index}` : '';
18
- const navigationLink = `${urlPath || ''}${navTag}`;
17
+ const navigationLink = (0, react_1.useMemo)(() => {
18
+ const queryString = Object.entries(Object.assign(Object.assign({}, (index > 1 ? { page: index } : undefined)), queryParams))
19
+ .map(([param, value]) => `${param}=${value}`)
20
+ .join('&');
21
+ return queryString ? `${urlPath}?${queryString}` : urlPath;
22
+ }, [queryParams, index, urlPath]);
19
23
  const renderButton = (react_1.default.createElement(uikit_1.Button, { view: "flat", size: "xl", className: b('item', mods), onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(itemKey), loading: loading && Boolean(mods.active) }, content));
20
24
  return (react_1.default.createElement(react_1.Fragment, null, addNavigationLinkForPages ? (react_1.default.createElement("a", { href: navigationLink, className: b('link'), onClick: (event) => event.preventDefault() }, renderButton)) : (react_1.default.createElement(react_1.Fragment, null, renderButton))));
21
25
  };
@@ -1,11 +1,12 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { NoStrictEntityMods } from '@bem-react/classname';
3
- import type { ClassNameProps } from '../../models/common';
3
+ import type { ClassNameProps, Query } from '../../models/common';
4
4
  export interface PaginatorItemProps {
5
5
  key: string | ArrowType;
6
6
  dataKey: string | ArrowType;
7
7
  mods: NoStrictEntityMods;
8
8
  content: ReactNode;
9
+ queryParams: Query;
9
10
  onClick?: (key: number | ArrowType) => void;
10
11
  loading?: boolean;
11
12
  index: number;
@@ -17,6 +18,7 @@ export type PaginatorProps = {
17
18
  maxPages: number;
18
19
  onPageChange: (page: number) => void;
19
20
  pageCountForShowSupportButtons?: number;
21
+ queryParams: Query;
20
22
  } & ClassNameProps;
21
23
  export declare enum ArrowType {
22
24
  Prev = "prev",
@@ -25,5 +27,6 @@ export declare enum ArrowType {
25
27
  export type GetPageConfigParams = {
26
28
  page: number;
27
29
  pagesCount: number;
30
+ queryParams: Query;
28
31
  handlePageClick: (key: number | ArrowType) => void;
29
32
  };
@@ -1,3 +1,3 @@
1
1
  import { GetPageConfigParams, PaginatorItemProps, PaginatorProps } from './types';
2
- export declare const getPageConfigs: ({ page, pagesCount, handlePageClick }: GetPageConfigParams) => PaginatorItemProps[];
2
+ export declare const getPageConfigs: ({ page, queryParams, pagesCount, handlePageClick, }: GetPageConfigParams) => PaginatorItemProps[];
3
3
  export declare const getPagesCount: (props: Pick<PaginatorProps, 'totalItems' | 'itemsPerPage' | 'maxPages'>) => number;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPagesCount = exports.getPageConfigs = void 0;
4
4
  const MAX_VISIBLE_PAGES = 5;
5
- const getPageConfigs = ({ page, pagesCount, handlePageClick }) => {
5
+ const getPageConfigs = ({ page, queryParams, pagesCount, handlePageClick, }) => {
6
6
  const paginatorItems = [];
7
7
  // it is calculating the middle of visible pages below
8
8
  const pageOffset = (MAX_VISIBLE_PAGES - 1) / 2;
@@ -19,6 +19,7 @@ const getPageConfigs = ({ page, pagesCount, handlePageClick }) => {
19
19
  dataKey: String(i),
20
20
  index: i,
21
21
  mods: { type: 'page', active: page === i },
22
+ queryParams,
22
23
  onClick: handlePageClick,
23
24
  content: i,
24
25
  });
@@ -1,5 +1,5 @@
1
1
  import React, { MouseEvent } from 'react';
2
- import { PostData } from '../../models/common';
2
+ import { PostData, Query } from '../../models/common';
3
3
  type PostCardProps = {
4
4
  containerId: string;
5
5
  currentPage: number;
@@ -13,6 +13,7 @@ type PostCardProps = {
13
13
  postsOnPage?: PostData[];
14
14
  pinnedPostOnPage?: PostData;
15
15
  pageCountForShowSupportButtons?: number;
16
+ queryParams: Query;
16
17
  };
17
- export declare const Posts: ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, }: PostCardProps) => React.JSX.Element;
18
+ export declare const Posts: ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, queryParams, }: PostCardProps) => React.JSX.Element;
18
19
  export {};
@@ -12,7 +12,7 @@ const Paginator_1 = require("../Paginator/Paginator");
12
12
  const PostCard_1 = require("../PostCard/PostCard");
13
13
  const PostsEmpty_1 = require("../PostsEmpty/PostsEmpty");
14
14
  const b = (0, cn_1.block)('posts');
15
- const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, }) => (react_1.default.createElement("div", { className: b() },
15
+ const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, queryParams, }) => (react_1.default.createElement("div", { className: b() },
16
16
  isFetching && react_1.default.createElement("div", { className: b('loaderContainer') }),
17
17
  react_1.default.createElement("div", { id: containerId, className: b('cards-container', { isLoading: isFetching }) },
18
18
  pinnedPostOnPage && currentPage === 1 && (react_1.default.createElement("div", { className: b('pinned-container') },
@@ -30,5 +30,5 @@ const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShow
30
30
  react_1.default.createElement("div", null, (0, i18n_1.i18)(i18n_1.Keyset.ErrorTitle)),
31
31
  react_1.default.createElement("div", null, (0, i18n_1.i18)(i18n_1.Keyset.PostLoadError)))),
32
32
  Boolean(currentPage && postCountOnPage) && (react_1.default.createElement("div", { className: b('paginator') },
33
- react_1.default.createElement(Paginator_1.Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery, maxPages: Infinity, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))))));
33
+ react_1.default.createElement(Paginator_1.Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery, maxPages: Infinity, pageCountForShowSupportButtons: pageCountForShowSupportButtons, queryParams: queryParams }))))));
34
34
  exports.Posts = Posts;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  export interface SettingsContextProps {
3
3
  addNavigationLinkForPages?: boolean;
4
+ getBlogPath?: (pathPrefix: string) => string;
4
5
  }
5
6
  export declare const SettingsContext: React.Context<SettingsContextProps>;
@@ -13,9 +13,8 @@ export declare function getAbsolutePath(router: RouterContextProps, url?: string
13
13
  export declare const getPageSearchParams: (query?: Query) => URLSearchParams;
14
14
  export declare const scrollToHash: (hash: string, browser?: string) => void;
15
15
  type CloudListTagStub = {};
16
- export declare const getTags: ((tags: Tag[], prefix?: string) => CloudListTagStub[]) & import("lodash").MemoizedFunction;
16
+ export declare const getTags: ((tags: Tag[], blogPath: string) => CloudListTagStub[]) & import("lodash").MemoizedFunction;
17
17
  export declare const postLikeStatus: import("lodash").DebouncedFunc<(postId: number, hasUserLike: boolean) => void>;
18
- export declare const getTagFilterUrl: (tagId: string | number, prefix: string) => string;
19
18
  export declare const updateContentSizes: ({ size, colSizes, theme, ...contentData }: ContentBlockProps) => {
20
19
  size: import("@gravity-ui/page-constructor").ContentSize;
21
20
  colSizes: {
@@ -35,10 +34,10 @@ export declare const updateContentSizes: ({ size, colSizes, theme, ...contentDat
35
34
  };
36
35
  type GetBreadcrumbsProps = {
37
36
  tags?: Tag[];
38
- pathPrefix?: string;
37
+ blogPath: string;
39
38
  };
40
39
  export declare const getBlogPath: (pathPrefix: string) => string;
41
- export declare const getBreadcrumbs: ({ tags, pathPrefix }: GetBreadcrumbsProps) => HeaderBreadCrumbsProps;
40
+ export declare const getBreadcrumbs: ({ tags, blogPath }: GetBreadcrumbsProps) => HeaderBreadCrumbsProps;
42
41
  export declare const isMetrikaExist: (goal: NewMetrikaGoal, existGoals: NewMetrikaGoal[]) => boolean;
43
42
  export declare const getBlogElementMetrika: (blogCustomGoal: NewMetrikaGoal, existingGoals?: MetrikaGoal) => string | string[] | NewMetrikaGoal[];
44
43
  export declare const getFeedQueryParams: (queryString: Query, pageNumber?: number) => GetPostsRequest;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getQaAttributes = exports.scrollOnPageChange = exports.getFeedQueryParams = exports.getBlogElementMetrika = exports.isMetrikaExist = exports.getBreadcrumbs = exports.getBlogPath = exports.updateContentSizes = exports.getTagFilterUrl = exports.postLikeStatus = exports.getTags = exports.scrollToHash = exports.getPageSearchParams = exports.getAbsolutePath = void 0;
3
+ exports.getQaAttributes = exports.scrollOnPageChange = exports.getFeedQueryParams = exports.getBlogElementMetrika = exports.isMetrikaExist = exports.getBreadcrumbs = exports.getBlogPath = exports.updateContentSizes = exports.postLikeStatus = exports.getTags = exports.scrollToHash = exports.getPageSearchParams = exports.getAbsolutePath = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const url_1 = require("url");
6
6
  const page_constructor_1 = require("@gravity-ui/page-constructor");
@@ -38,43 +38,38 @@ const scrollToHash = (hash, browser) => {
38
38
  setTimeout(() => element.scrollIntoView({ behavior: browser === 'Yandex' ? 'auto' : 'smooth' }), 0);
39
39
  };
40
40
  exports.scrollToHash = scrollToHash;
41
- exports.getTags = (0, memoize_1.default)((tags, prefix) => {
41
+ exports.getTags = (0, memoize_1.default)((tags, blogPath) => {
42
42
  return tags.map((_a) => {
43
43
  var { slug } = _a, tag = tslib_1.__rest(_a, ["slug"]);
44
44
  const queryParams = new URLSearchParams();
45
45
  queryParams.set('tags', slug);
46
- return Object.assign(Object.assign({}, tag), { id: slug, url: `${prefix}blog?${queryParams}` });
46
+ return Object.assign(Object.assign({}, tag), { id: slug, url: `${blogPath}?${queryParams}` });
47
47
  });
48
48
  });
49
49
  const stub = (postId) => postId;
50
50
  exports.postLikeStatus = (0, debounce_1.default)((postId, hasUserLike) => {
51
51
  (hasUserLike ? stub : stub)(postId);
52
52
  }, 300);
53
- const getTagFilterUrl = (tagId, prefix) => {
54
- return `${prefix}blog?tags=` + tagId;
55
- };
56
- exports.getTagFilterUrl = getTagFilterUrl;
57
53
  const updateContentSizes = (_a) => {
58
54
  var { size, colSizes, theme } = _a, contentData = tslib_1.__rest(_a, ["size", "colSizes", "theme"]);
59
55
  return (Object.assign(Object.assign({}, contentData), { size: size || constants_1.CONTENT_DEFAULT_SIZE, colSizes: colSizes || constants_1.CONTENT_DEFAULT_COL_SIZES, theme: theme || constants_1.CONTENT_DEFAULT_THEME }));
60
56
  };
61
57
  exports.updateContentSizes = updateContentSizes;
62
58
  const getBlogPath = (pathPrefix) => {
63
- const prefix = pathPrefix ? `/${pathPrefix}/` : '/';
64
- return `${prefix}blog`;
59
+ const prefix = pathPrefix ? `/${pathPrefix}` : '';
60
+ return `${prefix}/blog`;
65
61
  };
66
62
  exports.getBlogPath = getBlogPath;
67
- const getBreadcrumbs = ({ tags, pathPrefix }) => {
68
- const prefix = pathPrefix ? `/${pathPrefix}/` : '/';
63
+ const getBreadcrumbs = ({ tags, blogPath }) => {
69
64
  const breadcrumbs = {
70
- items: [{ text: (0, i18n_1.i18)(i18n_1.Keyset.TitleBreadcrumbs), url: `${prefix}blog` }],
65
+ items: [{ text: (0, i18n_1.i18)(i18n_1.Keyset.TitleBreadcrumbs), url: blogPath }],
71
66
  theme: 'light',
72
67
  };
73
68
  if (tags === null || tags === void 0 ? void 0 : tags.length) {
74
- const localizedTags = (0, exports.getTags)(tags, prefix);
69
+ const localizedTags = (0, exports.getTags)(tags, blogPath);
75
70
  const tag = localizedTags[0];
76
71
  // @ts-ignore todo fix
77
- breadcrumbs.items.push({ text: tag.name, url: (0, exports.getTagFilterUrl)(tag.id, prefix) });
72
+ breadcrumbs.items.push({ text: tag.name, url: tag.url });
78
73
  }
79
74
  return breadcrumbs;
80
75
  };
@@ -160,5 +160,5 @@ export const Feed = ({ image }) => {
160
160
  url: image,
161
161
  disableCompress: true,
162
162
  } }),
163
- errorLoad ? (React.createElement(PostsError, { onButtonClick: handleOnErrorReload })) : (React.createElement(Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
163
+ errorLoad ? (React.createElement(PostsError, { onButtonClick: handleOnErrorReload })) : (React.createElement(Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, queryParams: queryParams, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
164
164
  };
@@ -6,7 +6,8 @@ import { BlogMetrikaGoalIds } 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 } from '../../utils/common';
9
+ import { getBreadcrumbs, getBlogPath as getDefaultBlogPath } from '../../utils/common';
10
+ import { SettingsContext } from '../../contexts/SettingsContext';
10
11
  /**
11
12
  * @deprecated Metrika will be deleted after launch of analyticsEvents
12
13
  */
@@ -24,8 +25,10 @@ export const Header = (props) => {
24
25
  const { theme, paddingTop, paddingBottom } = props;
25
26
  const { post } = useContext(PostPageContext);
26
27
  const { locale } = useContext(LocaleContext);
28
+ const { getBlogPath = getDefaultBlogPath } = useContext(SettingsContext);
29
+ const blogPath = getBlogPath(locale.pathPrefix || '');
27
30
  const { description, title, id, date, readingTime, tags } = post;
28
- const breadcrumbs = getBreadcrumbs({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
31
+ const breadcrumbs = getBreadcrumbs({ tags, blogPath });
29
32
  if (theme === 'dark' && breadcrumbs) {
30
33
  breadcrumbs.theme = 'dark';
31
34
  }
@@ -4,10 +4,11 @@ import { PostInfo } from '../../components/PostInfo/PostInfo';
4
4
  import { Wrapper } from '../../components/Wrapper/Wrapper';
5
5
  import { BlogMetrikaGoalIds } from '../../constants';
6
6
  import { LocaleContext } from '../../contexts/LocaleContext';
7
+ import { SettingsContext } from '../../contexts/SettingsContext';
7
8
  import { PostPageContext } from '../../contexts/PostPageContext';
8
9
  import { PaddingsDirections } from '../../models/paddings';
9
10
  import { block } from '../../utils/cn';
10
- import { getBreadcrumbs, getQaAttributes } from '../../utils/common';
11
+ import { getBreadcrumbs, getBlogPath as getDefaultBlogPath, getQaAttributes, } from '../../utils/common';
11
12
  import './Meta.css';
12
13
  const b = block('meta');
13
14
  /**
@@ -28,8 +29,10 @@ export const Meta = (props) => {
28
29
  const { post } = useContext(PostPageContext);
29
30
  const { locale } = useContext(LocaleContext);
30
31
  const qaAttributes = getQaAttributes(qa, 'post-info');
32
+ const { getBlogPath = getDefaultBlogPath } = useContext(SettingsContext);
33
+ const blogPath = getBlogPath(locale.pathPrefix || '');
31
34
  const { title, id, date, readingTime, tags } = post;
32
- const breadcrumbs = getBreadcrumbs({ tags, pathPrefix: (locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '' });
35
+ const breadcrumbs = getBreadcrumbs({ tags, blogPath });
33
36
  breadcrumbs.metrikaGoals = breadcrumbsGoals;
34
37
  return (React.createElement(Wrapper, { paddings: {
35
38
  [PaddingsDirections.top]: paddingTop,
@@ -44,6 +44,10 @@ unpredictable css rules order in build */
44
44
  border-radius: 8px;
45
45
  }
46
46
 
47
+ .bc-feed-controls__popup_isMobile.bc-feed-controls__popup_isMobile {
48
+ max-height: inherit;
49
+ }
50
+
47
51
  .bc-feed-controls__popup-filter {
48
52
  font-size: var(--g-text-body-2-font-size);
49
53
  line-height: var(--g-text-body-2-line-height);
@@ -6,6 +6,7 @@ import { Button, Icon, Select } from '@gravity-ui/uikit';
6
6
  */
7
7
  import { BlogMetrikaGoalIds } from '../../../../constants';
8
8
  import { LikesContext } from '../../../../contexts/LikesContext';
9
+ import { MobileContext } from '../../../../contexts/MobileContext';
9
10
  import metrika from '../../../../counters/metrika';
10
11
  import { MetrikaCounter } from '../../../../counters/utils';
11
12
  import { Keyset, i18 } from '../../../../i18n';
@@ -27,6 +28,7 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
27
28
  const { savedOnly: savedOnlyInitial, search: searchInitial, tags: tagInitial, services: servicesInitial, } = queryParams || {};
28
29
  const [savedOnly, setSavedOnly] = useState(savedOnlyInitial === 'true');
29
30
  const [search, setSearch] = useState(searchInitial);
31
+ const isMobile = useContext(MobileContext);
30
32
  const handleSavedOnly = () => {
31
33
  handleAnalyticsSaveOnly();
32
34
  setSavedOnly(!savedOnly);
@@ -95,13 +97,13 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
95
97
  React.createElement("div", { className: b('filter-item') },
96
98
  React.createElement(Search, { className: b('search'), placeholder: i18(Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
97
99
  React.createElement("div", { className: b('filter-item') },
98
- React.createElement(Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: i18(Keyset.AllTags), popupClassName: b('popup'), renderControl: renderSwitcher({
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({
99
101
  initial: [tagInitial],
100
102
  list: tagsItems,
101
103
  defaultLabel: i18(Keyset.AllTags),
102
104
  }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption })),
103
105
  services.length > 0 ? (React.createElement("div", { className: b('filter-item') },
104
- React.createElement(Select, { className: b('select'), size: "xl", multiple: true, filterable: true, hasClear: true, disablePortal: true, options: services, defaultValue: servicesItems, popupClassName: b('popup'), onUpdate: handleServicesSelect, placeholder: i18(Keyset.AllServices), renderControl: renderSwitcher({
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({
105
107
  initial: servicesItems,
106
108
  list: services,
107
109
  defaultLabel: i18(Keyset.AllServices),
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { PaginatorProps } from './types';
3
3
  import './Paginator.css';
4
- export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons, }: PaginatorProps) => React.JSX.Element | null;
4
+ export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, queryParams, pageCountForShowSupportButtons, }: PaginatorProps) => React.JSX.Element | null;
@@ -13,11 +13,15 @@ import { NavigationButton } from './components/NavigationButton';
13
13
  import { PaginatorItem } from './components/PaginatorItem';
14
14
  import { ArrowType } from './types';
15
15
  import { getPageConfigs, getPagesCount } from './utils';
16
+ import _ from 'lodash';
16
17
  import './Paginator.css';
17
18
  const b = block('paginator');
18
19
  const DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS = 6;
19
- export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
20
+ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, queryParams, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
20
21
  const [pagesCount, setPagesCount] = useState(getPagesCount({ itemsPerPage, totalItems, maxPages }));
22
+ const nonPagedQuery = useMemo(() => {
23
+ return _.omit(queryParams, ['page']);
24
+ }, [queryParams]);
21
25
  useEffect(() => {
22
26
  const count = getPagesCount({ itemsPerPage, totalItems, maxPages });
23
27
  setPagesCount(count);
@@ -62,11 +66,17 @@ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
62
66
  handlePageChange(index);
63
67
  }
64
68
  };
65
- const paginatorItems = getPageConfigs({ page, pagesCount, handlePageClick });
69
+ const paginatorItems = getPageConfigs({
70
+ page,
71
+ pagesCount,
72
+ queryParams: nonPagedQuery,
73
+ handlePageClick,
74
+ });
66
75
  if (page > 1 && isShowSupportButtons) {
67
76
  paginatorItems.unshift({
68
77
  key: ArrowType.Prev,
69
78
  dataKey: ArrowType.Prev,
79
+ queryParams: nonPagedQuery,
70
80
  mods: { type: ArrowType.Prev },
71
81
  onClick: handleArrowClick,
72
82
  index: 0,
@@ -76,6 +86,7 @@ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
76
86
  if (page < pagesCount && isShowSupportButtons) {
77
87
  paginatorItems.push({
78
88
  key: ArrowType.Next,
89
+ queryParams: nonPagedQuery,
79
90
  dataKey: ArrowType.Next,
80
91
  mods: { type: ArrowType.Next },
81
92
  index: page + 1,
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { PaginatorItemProps } from '../types';
3
3
  import '../Paginator.css';
4
- export declare const PaginatorItem: ({ dataKey, mods, content, onClick, loading, index, }: PaginatorItemProps) => React.JSX.Element;
4
+ export declare const PaginatorItem: ({ dataKey, mods, content, queryParams, onClick, loading, index, }: PaginatorItemProps) => React.JSX.Element;
@@ -1,18 +1,22 @@
1
- import React, { Fragment, useContext } from 'react';
1
+ import React, { Fragment, useContext, useMemo } from 'react';
2
2
  import { Button } from '@gravity-ui/uikit';
3
3
  import { LocaleContext } from '../../../contexts/LocaleContext';
4
4
  import { SettingsContext } from '../../../contexts/SettingsContext';
5
5
  import { block } from '../../../utils/cn';
6
- import { getBlogPath } from '../../../utils/common';
6
+ import { getBlogPath as getDefaultBlogPath } from '../../../utils/common';
7
7
  import '../Paginator.css';
8
8
  const b = block('paginator');
9
- export const PaginatorItem = ({ dataKey, mods, content, onClick, loading = false, index, }) => {
9
+ export const PaginatorItem = ({ dataKey, mods, content, queryParams, onClick, loading = false, index, }) => {
10
10
  const { locale } = useContext(LocaleContext);
11
- const { addNavigationLinkForPages } = useContext(SettingsContext);
11
+ const { addNavigationLinkForPages, getBlogPath = getDefaultBlogPath } = useContext(SettingsContext);
12
12
  const urlPath = getBlogPath((locale === null || locale === void 0 ? void 0 : locale.pathPrefix) || '');
13
13
  const itemKey = Number(dataKey) > 0 ? Number(dataKey) : dataKey;
14
- const navTag = index > 1 ? `?page=${index}` : '';
15
- const navigationLink = `${urlPath || ''}${navTag}`;
14
+ const navigationLink = useMemo(() => {
15
+ const queryString = Object.entries(Object.assign(Object.assign({}, (index > 1 ? { page: index } : undefined)), queryParams))
16
+ .map(([param, value]) => `${param}=${value}`)
17
+ .join('&');
18
+ return queryString ? `${urlPath}?${queryString}` : urlPath;
19
+ }, [queryParams, index, urlPath]);
16
20
  const renderButton = (React.createElement(Button, { view: "flat", size: "xl", className: b('item', mods), onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(itemKey), loading: loading && Boolean(mods.active) }, content));
17
21
  return (React.createElement(Fragment, null, addNavigationLinkForPages ? (React.createElement("a", { href: navigationLink, className: b('link'), onClick: (event) => event.preventDefault() }, renderButton)) : (React.createElement(Fragment, null, renderButton))));
18
22
  };
@@ -1,11 +1,12 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { NoStrictEntityMods } from '@bem-react/classname';
3
- import type { ClassNameProps } from '../../models/common';
3
+ import type { ClassNameProps, Query } from '../../models/common';
4
4
  export interface PaginatorItemProps {
5
5
  key: string | ArrowType;
6
6
  dataKey: string | ArrowType;
7
7
  mods: NoStrictEntityMods;
8
8
  content: ReactNode;
9
+ queryParams: Query;
9
10
  onClick?: (key: number | ArrowType) => void;
10
11
  loading?: boolean;
11
12
  index: number;
@@ -17,6 +18,7 @@ export type PaginatorProps = {
17
18
  maxPages: number;
18
19
  onPageChange: (page: number) => void;
19
20
  pageCountForShowSupportButtons?: number;
21
+ queryParams: Query;
20
22
  } & ClassNameProps;
21
23
  export declare enum ArrowType {
22
24
  Prev = "prev",
@@ -25,5 +27,6 @@ export declare enum ArrowType {
25
27
  export type GetPageConfigParams = {
26
28
  page: number;
27
29
  pagesCount: number;
30
+ queryParams: Query;
28
31
  handlePageClick: (key: number | ArrowType) => void;
29
32
  };
@@ -1,3 +1,3 @@
1
1
  import { GetPageConfigParams, PaginatorItemProps, PaginatorProps } from './types';
2
- export declare const getPageConfigs: ({ page, pagesCount, handlePageClick }: GetPageConfigParams) => PaginatorItemProps[];
2
+ export declare const getPageConfigs: ({ page, queryParams, pagesCount, handlePageClick, }: GetPageConfigParams) => PaginatorItemProps[];
3
3
  export declare const getPagesCount: (props: Pick<PaginatorProps, 'totalItems' | 'itemsPerPage' | 'maxPages'>) => number;
@@ -1,5 +1,5 @@
1
1
  const MAX_VISIBLE_PAGES = 5;
2
- export const getPageConfigs = ({ page, pagesCount, handlePageClick }) => {
2
+ export const getPageConfigs = ({ page, queryParams, pagesCount, handlePageClick, }) => {
3
3
  const paginatorItems = [];
4
4
  // it is calculating the middle of visible pages below
5
5
  const pageOffset = (MAX_VISIBLE_PAGES - 1) / 2;
@@ -16,6 +16,7 @@ export const getPageConfigs = ({ page, pagesCount, handlePageClick }) => {
16
16
  dataKey: String(i),
17
17
  index: i,
18
18
  mods: { type: 'page', active: page === i },
19
+ queryParams,
19
20
  onClick: handlePageClick,
20
21
  content: i,
21
22
  });
@@ -1,5 +1,5 @@
1
1
  import React, { MouseEvent } from 'react';
2
- import { PostData } from '../../models/common';
2
+ import { PostData, Query } from '../../models/common';
3
3
  import './Posts.css';
4
4
  type PostCardProps = {
5
5
  containerId: string;
@@ -14,6 +14,7 @@ type PostCardProps = {
14
14
  postsOnPage?: PostData[];
15
15
  pinnedPostOnPage?: PostData;
16
16
  pageCountForShowSupportButtons?: number;
17
+ queryParams: Query;
17
18
  };
18
- export declare const Posts: ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, }: PostCardProps) => React.JSX.Element;
19
+ export declare const Posts: ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, queryParams, }: PostCardProps) => React.JSX.Element;
19
20
  export {};
@@ -9,7 +9,7 @@ import { PostCard } from '../PostCard/PostCard';
9
9
  import { PostsEmpty } from '../PostsEmpty/PostsEmpty';
10
10
  import './Posts.css';
11
11
  const b = block('posts');
12
- export const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, }) => (React.createElement("div", { className: b() },
12
+ export const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, queryParams, }) => (React.createElement("div", { className: b() },
13
13
  isFetching && React.createElement("div", { className: b('loaderContainer') }),
14
14
  React.createElement("div", { id: containerId, className: b('cards-container', { isLoading: isFetching }) },
15
15
  pinnedPostOnPage && currentPage === 1 && (React.createElement("div", { className: b('pinned-container') },
@@ -27,4 +27,4 @@ export const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage,
27
27
  React.createElement("div", null, i18(Keyset.ErrorTitle)),
28
28
  React.createElement("div", null, i18(Keyset.PostLoadError)))),
29
29
  Boolean(currentPage && postCountOnPage) && (React.createElement("div", { className: b('paginator') },
30
- React.createElement(Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery, maxPages: Infinity, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))))));
30
+ React.createElement(Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery, maxPages: Infinity, pageCountForShowSupportButtons: pageCountForShowSupportButtons, queryParams: queryParams }))))));
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  export interface SettingsContextProps {
3
3
  addNavigationLinkForPages?: boolean;
4
+ getBlogPath?: (pathPrefix: string) => string;
4
5
  }
5
6
  export declare const SettingsContext: React.Context<SettingsContextProps>;
@@ -13,9 +13,8 @@ export declare function getAbsolutePath(router: RouterContextProps, url?: string
13
13
  export declare const getPageSearchParams: (query?: Query) => URLSearchParams;
14
14
  export declare const scrollToHash: (hash: string, browser?: string) => void;
15
15
  type CloudListTagStub = {};
16
- export declare const getTags: ((tags: Tag[], prefix?: string) => CloudListTagStub[]) & import("lodash").MemoizedFunction;
16
+ export declare const getTags: ((tags: Tag[], blogPath: string) => CloudListTagStub[]) & import("lodash").MemoizedFunction;
17
17
  export declare const postLikeStatus: import("lodash").DebouncedFunc<(postId: number, hasUserLike: boolean) => void>;
18
- export declare const getTagFilterUrl: (tagId: string | number, prefix: string) => string;
19
18
  export declare const updateContentSizes: ({ size, colSizes, theme, ...contentData }: ContentBlockProps) => {
20
19
  size: import("@gravity-ui/page-constructor").ContentSize;
21
20
  colSizes: {
@@ -35,10 +34,10 @@ export declare const updateContentSizes: ({ size, colSizes, theme, ...contentDat
35
34
  };
36
35
  type GetBreadcrumbsProps = {
37
36
  tags?: Tag[];
38
- pathPrefix?: string;
37
+ blogPath: string;
39
38
  };
40
39
  export declare const getBlogPath: (pathPrefix: string) => string;
41
- export declare const getBreadcrumbs: ({ tags, pathPrefix }: GetBreadcrumbsProps) => HeaderBreadCrumbsProps;
40
+ export declare const getBreadcrumbs: ({ tags, blogPath }: GetBreadcrumbsProps) => HeaderBreadCrumbsProps;
42
41
  export declare const isMetrikaExist: (goal: NewMetrikaGoal, existGoals: NewMetrikaGoal[]) => boolean;
43
42
  export declare const getBlogElementMetrika: (blogCustomGoal: NewMetrikaGoal, existingGoals?: MetrikaGoal) => string | string[] | NewMetrikaGoal[];
44
43
  export declare const getFeedQueryParams: (queryString: Query, pageNumber?: number) => GetPostsRequest;
@@ -32,40 +32,36 @@ export const scrollToHash = (hash, browser) => {
32
32
  }
33
33
  setTimeout(() => element.scrollIntoView({ behavior: browser === 'Yandex' ? 'auto' : 'smooth' }), 0);
34
34
  };
35
- export const getTags = memoize((tags, prefix) => {
35
+ export const getTags = memoize((tags, blogPath) => {
36
36
  return tags.map((_a) => {
37
37
  var { slug } = _a, tag = __rest(_a, ["slug"]);
38
38
  const queryParams = new URLSearchParams();
39
39
  queryParams.set('tags', slug);
40
- return Object.assign(Object.assign({}, tag), { id: slug, url: `${prefix}blog?${queryParams}` });
40
+ return Object.assign(Object.assign({}, tag), { id: slug, url: `${blogPath}?${queryParams}` });
41
41
  });
42
42
  });
43
43
  const stub = (postId) => postId;
44
44
  export const postLikeStatus = debounce((postId, hasUserLike) => {
45
45
  (hasUserLike ? stub : stub)(postId);
46
46
  }, 300);
47
- export const getTagFilterUrl = (tagId, prefix) => {
48
- return `${prefix}blog?tags=` + tagId;
49
- };
50
47
  export const updateContentSizes = (_a) => {
51
48
  var { size, colSizes, theme } = _a, contentData = __rest(_a, ["size", "colSizes", "theme"]);
52
49
  return (Object.assign(Object.assign({}, contentData), { size: size || CONTENT_DEFAULT_SIZE, colSizes: colSizes || CONTENT_DEFAULT_COL_SIZES, theme: theme || CONTENT_DEFAULT_THEME }));
53
50
  };
54
51
  export const getBlogPath = (pathPrefix) => {
55
- const prefix = pathPrefix ? `/${pathPrefix}/` : '/';
56
- return `${prefix}blog`;
52
+ const prefix = pathPrefix ? `/${pathPrefix}` : '';
53
+ return `${prefix}/blog`;
57
54
  };
58
- export const getBreadcrumbs = ({ tags, pathPrefix }) => {
59
- const prefix = pathPrefix ? `/${pathPrefix}/` : '/';
55
+ export const getBreadcrumbs = ({ tags, blogPath }) => {
60
56
  const breadcrumbs = {
61
- items: [{ text: i18(Keyset.TitleBreadcrumbs), url: `${prefix}blog` }],
57
+ items: [{ text: i18(Keyset.TitleBreadcrumbs), url: blogPath }],
62
58
  theme: 'light',
63
59
  };
64
60
  if (tags === null || tags === void 0 ? void 0 : tags.length) {
65
- const localizedTags = getTags(tags, prefix);
61
+ const localizedTags = getTags(tags, blogPath);
66
62
  const tag = localizedTags[0];
67
63
  // @ts-ignore todo fix
68
- breadcrumbs.items.push({ text: tag.name, url: getTagFilterUrl(tag.id, prefix) });
64
+ breadcrumbs.items.push({ text: tag.name, url: tag.url });
69
65
  }
70
66
  return breadcrumbs;
71
67
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/blog-constructor",
3
- "version": "5.14.0",
3
+ "version": "5.16.0",
4
4
  "description": "Gravity UI Blog Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -86,7 +86,7 @@
86
86
  "@gravity-ui/prettier-config": "^1.1.0",
87
87
  "@gravity-ui/stylelint-config": "^4.0.1",
88
88
  "@gravity-ui/tsconfig": "^1.0.0",
89
- "@gravity-ui/uikit": "^5.20.0",
89
+ "@gravity-ui/uikit": "^5.25.0",
90
90
  "@jest/environment": "^29.7.0",
91
91
  "@storybook/addon-essentials": "^7.0.27",
92
92
  "@storybook/cli": "^7.0.27",