@cloud-ru/ds-uikit-product-header 1.3.2 → 1.3.3-preview-18093d38.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.
- package/README.md +2 -0
- package/dist/cjs/components/MainMenu/helperComponents/Content/Content.js +1 -1
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +4 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +5 -0
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
- package/dist/cjs/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
- package/dist/cjs/components/MainMenu/types.d.ts +2 -0
- package/dist/cjs/style.css +8 -0
- package/dist/esm/components/MainMenu/helperComponents/Content/Content.js +1 -1
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.d.ts +3 -1
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.js +5 -3
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.css +5 -0
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.js +5 -2
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.js +6 -2
- package/dist/esm/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.css +3 -0
- package/dist/esm/components/MainMenu/types.d.ts +2 -0
- package/dist/esm/style.css +8 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +27 -27
- package/src/components/MainMenu/helperComponents/Content/Content.tsx +1 -0
- package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/ContentToolbar.tsx +27 -11
- package/src/components/MainMenu/helperComponents/Content/helperComponents/ContentToolbar/styles.module.scss +5 -0
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategory.tsx +6 -2
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/SubCategoryTitle.tsx +10 -2
- package/src/components/MainMenu/helperComponents/Content/helperComponents/SortableGroup/components/SubCategory/styles.module.scss +7 -0
- package/src/components/MainMenu/types.ts +2 -0
package/README.md
CHANGED
|
@@ -342,6 +342,7 @@ function LocalMainMenu() {
|
|
|
342
342
|
| `badge` | `CardServiceLightProps` \| `PromoTagPredefinedBaseProps` | — | |
|
|
343
343
|
| `description` | `string \| undefined` | — | Краткое описание сервиса — отображается при включённом переключателе «Описание». |
|
|
344
344
|
| `disabled` | `boolean \| undefined` | — | |
|
|
345
|
+
| `expandableEnabled` | `boolean \| undefined` | — | Разрешено ли раскрытие карточки. default=false - Запрещено |
|
|
345
346
|
| `favoritesEnabled` | `boolean \| undefined` | — | Разрешено ли добавление карточки в избранное. default=true - разрешено |
|
|
346
347
|
| `hidden` | `boolean \| undefined` | — | |
|
|
347
348
|
| `href` | `string \| undefined` | — | |
|
|
@@ -513,6 +514,7 @@ import { MainMenu, MenuMobile } from '@cloud-ru/ds-uikit-product-header';
|
|
|
513
514
|
| `badge` | `CardServiceLightProps` \| `PromoTagPredefinedBaseProps` | — | |
|
|
514
515
|
| `description` | `string \| undefined` | — | Краткое описание сервиса — отображается при включённом переключателе «Описание». |
|
|
515
516
|
| `disabled` | `boolean \| undefined` | — | |
|
|
517
|
+
| `expandableEnabled` | `boolean \| undefined` | — | Разрешено ли раскрытие карточки. default=false - Запрещено |
|
|
516
518
|
| `favoritesEnabled` | `boolean \| undefined` | — | Разрешено ли добавление карточки в избранное. default=true - разрешено |
|
|
517
519
|
| `hidden` | `boolean \| undefined` | — | |
|
|
518
520
|
| `href` | `string \| undefined` | — | |
|
|
@@ -97,5 +97,5 @@ function Content({ searchValue, search, rightTop, segments, searchGroups = [], s
|
|
|
97
97
|
appearance: 'neutral',
|
|
98
98
|
}, content: isSearching ? t('noDataFound') : t('noData'), "data-test-id": isSearching ? constants_1.TEST_IDS.noDataFound : constants_1.TEST_IDS.noData, "data-mobile": isMobile || undefined, className: styles_module_scss_1.default.noData }));
|
|
99
99
|
})();
|
|
100
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [search, (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isMobile && rightTop, (0, jsx_runtime_1.jsx)(ContentToolbar_1.ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
100
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [search, (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isMobile && rightTop, (0, jsx_runtime_1.jsx)(ContentToolbar_1.ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile, loading: loading }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
101
101
|
}
|
|
@@ -14,5 +14,7 @@ export type ContentToolbarProps = {
|
|
|
14
14
|
/** Настройки меню (модалка по кнопке). Не передано — кнопка настроек не отображается. */
|
|
15
15
|
preferences?: MainMenuPreferencesProps;
|
|
16
16
|
isMobile?: boolean;
|
|
17
|
+
/** Флаг загрузки данных — сегменты подгружаются с бэка, поэтому SegmentControl тоже уходит в скелетон. */
|
|
18
|
+
loading?: boolean;
|
|
17
19
|
};
|
|
18
|
-
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,6 +9,7 @@ const button_1 = require("@cloud-ru/ds-button");
|
|
|
9
9
|
const system_1 = require("@cloud-ru/ds-icons/interface/system");
|
|
10
10
|
const modal_1 = require("@cloud-ru/ds-modal");
|
|
11
11
|
const segment_control_1 = require("@cloud-ru/ds-segment-control");
|
|
12
|
+
const skeleton_1 = require("@cloud-ru/ds-skeleton");
|
|
12
13
|
const uikit_product_switch_row_1 = require("@cloud-ru/ds-uikit-product-switch-row");
|
|
13
14
|
const utils_1 = require("@cloud-ru/ds-utils");
|
|
14
15
|
const react_1 = require("react");
|
|
@@ -16,7 +17,7 @@ const locale_1 = require("../../../../../../locale");
|
|
|
16
17
|
const HeaderButton_1 = require("../../../../../HeaderButton");
|
|
17
18
|
const constants_1 = require("../../constants");
|
|
18
19
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
19
|
-
function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }) {
|
|
20
|
+
function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }) {
|
|
20
21
|
const { t } = locale_1.headerLocale.useTranslations();
|
|
21
22
|
const [open = false, setOpen] = (0, utils_1.useValueControl)({
|
|
22
23
|
value: preferences?.open,
|
|
@@ -28,7 +29,8 @@ function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpan
|
|
|
28
29
|
(0, react_1.startTransition)(() => preferences?.showDescription?.onChange(value));
|
|
29
30
|
};
|
|
30
31
|
const hasSegmentItems = segmentItems && segmentItems?.length > 0;
|
|
31
|
-
|
|
32
|
+
const segmentControlSkeletonSize = isMobile ? { width: '100%', height: 48 } : { width: 262, height: 32 };
|
|
33
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.root, "data-test-id": constants_1.TEST_IDS.toolbar, children: [hasSegmentItems && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: loading ? ((0, jsx_runtime_1.jsx)(skeleton_1.SkeletonContext.Provider, { value: true, children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.segmentControlSkeleton, "data-test-id": constants_1.TEST_IDS.segmentControl, children: (0, jsx_runtime_1.jsx)(skeleton_1.Skeleton, { ...segmentControlSkeletonSize }) }) })) : ((0, jsx_runtime_1.jsx)(segment_control_1.SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles_module_scss_1.default.segmentControl, "data-test-id": constants_1.TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' })) })), (preferences || !isMobile) && !loading && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.actions, children: [preferences && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: (0, jsx_runtime_1.jsx)(system_1.SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsButton, onClick: openModal }), (0, jsx_runtime_1.jsx)(modal_1.Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": constants_1.TEST_IDS.settingsModal, cancelButton: {
|
|
32
34
|
label: t('close'),
|
|
33
35
|
onClick: closeModal,
|
|
34
36
|
}, content: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.settingsContent, children: [preferences.showGroupsColors && ((0, jsx_runtime_1.jsx)(uikit_product_switch_row_1.SwitchRow, { title: t('menuSettingsShowGroupsColors'), checked: preferences.showGroupsColors.value, onChange: preferences.showGroupsColors.onChange, "data-test-id": constants_1.TEST_IDS.settingsShowGroupsColorsSwitch })), (0, jsx_runtime_1.jsx)(uikit_product_switch_row_1.SwitchRow, { title: t('menuSettingsShowDescription'), checked: preferences.showDescription.value, onChange: handleShowDescriptionChange, "data-test-id": constants_1.TEST_IDS.settingsShowDescriptionSwitch })] }) })] })), !isMobile && ((0, jsx_runtime_1.jsx)(HeaderButton_1.HeaderButton, { icon: allGroupsExpanded ? (0, jsx_runtime_1.jsx)(system_1.CollapseVerticalSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.ExpandVerticalSVG, {}), "aria-label": allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups'), "data-test-id": constants_1.TEST_IDS.toggleAllGroups, onClick: onToggleAllGroupsExpanded, tooltip: { tip: allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups') } }))] }))] }));
|
|
@@ -17,11 +17,14 @@ function SubCategory({ groupId, service, showDescription, isMobile, dragDisabled
|
|
|
17
17
|
const subcategoryId = (0, innerLink_1.getSubCategoryId)(groupId, service.id);
|
|
18
18
|
const nestedGroupId = (0, innerLink_1.getNestedServiceGroupId)(groupId, service.id);
|
|
19
19
|
const nestedItems = (0, react_1.useMemo)(() => service.items?.filter(item => !item.hidden) ?? [], [service.items]);
|
|
20
|
+
const isExpandableEnabled = service.expandableEnabled ?? false;
|
|
20
21
|
// Раскрытие подкатегории — локальное uncontrolled состояние: наружу его пока не выводим.
|
|
21
22
|
const [isExpanded, setIsExpanded] = (0, react_1.useState)(subcategoryId);
|
|
22
23
|
const handleExpandedChange = (0, react_1.useCallback)(() => {
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
if (isExpandableEnabled) {
|
|
25
|
+
setIsExpanded(isExpanded ? undefined : subcategoryId);
|
|
26
|
+
}
|
|
27
|
+
}, [isExpanded, subcategoryId, isExpandableEnabled]);
|
|
25
28
|
return ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.subcategory, "data-test-id": `${constants_1.TEST_IDS.subcategory}-${service.id}`, children: (0, jsx_runtime_1.jsx)(accordion_1.Accordion, { selectionMode: 'single', expanded: isExpanded, onExpandedChange: handleExpandedChange, children: (0, jsx_runtime_1.jsx)(accordion_1.Accordion.CollapseBlockTertiary, { id: subcategoryId, showChevron: false, className: styles_module_scss_2.default.subcategoryAccordion, afterTitle: (0, jsx_runtime_1.jsx)(SubCategoryTitle_1.SubCategoryTitle, { groupId: groupId, service: service, expandable: {
|
|
26
29
|
value: Boolean(isExpanded),
|
|
27
30
|
onClick: handleExpandedChange,
|
|
@@ -39,7 +39,7 @@ function SubCategoryTitle({ groupId, service, showDescription: showDescriptionPr
|
|
|
39
39
|
],
|
|
40
40
|
});
|
|
41
41
|
if (expandable?.value) {
|
|
42
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitle, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)(uikit_product_title_clickable_1.TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: (0, utils_2.getLinkEmblem)(service), className: styles_module_scss_1.default.subcategoryTitleClickable, "data-test-id": titleTestId }), (0, jsx_runtime_1.jsx)(uikit_product_card_predefined_1.CardActionsSurface, { className: styles_module_scss_1.default.subcategoryTitleActions, actionsVisibility: 'always', tooltip: hasTooltip
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitle, "data-mobile": isMobile || undefined, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [(0, jsx_runtime_1.jsx)(uikit_product_title_clickable_1.TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: (0, utils_2.getLinkEmblem)(service), className: styles_module_scss_1.default.subcategoryTitleClickable, "data-test-id": titleTestId }), (0, jsx_runtime_1.jsx)(uikit_product_card_predefined_1.CardActionsSurface, { className: styles_module_scss_1.default.subcategoryTitleActions, actionsVisibility: 'always', actionsSize: isMobile ? 's' : 'm', tooltip: hasTooltip
|
|
43
43
|
? {
|
|
44
44
|
tip: service.description,
|
|
45
45
|
buttonRef: tooltipTriggerRef,
|
|
@@ -56,5 +56,9 @@ function SubCategoryTitle({ groupId, service, showDescription: showDescriptionPr
|
|
|
56
56
|
}
|
|
57
57
|
: undefined })] }), showDescription && ((0, jsx_runtime_1.jsx)(typography_1.Typography, { as: 'p', variant: 'body', size: 's', className: styles_module_scss_1.default.subcategoryDescription, "data-test-id": `${titleTestId}-description`, children: service.description }))] }));
|
|
58
58
|
}
|
|
59
|
-
return (
|
|
59
|
+
return (
|
|
60
|
+
// Карточка — ссылка `<a>`: клик по ней бы долетал до `onClick={toggleOpen}` заголовка
|
|
61
|
+
// родительского CollapseBlockTertiary (см. TODO там) и лишний раз переключал аккордеон.
|
|
62
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
63
|
+
(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.subcategoryTitleDraggable, onPointerDown: utils_1.stopEventPropagation, onClick: utils_1.stopEventPropagation, children: (0, jsx_runtime_1.jsx)(ServiceCard_1.DraggableServiceCard, { groupId: groupId, service: service, favorite: favorite, isMobile: isMobile, onServiceClick: onServiceClick, showDescription: showDescriptionProp, dragDisabled: dragDisabled, expandable: expandable }) }));
|
|
60
64
|
}
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
33
33
|
visibility:visible;
|
|
34
34
|
}
|
|
35
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
36
|
+
visibility:visible;
|
|
37
|
+
}
|
|
35
38
|
|
|
36
39
|
.subcategoryTitleRow{
|
|
37
40
|
display:flex;
|
|
@@ -36,6 +36,8 @@ export type InnerLink = {
|
|
|
36
36
|
badge?: CardServiceLightProps['promoTag'];
|
|
37
37
|
/** Разрешено ли добавление карточки в избранное. default=true - разрешено */
|
|
38
38
|
favoritesEnabled?: boolean;
|
|
39
|
+
/** Разрешено ли раскрытие карточки. default=false - Запрещено */
|
|
40
|
+
expandableEnabled?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Вложенные сервисы подкатегории.
|
|
41
43
|
*
|
package/dist/cjs/style.css
CHANGED
|
@@ -166,6 +166,11 @@
|
|
|
166
166
|
flex-shrink:0;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
.segmentControlSkeleton{
|
|
170
|
+
display:flex;
|
|
171
|
+
flex-shrink:0;
|
|
172
|
+
}
|
|
173
|
+
|
|
169
174
|
.actions{
|
|
170
175
|
display:flex;
|
|
171
176
|
flex-shrink:0;
|
|
@@ -214,6 +219,9 @@
|
|
|
214
219
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
215
220
|
visibility:visible;
|
|
216
221
|
}
|
|
222
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
223
|
+
visibility:visible;
|
|
224
|
+
}
|
|
217
225
|
|
|
218
226
|
.subcategoryTitleRow{
|
|
219
227
|
display:flex;
|
|
@@ -91,5 +91,5 @@ export function Content({ searchValue, search, rightTop, segments, searchGroups
|
|
|
91
91
|
appearance: 'neutral',
|
|
92
92
|
}, content: isSearching ? t('noDataFound') : t('noData'), "data-test-id": isSearching ? TEST_IDS.noDataFound : TEST_IDS.noData, "data-mobile": isMobile || undefined, className: styles.noData }));
|
|
93
93
|
})();
|
|
94
|
-
return (_jsxs(_Fragment, { children: [search, _jsxs("div", { className: cn(styles.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && (_jsxs(_Fragment, { children: [isMobile && rightTop, _jsx(ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
94
|
+
return (_jsxs(_Fragment, { children: [search, _jsxs("div", { className: cn(styles.content, className), "data-empty": (!loading && !hasCards) || undefined, children: [!isSearching && (_jsxs(_Fragment, { children: [isMobile && rightTop, _jsx(ContentToolbar, { segment: segmentId, onSegmentChange: setSegmentId, segmentItems: segmentItems, allGroupsExpanded: allGroupsExpanded, onToggleAllGroupsExpanded: handleToggleAllGroupsExpanded, preferences: preferences, isMobile: isMobile, loading: loading }), !isMobile && rightTop] })), cards, footer] })] }));
|
|
95
95
|
}
|
|
@@ -14,5 +14,7 @@ export type ContentToolbarProps = {
|
|
|
14
14
|
/** Настройки меню (модалка по кнопке). Не передано — кнопка настроек не отображается. */
|
|
15
15
|
preferences?: MainMenuPreferencesProps;
|
|
16
16
|
isMobile?: boolean;
|
|
17
|
+
/** Флаг загрузки данных — сегменты подгружаются с бэка, поэтому SegmentControl тоже уходит в скелетон. */
|
|
18
|
+
loading?: boolean;
|
|
17
19
|
};
|
|
18
|
-
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }: ContentToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button } from '@cloud-ru/ds-button';
|
|
3
3
|
import { CollapseVerticalSVG, ExpandVerticalSVG, SettingsSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
4
4
|
import { Modal } from '@cloud-ru/ds-modal';
|
|
5
5
|
import { SegmentControl } from '@cloud-ru/ds-segment-control';
|
|
6
|
+
import { Skeleton, SkeletonContext } from '@cloud-ru/ds-skeleton';
|
|
6
7
|
import { SwitchRow } from '@cloud-ru/ds-uikit-product-switch-row';
|
|
7
8
|
import { useValueControl } from '@cloud-ru/ds-utils';
|
|
8
9
|
import { startTransition } from 'react';
|
|
@@ -10,7 +11,7 @@ import { headerLocale } from '../../../../../../locale/index.js';
|
|
|
10
11
|
import { HeaderButton } from '../../../../../HeaderButton/index.js';
|
|
11
12
|
import { TEST_IDS } from '../../constants.js';
|
|
12
13
|
import styles from './styles.module.css';
|
|
13
|
-
export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, }) {
|
|
14
|
+
export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGroupsExpanded, onToggleAllGroupsExpanded, preferences, isMobile, loading, }) {
|
|
14
15
|
const { t } = headerLocale.useTranslations();
|
|
15
16
|
const [open = false, setOpen] = useValueControl({
|
|
16
17
|
value: preferences?.open,
|
|
@@ -22,7 +23,8 @@ export function ContentToolbar({ segment, onSegmentChange, segmentItems, allGrou
|
|
|
22
23
|
startTransition(() => preferences?.showDescription?.onChange(value));
|
|
23
24
|
};
|
|
24
25
|
const hasSegmentItems = segmentItems && segmentItems?.length > 0;
|
|
25
|
-
|
|
26
|
+
const segmentControlSkeletonSize = isMobile ? { width: '100%', height: 48 } : { width: 262, height: 32 };
|
|
27
|
+
return (_jsxs("div", { className: styles.root, "data-test-id": TEST_IDS.toolbar, children: [hasSegmentItems && (_jsx(_Fragment, { children: loading ? (_jsx(SkeletonContext.Provider, { value: true, children: _jsx("div", { className: styles.segmentControlSkeleton, "data-test-id": TEST_IDS.segmentControl, children: _jsx(Skeleton, { ...segmentControlSkeletonSize }) }) })) : (_jsx(SegmentControl, { size: 'm', outline: true, value: segment, onChange: onSegmentChange, className: styles.segmentControl, "data-test-id": TEST_IDS.segmentControl, items: segmentItems, width: isMobile ? 'full' : 'auto' })) })), (preferences || !isMobile) && !loading && (_jsxs("div", { className: styles.actions, children: [preferences && (_jsxs(_Fragment, { children: [_jsx(Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: _jsx(SettingsSVG, {}), "aria-label": t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsButton, onClick: openModal }), _jsx(Modal, { open: open, onClose: closeModal, title: t('menuSettingsTitle'), "data-test-id": TEST_IDS.settingsModal, cancelButton: {
|
|
26
28
|
label: t('close'),
|
|
27
29
|
onClick: closeModal,
|
|
28
30
|
}, content: _jsxs("div", { className: styles.settingsContent, children: [preferences.showGroupsColors && (_jsx(SwitchRow, { title: t('menuSettingsShowGroupsColors'), checked: preferences.showGroupsColors.value, onChange: preferences.showGroupsColors.onChange, "data-test-id": TEST_IDS.settingsShowGroupsColorsSwitch })), _jsx(SwitchRow, { title: t('menuSettingsShowDescription'), checked: preferences.showDescription.value, onChange: handleShowDescriptionChange, "data-test-id": TEST_IDS.settingsShowDescriptionSwitch })] }) })] })), !isMobile && (_jsx(HeaderButton, { icon: allGroupsExpanded ? _jsx(CollapseVerticalSVG, {}) : _jsx(ExpandVerticalSVG, {}), "aria-label": allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups'), "data-test-id": TEST_IDS.toggleAllGroups, onClick: onToggleAllGroupsExpanded, tooltip: { tip: allGroupsExpanded ? t('contentCollapseAllGroups') : t('contentExpandAllGroups') } }))] }))] }));
|
|
@@ -11,11 +11,14 @@ export function SubCategory({ groupId, service, showDescription, isMobile, dragD
|
|
|
11
11
|
const subcategoryId = getSubCategoryId(groupId, service.id);
|
|
12
12
|
const nestedGroupId = getNestedServiceGroupId(groupId, service.id);
|
|
13
13
|
const nestedItems = useMemo(() => service.items?.filter(item => !item.hidden) ?? [], [service.items]);
|
|
14
|
+
const isExpandableEnabled = service.expandableEnabled ?? false;
|
|
14
15
|
// Раскрытие подкатегории — локальное uncontrolled состояние: наружу его пока не выводим.
|
|
15
16
|
const [isExpanded, setIsExpanded] = useState(subcategoryId);
|
|
16
17
|
const handleExpandedChange = useCallback(() => {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
if (isExpandableEnabled) {
|
|
19
|
+
setIsExpanded(isExpanded ? undefined : subcategoryId);
|
|
20
|
+
}
|
|
21
|
+
}, [isExpanded, subcategoryId, isExpandableEnabled]);
|
|
19
22
|
return (_jsx("div", { className: styles.subcategory, "data-test-id": `${TEST_IDS.subcategory}-${service.id}`, children: _jsx(Accordion, { selectionMode: 'single', expanded: isExpanded, onExpandedChange: handleExpandedChange, children: _jsx(Accordion.CollapseBlockTertiary, { id: subcategoryId, showChevron: false, className: styles.subcategoryAccordion, afterTitle: _jsx(SubCategoryTitle, { groupId: groupId, service: service, expandable: {
|
|
20
23
|
value: Boolean(isExpanded),
|
|
21
24
|
onClick: handleExpandedChange,
|
|
@@ -33,7 +33,7 @@ export function SubCategoryTitle({ groupId, service, showDescription: showDescri
|
|
|
33
33
|
],
|
|
34
34
|
});
|
|
35
35
|
if (expandable?.value) {
|
|
36
|
-
return (_jsxs("div", { className: styles.subcategoryTitle, children: [_jsxs("div", { className: styles.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [_jsx(TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: getLinkEmblem(service), className: styles.subcategoryTitleClickable, "data-test-id": titleTestId }), _jsx(CardActionsSurface, { className: styles.subcategoryTitleActions, actionsVisibility: 'always', tooltip: hasTooltip
|
|
36
|
+
return (_jsxs("div", { className: styles.subcategoryTitle, "data-mobile": isMobile || undefined, children: [_jsxs("div", { className: styles.subcategoryTitleRow, onKeyDown: handleKeyDown, children: [_jsx(TitleClickable, { as: 'a', href: service.href, onClick: handleServiceClick, innerRef: titleRef, title: service.label, icon: getLinkEmblem(service), className: styles.subcategoryTitleClickable, "data-test-id": titleTestId }), _jsx(CardActionsSurface, { className: styles.subcategoryTitleActions, actionsVisibility: 'always', actionsSize: isMobile ? 's' : 'm', tooltip: hasTooltip
|
|
37
37
|
? {
|
|
38
38
|
tip: service.description,
|
|
39
39
|
buttonRef: tooltipTriggerRef,
|
|
@@ -50,5 +50,9 @@ export function SubCategoryTitle({ groupId, service, showDescription: showDescri
|
|
|
50
50
|
}
|
|
51
51
|
: undefined })] }), showDescription && (_jsx(Typography, { as: 'p', variant: 'body', size: 's', className: styles.subcategoryDescription, "data-test-id": `${titleTestId}-description`, children: service.description }))] }));
|
|
52
52
|
}
|
|
53
|
-
return (
|
|
53
|
+
return (
|
|
54
|
+
// Карточка — ссылка `<a>`: клик по ней бы долетал до `onClick={toggleOpen}` заголовка
|
|
55
|
+
// родительского CollapseBlockTertiary (см. TODO там) и лишний раз переключал аккордеон.
|
|
56
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
57
|
+
_jsx("div", { className: styles.subcategoryTitleDraggable, onPointerDown: stopEventPropagation, onClick: stopEventPropagation, children: _jsx(DraggableServiceCard, { groupId: groupId, service: service, favorite: favorite, isMobile: isMobile, onServiceClick: onServiceClick, showDescription: showDescriptionProp, dragDisabled: dragDisabled, expandable: expandable }) }));
|
|
54
58
|
}
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
33
33
|
visibility:visible;
|
|
34
34
|
}
|
|
35
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
36
|
+
visibility:visible;
|
|
37
|
+
}
|
|
35
38
|
|
|
36
39
|
.subcategoryTitleRow{
|
|
37
40
|
display:flex;
|
|
@@ -36,6 +36,8 @@ export type InnerLink = {
|
|
|
36
36
|
badge?: CardServiceLightProps['promoTag'];
|
|
37
37
|
/** Разрешено ли добавление карточки в избранное. default=true - разрешено */
|
|
38
38
|
favoritesEnabled?: boolean;
|
|
39
|
+
/** Разрешено ли раскрытие карточки. default=false - Запрещено */
|
|
40
|
+
expandableEnabled?: boolean;
|
|
39
41
|
/**
|
|
40
42
|
* Вложенные сервисы подкатегории.
|
|
41
43
|
*
|
package/dist/esm/style.css
CHANGED
|
@@ -166,6 +166,11 @@
|
|
|
166
166
|
flex-shrink:0;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
.segmentControlSkeleton{
|
|
170
|
+
display:flex;
|
|
171
|
+
flex-shrink:0;
|
|
172
|
+
}
|
|
173
|
+
|
|
169
174
|
.actions{
|
|
170
175
|
display:flex;
|
|
171
176
|
flex-shrink:0;
|
|
@@ -214,6 +219,9 @@
|
|
|
214
219
|
.subcategoryTitle:hover .subcategoryTitleActions, .subcategoryTitle:focus-within .subcategoryTitleActions{
|
|
215
220
|
visibility:visible;
|
|
216
221
|
}
|
|
222
|
+
.subcategoryTitle[data-mobile] .subcategoryTitleActions{
|
|
223
|
+
visibility:visible;
|
|
224
|
+
}
|
|
217
225
|
|
|
218
226
|
.subcategoryTitleRow{
|
|
219
227
|
display:flex;
|