@gravity-ui/blog-constructor 6.4.4-alpha.0 → 6.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. package/build/cjs/blocks/Header/Header.js +2 -2
  2. package/build/cjs/components/FeedHeader/components/Controls/Controls.js +21 -22
  3. package/build/cjs/components/FeedHeader/components/Controls/customRenders.d.ts +2 -1
  4. package/build/cjs/components/FeedHeader/components/Controls/customRenders.js +8 -2
  5. package/build/cjs/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.d.ts +8 -2
  6. package/build/cjs/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.js +2 -2
  7. package/build/cjs/containers/BlogPostPage/BlogPostPage.d.ts +3 -2
  8. package/build/cjs/containers/BlogPostPage/BlogPostPage.js +2 -1
  9. package/build/cjs/contexts/PostPageContext.d.ts +2 -0
  10. package/build/cjs/index.d.ts +1 -0
  11. package/build/cjs/index.js +2 -1
  12. package/build/cjs/utils/index.d.ts +1 -0
  13. package/build/cjs/utils/index.js +5 -0
  14. package/build/esm/blocks/Header/Header.js +2 -2
  15. package/build/esm/components/FeedHeader/components/Controls/Controls.js +22 -23
  16. package/build/esm/components/FeedHeader/components/Controls/customRenders.d.ts +2 -1
  17. package/build/esm/components/FeedHeader/components/Controls/customRenders.js +9 -2
  18. package/build/esm/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.d.ts +8 -2
  19. package/build/esm/components/FeedHeader/components/CustomSwitcher/CustomSwitcher.js +2 -2
  20. package/build/esm/containers/BlogPostPage/BlogPostPage.d.ts +3 -2
  21. package/build/esm/containers/BlogPostPage/BlogPostPage.js +2 -1
  22. package/build/esm/contexts/PostPageContext.d.ts +2 -0
  23. package/build/esm/index.d.ts +1 -0
  24. package/build/esm/index.js +2 -1
  25. package/build/esm/utils/index.d.ts +1 -0
  26. package/build/esm/utils/index.js +1 -0
  27. package/package.json +3 -3
@@ -23,7 +23,7 @@ const breadcrumbsGoals = (0, common_1.prepareAnalyticsEvent)({
23
23
  });
24
24
  const Header = (props) => {
25
25
  const { theme, paddingTop, paddingBottom } = props;
26
- const { post } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
26
+ const { post, breadcrumbs: customBreadcrumbs = {} } = (0, react_1.useContext)(PostPageContext_1.PostPageContext);
27
27
  const { locale } = (0, react_1.useContext)(LocaleContext_1.LocaleContext);
28
28
  const { getBlogPath = common_1.getBlogPath } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
29
29
  const blogPath = getBlogPath(locale.pathPrefix || '');
@@ -37,7 +37,7 @@ const Header = (props) => {
37
37
  [paddings_1.PaddingsDirections.top]: paddingTop,
38
38
  [paddings_1.PaddingsDirections.bottom]: paddingBottom,
39
39
  } },
40
- react_1.default.createElement(page_constructor_1.HeaderBlock, Object.assign({}, props, { title: title, description: description, breadcrumbs: breadcrumbs }),
40
+ react_1.default.createElement(page_constructor_1.HeaderBlock, Object.assign({}, props, { title: title, description: description, breadcrumbs: Object.assign(Object.assign({}, breadcrumbs), customBreadcrumbs) }),
41
41
  react_1.default.createElement(PostInfo_1.PostInfo, { postId: id, date: date, readingTime: readingTime, analyticsEventsContainer: analyticsEventsContainer, theme: theme, qa: "blog-header-meta-container" }))));
42
42
  };
43
43
  exports.Header = Header;
@@ -89,27 +89,26 @@ const Controls = ({ handleLoadData, tags = [], services = [], queryParams, }) =>
89
89
  };
90
90
  const tagsItems = (0, react_1.useMemo)(() => [{ value: 'empty', content: (0, i18n_1.i18n)(i18n_1.Keyset.AllTags) }, ...tags], [tags]);
91
91
  const servicesItems = (0, react_1.useMemo)(() => (servicesInitial ? [...servicesInitial.split(',')] : []), [servicesInitial]);
92
- return (react_1.default.createElement(uikit_1.MobileProvider, { mobile: false },
93
- react_1.default.createElement("div", { className: b('header') },
94
- react_1.default.createElement("h1", { className: b('header-item', { title: true }) }, (0, i18n_1.i18n)(i18n_1.Keyset.Title)),
95
- react_1.default.createElement("div", { className: b('header-item', { filters: true }) },
96
- react_1.default.createElement("div", { className: b('filter-item') },
97
- react_1.default.createElement(Search_1.Search, { className: b('search'), placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
98
- react_1.default.createElement("div", { className: b('filter-item') },
99
- react_1.default.createElement(uikit_1.Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: (0, customRenders_1.renderSwitcher)({
100
- initial: [tagInitial],
101
- list: tagsItems,
102
- defaultLabel: (0, i18n_1.i18n)(i18n_1.Keyset.AllTags),
103
- }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: customRenders_1.renderOption })),
104
- services.length > 0 ? (react_1.default.createElement("div", { className: b('filter-item') },
105
- 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.i18n)(i18n_1.Keyset.AllServices), renderControl: (0, customRenders_1.renderSwitcher)({
106
- initial: servicesItems,
107
- list: services,
108
- defaultLabel: (0, i18n_1.i18n)(i18n_1.Keyset.AllServices),
109
- }), virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: customRenders_1.renderOption, renderFilter: customRenders_1.renderFilter }))) : null,
110
- hasLikes ? (react_1.default.createElement("div", { className: b('filter-item', { 'width-auto': true }) },
111
- react_1.default.createElement(uikit_1.Button, { view: 'outlined', className: b('saved-only-button', { savedOnly }), size: "xl", onClick: handleSavedOnly, selected: savedOnly },
112
- react_1.default.createElement(uikit_1.Icon, { data: Save_1.Save, size: ICON_SIZE, className: b('icon', { savedOnly }) }),
113
- (0, i18n_1.i18n)(i18n_1.Keyset.ActionSavedOnly)))) : null))));
92
+ return (react_1.default.createElement("div", { className: b('header') },
93
+ react_1.default.createElement("h1", { className: b('header-item', { title: true }) }, (0, i18n_1.i18n)(i18n_1.Keyset.Title)),
94
+ react_1.default.createElement("div", { className: b('header-item', { filters: true }) },
95
+ react_1.default.createElement("div", { className: b('filter-item') },
96
+ react_1.default.createElement(Search_1.Search, { className: b('search'), placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
97
+ react_1.default.createElement("div", { className: b('filter-item') },
98
+ react_1.default.createElement(uikit_1.Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: (0, customRenders_1.renderSwitcher)({
99
+ initial: [tagInitial],
100
+ list: tagsItems,
101
+ defaultLabel: (0, i18n_1.i18n)(i18n_1.Keyset.AllTags),
102
+ }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: customRenders_1.renderOption })),
103
+ services.length > 0 ? (react_1.default.createElement("div", { className: b('filter-item') },
104
+ 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.i18n)(i18n_1.Keyset.AllServices), renderControl: (0, customRenders_1.renderSwitcher)({
105
+ initial: servicesItems,
106
+ list: services,
107
+ defaultLabel: (0, i18n_1.i18n)(i18n_1.Keyset.AllServices),
108
+ }), virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: customRenders_1.renderOption, renderFilter: customRenders_1.renderFilter }))) : null,
109
+ hasLikes ? (react_1.default.createElement("div", { className: b('filter-item', { 'width-auto': true }) },
110
+ react_1.default.createElement(uikit_1.Button, { view: 'outlined', className: b('saved-only-button', { savedOnly }), size: "xl", onClick: handleSavedOnly, selected: savedOnly },
111
+ react_1.default.createElement(uikit_1.Icon, { data: Save_1.Save, size: ICON_SIZE, className: b('icon', { savedOnly }) }),
112
+ (0, i18n_1.i18n)(i18n_1.Keyset.ActionSavedOnly)))) : null)));
114
113
  };
115
114
  exports.Controls = Controls;
@@ -6,7 +6,8 @@ type RenderSwitcherType = ({ initial, list, defaultLabel, }: {
6
6
  list: CustomSwitcherProps['list'];
7
7
  defaultLabel: string;
8
8
  }) => SelectProps['renderControl'];
9
+ type RenderFilterType = SelectProps['renderFilter'];
9
10
  export declare const renderSwitcher: RenderSwitcherType;
10
- export declare const renderFilter: SelectProps['renderFilter'];
11
+ export declare const renderFilter: RenderFilterType;
11
12
  export declare const renderOption: (option: SelectOption) => React.JSX.Element;
12
13
  export {};
@@ -11,9 +11,15 @@ const CustomSwitcher_1 = require("../CustomSwitcher/CustomSwitcher");
11
11
  const b = (0, cn_1.block)('feed-controls');
12
12
  const renderSwitcher = ({ initial, list, defaultLabel }) =>
13
13
  // eslint-disable-next-line react/display-name
14
- ({ onClick, ref, onKeyDown, open, renderClear, popupId, activeIndex }) => (react_1.default.createElement(CustomSwitcher_1.CustomSwitcher, { initial: initial, defaultLabel: defaultLabel, list: list, controlRef: ref, onClick: onClick, onKeyDown: onKeyDown, renderClear: renderClear, open: open, popupId: popupId, activeIndex: activeIndex }));
14
+ (_a) => {
15
+ var { ref, renderClear } = _a, _b = _a.triggerProps, { id, disabled, type, onClick, onKeyDown } = _b, a11yProps = tslib_1.__rest(_b, ["id", "disabled", "type", "onClick", "onKeyDown"]);
16
+ return (react_1.default.createElement(CustomSwitcher_1.CustomSwitcher, { id: id, disabled: disabled, type: type, initial: initial, defaultLabel: defaultLabel, list: list, controlRef: ref, onClick: onClick, onKeyDown: onKeyDown, renderClear: renderClear, a11yProps: a11yProps }));
17
+ };
15
18
  exports.renderSwitcher = renderSwitcher;
16
- const renderFilter = ({ value, onChange, onKeyDown }) => (react_1.default.createElement(uikit_1.TextInput, { controlProps: { size: 1 }, value: value, view: "clear", placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.Search), onUpdate: onChange, onKeyDown: onKeyDown, className: b('popup-filter') }));
19
+ const renderFilter = (_a) => {
20
+ var { ref, onChange } = _a, _b = _a.inputProps, { value, onKeyDown, onChange: _, size: __, placeholder: ___ } = _b, a11yProps = tslib_1.__rest(_b, ["value", "onKeyDown", "onChange", "size", "placeholder"]);
21
+ return (react_1.default.createElement(uikit_1.TextInput, { value: value, view: "clear", placeholder: (0, i18n_1.i18n)(i18n_1.Keyset.Search), onUpdate: onChange, onKeyDown: onKeyDown, className: b('popup-filter'), controlRef: ref, controlProps: Object.assign({ size: 1 }, a11yProps) }));
22
+ };
17
23
  exports.renderFilter = renderFilter;
18
24
  const renderOption = (option) => (react_1.default.createElement(CustomSelectOption_1.CustomSelectOption, { data: option }));
19
25
  exports.renderOption = renderOption;
@@ -2,11 +2,17 @@ import React from 'react';
2
2
  import { SelectProps } from '@gravity-ui/uikit';
3
3
  import { SelectItem } from '../Controls/Controls';
4
4
  type RenderControlParameters = Partial<Parameters<Required<SelectProps>['renderControl']>[0]>;
5
+ type TriggerProps = Required<RenderControlParameters>['triggerProps'];
6
+ type A11yKeys = {
7
+ [K in keyof TriggerProps]-?: K extends `aria-${string}` | 'role' ? K : never;
8
+ }[keyof TriggerProps];
9
+ type RenderControlA11yProps = Pick<TriggerProps, A11yKeys>;
5
10
  export type CustomSwitcherProps = {
6
11
  initial: (string | number | null)[];
7
12
  defaultLabel: string;
8
13
  list: SelectItem[];
9
14
  controlRef: RenderControlParameters['ref'];
10
- } & Omit<RenderControlParameters, 'ref'>;
11
- export declare const CustomSwitcher: ({ initial, defaultLabel, list, onClick, controlRef, onKeyDown, open, renderClear, popupId, activeIndex, }: CustomSwitcherProps) => React.JSX.Element;
15
+ a11yProps: RenderControlA11yProps;
16
+ } & Omit<RenderControlParameters, 'ref'> & Pick<TriggerProps, 'id' | 'disabled' | 'type'>;
17
+ export declare const CustomSwitcher: ({ id, disabled, type, initial, defaultLabel, list, onClick, controlRef, onKeyDown, renderClear, a11yProps, }: CustomSwitcherProps) => React.JSX.Element;
12
18
  export {};
@@ -10,7 +10,7 @@ const cn_1 = require("../../../../utils/cn");
10
10
  const b = (0, cn_1.block)('feed-custom-switcher');
11
11
  const ICON_SIZE = 12;
12
12
  const CLEAR_ICON_SIZE = 11;
13
- const CustomSwitcher = ({ initial, defaultLabel, list, onClick, controlRef, onKeyDown, open, renderClear, popupId, activeIndex, }) => {
13
+ const CustomSwitcher = ({ id, disabled, type, initial, defaultLabel, list, onClick, controlRef, onKeyDown, renderClear, a11yProps, }) => {
14
14
  const itemsNames = (0, react_1.useMemo)(() => {
15
15
  const items = list
16
16
  .filter((item) => initial.includes(item.value))
@@ -20,7 +20,7 @@ const CustomSwitcher = ({ initial, defaultLabel, list, onClick, controlRef, onKe
20
20
  const hasCounter = itemsNames.length > 1;
21
21
  const contentElementId = (0, uikit_1.useUniqId)();
22
22
  return (react_1.default.createElement("div", { className: b('custom-switcher'), ref: controlRef },
23
- react_1.default.createElement("button", { onClick: onClick, className: b('custom-switcher-element', { overlay: true }), onKeyDown: onKeyDown, "aria-expanded": open, "aria-labelledby": contentElementId, "aria-activedescendant": activeIndex === undefined ? undefined : `${popupId}-item-${activeIndex}` }),
23
+ react_1.default.createElement("button", Object.assign({ id: id, disabled: disabled, type: type, onClick: onClick, className: b('custom-switcher-element', { overlay: true }), onKeyDown: onKeyDown }, a11yProps, { "aria-labelledby": contentElementId })),
24
24
  react_1.default.createElement("div", { id: contentElementId, className: b('custom-switcher-element', { content: true }), "aria-hidden": true }, itemsNames === null || itemsNames === void 0 ? void 0 : itemsNames.join(', ')),
25
25
  renderClear &&
26
26
  renderClear({
@@ -1,6 +1,6 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
- import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
+ import { CustomConfig, HeaderBreadCrumbsProps, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
4
4
  import { MetaProps, PostData, ToggleLikeCallbackType } from '../../models/common';
5
5
  export interface BlogPostPageProps {
6
6
  suggestedPosts: PostData[];
@@ -18,5 +18,6 @@ export interface BlogPostPageProps {
18
18
  shareOptions?: ShareOptions[];
19
19
  isSignedInUser?: boolean;
20
20
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
21
+ breadcrumbs?: HeaderBreadCrumbsProps;
21
22
  }
22
- export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
23
+ export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, breadcrumbs, }: BlogPostPageProps) => React.JSX.Element;
@@ -12,7 +12,7 @@ const PostPageContext_1 = require("../../contexts/PostPageContext");
12
12
  const useExtendedComponentMap_1 = require("../../hooks/useExtendedComponentMap");
13
13
  const useLikes_1 = require("../../hooks/useLikes");
14
14
  const SettingsContext_1 = require("../../contexts/SettingsContext");
15
- const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
15
+ const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, breadcrumbs, }) => {
16
16
  const { isAnimationEnabled } = (0, react_1.useContext)(SettingsContext_1.SettingsContext);
17
17
  const { hasUserLike, likesCount, handleLike } = (0, useLikes_1.useLikes)({
18
18
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
@@ -40,6 +40,7 @@ const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings
40
40
  }
41
41
  : undefined,
42
42
  shareOptions,
43
+ breadcrumbs,
43
44
  } },
44
45
  react_1.default.createElement(page_constructor_1.PageConstructorProvider, Object.assign({}, settings, { projectSettings: Object.assign(Object.assign({}, ((settings === null || settings === void 0 ? void 0 : settings.projectSettings) || {})), { isAnimationEnabled }) }),
45
46
  metaData ? react_1.default.createElement(MetaWrapper_1.MetaWrapper, Object.assign({}, metaData)) : null,
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
3
  import { PostData } from '../models/common';
4
+ import { HeaderBreadCrumbsProps } from '@gravity-ui/page-constructor';
4
5
  export type LikesRoutineType = {
5
6
  handleUserLike: () => void;
6
7
  hasUserLike: boolean;
@@ -11,5 +12,6 @@ export interface PostPageContextProps {
11
12
  suggestedPosts: PostData[];
12
13
  likes?: LikesRoutineType;
13
14
  shareOptions?: ShareOptions[];
15
+ breadcrumbs?: HeaderBreadCrumbsProps;
14
16
  }
15
17
  export declare const PostPageContext: React.Context<PostPageContextProps>;
@@ -5,3 +5,4 @@ export * from './models/common';
5
5
  export * from './models/locale';
6
6
  export * from './schema';
7
7
  export { BREAKPOINTS } from './constants';
8
+ export * from './utils';
@@ -12,4 +12,5 @@ tslib_1.__exportStar(require("./models/common"), exports);
12
12
  tslib_1.__exportStar(require("./models/locale"), exports);
13
13
  tslib_1.__exportStar(require("./schema"), exports);
14
14
  var constants_1 = require("./constants");
15
- Object.defineProperty(exports, "BREAKPOINTS", { enumerable: true, get: function () { return constants_1.BREAKPOINTS; } });
15
+ Object.defineProperty(exports, "BREAKPOINTS", { enumerable: true, get: function () { return constants_1.BREAKPOINTS; } });
16
+ tslib_1.__exportStar(require("./utils"), exports);
@@ -0,0 +1 @@
1
+ export { getBreadcrumbs } from './common';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBreadcrumbs = void 0;
4
+ var common_1 = require("./common");
5
+ Object.defineProperty(exports, "getBreadcrumbs", { enumerable: true, get: function () { return common_1.getBreadcrumbs; } });
@@ -19,7 +19,7 @@ const breadcrumbsGoals = prepareAnalyticsEvent({
19
19
  });
20
20
  export const Header = (props) => {
21
21
  const { theme, paddingTop, paddingBottom } = props;
22
- const { post } = useContext(PostPageContext);
22
+ const { post, breadcrumbs: customBreadcrumbs = {} } = useContext(PostPageContext);
23
23
  const { locale } = useContext(LocaleContext);
24
24
  const { getBlogPath = getDefaultBlogPath } = useContext(SettingsContext);
25
25
  const blogPath = getBlogPath(locale.pathPrefix || '');
@@ -33,6 +33,6 @@ export const Header = (props) => {
33
33
  [PaddingsDirections.top]: paddingTop,
34
34
  [PaddingsDirections.bottom]: paddingBottom,
35
35
  } },
36
- React.createElement(HeaderBlock, Object.assign({}, props, { title: title, description: description, breadcrumbs: breadcrumbs }),
36
+ React.createElement(HeaderBlock, Object.assign({}, props, { title: title, description: description, breadcrumbs: Object.assign(Object.assign({}, breadcrumbs), customBreadcrumbs) }),
37
37
  React.createElement(PostInfo, { postId: id, date: date, readingTime: readingTime, analyticsEventsContainer: analyticsEventsContainer, theme: theme, qa: "blog-header-meta-container" }))));
38
38
  };
@@ -1,6 +1,6 @@
1
1
  import React, { useContext, useMemo, useState } from 'react';
2
2
  import { useAnalytics } from '@gravity-ui/page-constructor';
3
- import { Button, Icon, MobileProvider, Select } from '@gravity-ui/uikit';
3
+ import { Button, Icon, Select } from '@gravity-ui/uikit';
4
4
  import { DefaultGoalIds } from '../../../../constants';
5
5
  import { LikesContext } from '../../../../contexts/LikesContext';
6
6
  import { MobileContext } from '../../../../contexts/MobileContext';
@@ -86,26 +86,25 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
86
86
  };
87
87
  const tagsItems = useMemo(() => [{ value: 'empty', content: i18n(Keyset.AllTags) }, ...tags], [tags]);
88
88
  const servicesItems = useMemo(() => (servicesInitial ? [...servicesInitial.split(',')] : []), [servicesInitial]);
89
- return (React.createElement(MobileProvider, { mobile: false },
90
- React.createElement("div", { className: b('header') },
91
- React.createElement("h1", { className: b('header-item', { title: true }) }, i18n(Keyset.Title)),
92
- React.createElement("div", { className: b('header-item', { filters: true }) },
93
- React.createElement("div", { className: b('filter-item') },
94
- React.createElement(Search, { className: b('search'), placeholder: i18n(Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
95
- React.createElement("div", { className: b('filter-item') },
96
- React.createElement(Select, { className: b('select'), size: "xl", options: tagsItems, defaultValue: [tagInitial], onUpdate: handleTagSelect, placeholder: i18n(Keyset.AllTags), popupClassName: b('popup', { isMobile }), renderControl: renderSwitcher({
97
- initial: [tagInitial],
98
- list: tagsItems,
99
- defaultLabel: i18n(Keyset.AllTags),
100
- }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption })),
101
- services.length > 0 ? (React.createElement("div", { className: b('filter-item') },
102
- 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({
103
- initial: servicesItems,
104
- list: services,
105
- defaultLabel: i18n(Keyset.AllServices),
106
- }), virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption, renderFilter: renderFilter }))) : null,
107
- hasLikes ? (React.createElement("div", { className: b('filter-item', { 'width-auto': true }) },
108
- React.createElement(Button, { view: 'outlined', className: b('saved-only-button', { savedOnly }), size: "xl", onClick: handleSavedOnly, selected: savedOnly },
109
- React.createElement(Icon, { data: Save, size: ICON_SIZE, className: b('icon', { savedOnly }) }),
110
- i18n(Keyset.ActionSavedOnly)))) : null))));
89
+ return (React.createElement("div", { className: b('header') },
90
+ React.createElement("h1", { className: b('header-item', { title: true }) }, i18n(Keyset.Title)),
91
+ React.createElement("div", { className: b('header-item', { filters: true }) },
92
+ React.createElement("div", { className: b('filter-item') },
93
+ React.createElement(Search, { className: b('search'), placeholder: i18n(Keyset.Search), initialValue: search && typeof search === 'string' ? search : '', onSubmit: handleSearch })),
94
+ React.createElement("div", { className: b('filter-item') },
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({
96
+ initial: [tagInitial],
97
+ list: tagsItems,
98
+ defaultLabel: i18n(Keyset.AllTags),
99
+ }), disablePortal: true, virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption })),
100
+ services.length > 0 ? (React.createElement("div", { className: b('filter-item') },
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({
102
+ initial: servicesItems,
103
+ list: services,
104
+ defaultLabel: i18n(Keyset.AllServices),
105
+ }), virtualizationThreshold: VIRTUALIZATION_THRESHOLD, renderOption: renderOption, renderFilter: renderFilter }))) : null,
106
+ hasLikes ? (React.createElement("div", { className: b('filter-item', { 'width-auto': true }) },
107
+ React.createElement(Button, { view: 'outlined', className: b('saved-only-button', { savedOnly }), size: "xl", onClick: handleSavedOnly, selected: savedOnly },
108
+ React.createElement(Icon, { data: Save, size: ICON_SIZE, className: b('icon', { savedOnly }) }),
109
+ i18n(Keyset.ActionSavedOnly)))) : null)));
111
110
  };
@@ -7,7 +7,8 @@ type RenderSwitcherType = ({ initial, list, defaultLabel, }: {
7
7
  list: CustomSwitcherProps['list'];
8
8
  defaultLabel: string;
9
9
  }) => SelectProps['renderControl'];
10
+ type RenderFilterType = SelectProps['renderFilter'];
10
11
  export declare const renderSwitcher: RenderSwitcherType;
11
- export declare const renderFilter: SelectProps['renderFilter'];
12
+ export declare const renderFilter: RenderFilterType;
12
13
  export declare const renderOption: (option: SelectOption) => React.JSX.Element;
13
14
  export {};
@@ -1,3 +1,4 @@
1
+ import { __rest } from "tslib";
1
2
  import React from 'react';
2
3
  import { TextInput } from '@gravity-ui/uikit';
3
4
  import { Keyset, i18n } from '../../../../i18n';
@@ -8,6 +9,12 @@ import './Controls.css';
8
9
  const b = block('feed-controls');
9
10
  export const renderSwitcher = ({ initial, list, defaultLabel }) =>
10
11
  // eslint-disable-next-line react/display-name
11
- ({ onClick, ref, onKeyDown, open, renderClear, popupId, activeIndex }) => (React.createElement(CustomSwitcher, { initial: initial, defaultLabel: defaultLabel, list: list, controlRef: ref, onClick: onClick, onKeyDown: onKeyDown, renderClear: renderClear, open: open, popupId: popupId, activeIndex: activeIndex }));
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') }));
12
+ (_a) => {
13
+ var { ref, renderClear } = _a, _b = _a.triggerProps, { id, disabled, type, onClick, onKeyDown } = _b, a11yProps = __rest(_b, ["id", "disabled", "type", "onClick", "onKeyDown"]);
14
+ return (React.createElement(CustomSwitcher, { id: id, disabled: disabled, type: type, initial: initial, defaultLabel: defaultLabel, list: list, controlRef: ref, onClick: onClick, onKeyDown: onKeyDown, renderClear: renderClear, a11yProps: a11yProps }));
15
+ };
16
+ export const renderFilter = (_a) => {
17
+ var { ref, onChange } = _a, _b = _a.inputProps, { value, onKeyDown, onChange: _, size: __, placeholder: ___ } = _b, a11yProps = __rest(_b, ["value", "onKeyDown", "onChange", "size", "placeholder"]);
18
+ return (React.createElement(TextInput, { value: value, view: "clear", placeholder: i18n(Keyset.Search), onUpdate: onChange, onKeyDown: onKeyDown, className: b('popup-filter'), controlRef: ref, controlProps: Object.assign({ size: 1 }, a11yProps) }));
19
+ };
13
20
  export const renderOption = (option) => (React.createElement(CustomSelectOption, { data: option }));
@@ -3,11 +3,17 @@ import { SelectProps } from '@gravity-ui/uikit';
3
3
  import { SelectItem } from '../Controls/Controls';
4
4
  import './CustomSwitcher.css';
5
5
  type RenderControlParameters = Partial<Parameters<Required<SelectProps>['renderControl']>[0]>;
6
+ type TriggerProps = Required<RenderControlParameters>['triggerProps'];
7
+ type A11yKeys = {
8
+ [K in keyof TriggerProps]-?: K extends `aria-${string}` | 'role' ? K : never;
9
+ }[keyof TriggerProps];
10
+ type RenderControlA11yProps = Pick<TriggerProps, A11yKeys>;
6
11
  export type CustomSwitcherProps = {
7
12
  initial: (string | number | null)[];
8
13
  defaultLabel: string;
9
14
  list: SelectItem[];
10
15
  controlRef: RenderControlParameters['ref'];
11
- } & Omit<RenderControlParameters, 'ref'>;
12
- export declare const CustomSwitcher: ({ initial, defaultLabel, list, onClick, controlRef, onKeyDown, open, renderClear, popupId, activeIndex, }: CustomSwitcherProps) => React.JSX.Element;
16
+ a11yProps: RenderControlA11yProps;
17
+ } & Omit<RenderControlParameters, 'ref'> & Pick<TriggerProps, 'id' | 'disabled' | 'type'>;
18
+ export declare const CustomSwitcher: ({ id, disabled, type, initial, defaultLabel, list, onClick, controlRef, onKeyDown, renderClear, a11yProps, }: CustomSwitcherProps) => React.JSX.Element;
13
19
  export {};
@@ -7,7 +7,7 @@ import './CustomSwitcher.css';
7
7
  const b = block('feed-custom-switcher');
8
8
  const ICON_SIZE = 12;
9
9
  const CLEAR_ICON_SIZE = 11;
10
- export const CustomSwitcher = ({ initial, defaultLabel, list, onClick, controlRef, onKeyDown, open, renderClear, popupId, activeIndex, }) => {
10
+ export const CustomSwitcher = ({ id, disabled, type, initial, defaultLabel, list, onClick, controlRef, onKeyDown, renderClear, a11yProps, }) => {
11
11
  const itemsNames = useMemo(() => {
12
12
  const items = list
13
13
  .filter((item) => initial.includes(item.value))
@@ -17,7 +17,7 @@ export const CustomSwitcher = ({ initial, defaultLabel, list, onClick, controlRe
17
17
  const hasCounter = itemsNames.length > 1;
18
18
  const contentElementId = useUniqId();
19
19
  return (React.createElement("div", { className: b('custom-switcher'), ref: controlRef },
20
- React.createElement("button", { onClick: onClick, className: b('custom-switcher-element', { overlay: true }), onKeyDown: onKeyDown, "aria-expanded": open, "aria-labelledby": contentElementId, "aria-activedescendant": activeIndex === undefined ? undefined : `${popupId}-item-${activeIndex}` }),
20
+ React.createElement("button", Object.assign({ id: id, disabled: disabled, type: type, onClick: onClick, className: b('custom-switcher-element', { overlay: true }), onKeyDown: onKeyDown }, a11yProps, { "aria-labelledby": contentElementId })),
21
21
  React.createElement("div", { id: contentElementId, className: b('custom-switcher-element', { content: true }), "aria-hidden": true }, itemsNames === null || itemsNames === void 0 ? void 0 : itemsNames.join(', ')),
22
22
  renderClear &&
23
23
  renderClear({
@@ -1,6 +1,6 @@
1
1
  import React, { SyntheticEvent } from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
- import { CustomConfig, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
3
+ import { CustomConfig, HeaderBreadCrumbsProps, NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
4
4
  import { MetaProps, PostData, ToggleLikeCallbackType } from '../../models/common';
5
5
  import './BlogPostPage.css';
6
6
  export interface BlogPostPageProps {
@@ -19,5 +19,6 @@ export interface BlogPostPageProps {
19
19
  shareOptions?: ShareOptions[];
20
20
  isSignedInUser?: boolean;
21
21
  onClickSignIn?: React.EventHandler<SyntheticEvent>;
22
+ breadcrumbs?: HeaderBreadCrumbsProps;
22
23
  }
23
- export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, }: BlogPostPageProps) => React.JSX.Element;
24
+ export declare const BlogPostPage: ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser, onClickSignIn, breadcrumbs, }: BlogPostPageProps) => React.JSX.Element;
@@ -10,7 +10,7 @@ import { useExtendedComponentMap } from '../../hooks/useExtendedComponentMap';
10
10
  import { useLikes } from '../../hooks/useLikes';
11
11
  import { SettingsContext } from '../../contexts/SettingsContext';
12
12
  import './BlogPostPage.css';
13
- export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, }) => {
13
+ export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, settings, navigation, custom, shareOptions, isSignedInUser = false, onClickSignIn, breadcrumbs, }) => {
14
14
  const { isAnimationEnabled } = useContext(SettingsContext);
15
15
  const { hasUserLike, likesCount, handleLike } = useLikes({
16
16
  hasLike: likes === null || likes === void 0 ? void 0 : likes.hasUserLike,
@@ -38,6 +38,7 @@ export const BlogPostPage = ({ metaData, suggestedPosts, likes, content, post, s
38
38
  }
39
39
  : undefined,
40
40
  shareOptions,
41
+ breadcrumbs,
41
42
  } },
42
43
  React.createElement(PageConstructorProvider, Object.assign({}, settings, { projectSettings: Object.assign(Object.assign({}, ((settings === null || settings === void 0 ? void 0 : settings.projectSettings) || {})), { isAnimationEnabled }) }),
43
44
  metaData ? React.createElement(MetaWrapper, Object.assign({}, metaData)) : null,
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ShareOptions } from '@gravity-ui/components';
3
3
  import { PostData } from '../models/common';
4
+ import { HeaderBreadCrumbsProps } from '@gravity-ui/page-constructor';
4
5
  export type LikesRoutineType = {
5
6
  handleUserLike: () => void;
6
7
  hasUserLike: boolean;
@@ -11,5 +12,6 @@ export interface PostPageContextProps {
11
12
  suggestedPosts: PostData[];
12
13
  likes?: LikesRoutineType;
13
14
  shareOptions?: ShareOptions[];
15
+ breadcrumbs?: HeaderBreadCrumbsProps;
14
16
  }
15
17
  export declare const PostPageContext: React.Context<PostPageContextProps>;
@@ -5,3 +5,4 @@ export * from './models/common';
5
5
  export * from './models/locale';
6
6
  export * from './schema';
7
7
  export { BREAKPOINTS } from './constants';
8
+ export * from './utils';
@@ -4,4 +4,5 @@ export { BlogPage } from './containers/BlogPage/BlogPage';
4
4
  export * from './models/common';
5
5
  export * from './models/locale';
6
6
  export * from './schema';
7
- export { BREAKPOINTS } from './constants';
7
+ export { BREAKPOINTS } from './constants';
8
+ export * from './utils';
@@ -0,0 +1 @@
1
+ export { getBreadcrumbs } from './common';
@@ -0,0 +1 @@
1
+ export { getBreadcrumbs } from './common';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/blog-constructor",
3
- "version": "6.4.4-alpha.0",
3
+ "version": "6.6.0",
4
4
  "description": "Gravity UI Blog Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -79,7 +79,7 @@
79
79
  "peerDependencies": {
80
80
  "@diplodoc/transform": "^4.10.7",
81
81
  "@gravity-ui/page-constructor": "^5.0.0",
82
- "@gravity-ui/uikit": "^6.1.1",
82
+ "@gravity-ui/uikit": "^6.26.0",
83
83
  "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
84
84
  },
85
85
  "devDependencies": {
@@ -93,7 +93,7 @@
93
93
  "@gravity-ui/prettier-config": "^1.1.0",
94
94
  "@gravity-ui/stylelint-config": "^4.0.1",
95
95
  "@gravity-ui/tsconfig": "^1.0.0",
96
- "@gravity-ui/uikit": "^6.22.0",
96
+ "@gravity-ui/uikit": "^6.26.0",
97
97
  "@jest/environment": "^29.7.0",
98
98
  "@playwright/experimental-ct-react": "^1.45.3",
99
99
  "@playwright/test": "^1.45.3",