@cloud-ru/ds-uikit-product-header 2.1.8-preview-cb48d4cb.0 → 2.1.8-preview-448a8de1.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/dist/cjs/components/ListCustom/helperComponents/ContentWrapperCustom/ContentWrapperCustom.d.ts +10 -26
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/ListItemCustom.js +3 -4
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/index.d.ts +0 -1
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/index.js +0 -1
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/types.d.ts +0 -1
- package/dist/cjs/components/MainMenu/helperComponents/Favorites/Favorites.js +1 -1
- package/dist/cjs/components/UserMenu/UserMenu.js +1 -1
- package/dist/cjs/components/UserMenu/hooks/useProfileItem.d.ts +3 -1
- package/dist/cjs/components/UserMenu/hooks/useProfileItem.js +12 -5
- package/dist/cjs/components/UserMenu/hooks/useUserMenuItems.js +1 -1
- package/dist/esm/components/ListCustom/helperComponents/ContentWrapperCustom/ContentWrapperCustom.d.ts +10 -26
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/ListItemCustom.js +4 -5
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/index.d.ts +0 -1
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/index.js +0 -1
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/types.d.ts +0 -1
- package/dist/esm/components/MainMenu/helperComponents/Favorites/Favorites.js +1 -1
- package/dist/esm/components/UserMenu/UserMenu.js +1 -1
- package/dist/esm/components/UserMenu/hooks/useProfileItem.d.ts +3 -1
- package/dist/esm/components/UserMenu/hooks/useProfileItem.js +12 -5
- package/dist/esm/components/UserMenu/hooks/useUserMenuItems.js +1 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/src/components/ListCustom/helperComponents/ContentWrapperCustom/ContentWrapperCustom.tsx +20 -32
- package/src/components/ListCustom/helperComponents/ListItemCustom/ListItemCustom.tsx +4 -5
- package/src/components/ListCustom/helperComponents/ListItemCustom/index.ts +0 -1
- package/src/components/ListCustom/helperComponents/ListItemCustom/types.ts +0 -2
- package/src/components/ListCustom/specs/readme.md +16 -12
- package/src/components/MainMenu/helperComponents/Favorites/Favorites.tsx +3 -3
- package/src/components/UserMenu/UserMenu.tsx +3 -3
- package/src/components/UserMenu/hooks/useProfileItem.tsx +15 -5
- package/src/components/UserMenu/hooks/useUserMenuItems.ts +1 -1
- package/src/components/UserMenu/styles.module.scss +2 -2
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/constants.d.ts +0 -6
- package/dist/cjs/components/ListCustom/helperComponents/ListItemCustom/constants.js +0 -6
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/constants.d.ts +0 -6
- package/dist/esm/components/ListCustom/helperComponents/ListItemCustom/constants.js +0 -3
- package/src/components/ListCustom/helperComponents/ListItemCustom/constants.ts +0 -4
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GroupItemRenderProps, ItemContentProps, ItemRenderProps } from '@cloud-ru/ds-list';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
afterContent?: ReactNode;
|
|
13
|
-
/** Заголовок строки / группы */
|
|
14
|
-
label?: string | number;
|
|
15
|
-
/** Аннотация справа от label */
|
|
16
|
-
caption?: string;
|
|
17
|
-
/** Описание под label */
|
|
18
|
-
description?: string;
|
|
19
|
-
/** Настройки усечения длинных строк */
|
|
20
|
-
truncate?: TruncateProps;
|
|
21
|
-
/** Готовый узел вместо структурного текста (результат `contentRender` и т.п.) */
|
|
22
|
-
contentNode?: ReactNode;
|
|
3
|
+
/**
|
|
4
|
+
* Приватный слот before + текст + after.
|
|
5
|
+
* Текстовые поля и truncate — из `ItemContentProps`; слоты строки — из `ItemRenderProps`;
|
|
6
|
+
* `groupVariant` — из `GroupItemRenderProps`. Своё: `layout`, `selectButton`.
|
|
7
|
+
* `label` опционален: при `contentNode` структурный текст не собирается.
|
|
8
|
+
*/
|
|
9
|
+
export type ContentWrapperCustomProps = Partial<Pick<ItemContentProps, 'label'>> & Pick<ItemContentProps, 'caption' | 'description' | 'truncate' | 'disabled' | 'className'> & Pick<ItemRenderProps, 'beforeContent' | 'afterContent'> & Pick<GroupItemRenderProps, 'groupVariant'> & {
|
|
10
|
+
/** Готовый узел вместо структурного текста; у группы обычно не задаётся */
|
|
11
|
+
contentNode?: ItemRenderProps['contentNode'];
|
|
23
12
|
/** Слот справа в групповом заголовке (bulk select) */
|
|
24
13
|
selectButton?: ReactNode;
|
|
25
14
|
/** Раскладка: строка списка или заголовок группы */
|
|
26
15
|
layout?: 'item' | 'group';
|
|
27
|
-
/** Визуальный стиль подписи группы */
|
|
28
|
-
groupVariant?: 'subtitle' | 'subtitleTertiary';
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
className?: string;
|
|
31
16
|
};
|
|
32
17
|
export declare function ContentWrapperCustom({ beforeContent, afterContent, label, caption, description, truncate: truncateProp, contentNode, selectButton, layout, groupVariant, disabled, className, }: ContentWrapperCustomProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
-
export {};
|
|
@@ -9,7 +9,6 @@ const list_1 = require("@cloud-ru/ds-list");
|
|
|
9
9
|
const toggles_1 = require("@cloud-ru/ds-toggles");
|
|
10
10
|
const classnames_1 = __importDefault(require("classnames"));
|
|
11
11
|
const ContentWrapperCustom_1 = require("../ContentWrapperCustom");
|
|
12
|
-
const constants_1 = require("./constants");
|
|
13
12
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
14
13
|
function resolveStructuredContent(content, contentFromRender) {
|
|
15
14
|
if (contentFromRender) {
|
|
@@ -27,10 +26,10 @@ function resolveStructuredContent(content, contentFromRender) {
|
|
|
27
26
|
* Кастомная оболочка строки `List`/`Droplist` (Figma `listItemCustom`).
|
|
28
27
|
* Маркер (single) и чекбокс (multiple) рисуются внутри по `selectionMode` / `checked` / `disabled`.
|
|
29
28
|
*/
|
|
30
|
-
function ListItemCustom({ selectionMode =
|
|
29
|
+
function ListItemCustom({ selectionMode = list_1.MODE.None, checked = false, disabled = false, content, contentNode, contentFromRender, beforeContent, afterContent, dragHandle, switchControl, expandIcon, onExpandIconClick, inactive, open, isParentNode, level = 0, className, itemRef, tabIndex = -1, style, onClick, onMouseDown, onKeyDown, onFocus, 'data-test-id': dataTestId, }) {
|
|
31
30
|
const structuredContent = resolveStructuredContent(content, contentFromRender);
|
|
32
|
-
const isSingle = selectionMode ===
|
|
33
|
-
const isMultiple = selectionMode ===
|
|
31
|
+
const isSingle = selectionMode === list_1.MODE.Single;
|
|
32
|
+
const isMultiple = selectionMode === list_1.MODE.Multiple;
|
|
34
33
|
// Figma: activated-подложка только у single + checked + !disabled; multiple всегда emptyNeutral.
|
|
35
34
|
const stateLayerState = isSingle && checked && !disabled && !isParentNode && !switchControl
|
|
36
35
|
? 'activatedOnBackground'
|
|
@@ -15,5 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./ListItemCustom"), exports);
|
|
18
|
-
__exportStar(require("./constants"), exports);
|
|
19
18
|
__exportStar(require("./types"), exports);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ItemRenderProps, Mode } from '@cloud-ru/ds-list';
|
|
2
|
-
export type SelectionMode = Mode;
|
|
3
2
|
/**
|
|
4
3
|
* Пропы оболочки. Совместимы с `ItemRenderProps` списка (адаптер — spread).
|
|
5
4
|
* Для Playground часть полей опциональна: `contentNode` / `selectionMode` / `size` / `tabIndex` / `level`.
|
|
@@ -43,5 +43,5 @@ function Favorites({ favorite, servicesById, headerClassName, isMobile }) {
|
|
|
43
43
|
favorite.onFavoriteServiceClick?.(service.id, event);
|
|
44
44
|
service.onClick(event);
|
|
45
45
|
});
|
|
46
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.root, "data-test-id": constants_1.FAVORITES_TEST_IDS.root, children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.header, headerClassName), "data-test-id": constants_1.FAVORITES_TEST_IDS.header, children: [(0, jsx_runtime_1.jsx)(segment_control_1.SegmentControl, { size: 'm', width: segment_control_1.WIDTH.Full, value: segment, onChange: setSegment, className: styles_module_scss_1.default.segmentControl, "data-test-id": constants_1.FAVORITES_TEST_IDS.segmentControl, items: segmentControlItems }), favorite.actions && ((0, jsx_runtime_1.jsx)(list_1.Droplist, { ...favorite.actions, size: 's', closeDroplistOnItemClick: true, itemRender: ListCustom_1.renderListItemCustom, groupItemRender: ListCustom_1.renderListItemGroupCustom, children: (0, jsx_runtime_1.jsx)(button_1.Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: (0, jsx_runtime_1.jsx)(system_1.KebabSVG, { size: 24 }), "data-test-id": constants_1.FAVORITES_TEST_IDS.settingsButton, disabled: loading }) }))] }), loading ? ((0, jsx_runtime_1.jsx)(components_1.FavoritesItemsSkeleton, {})) : ((0, jsx_runtime_1.jsx)(components_1.Content, { isMobile: isMobile, favoriteIds: favorite.value, onFavoriteChange: favorite.onChange, favoriteItems: favoriteItems, recentItems: recentItems, segment: resolvedSegment, setSegment: setSegment, onFavoriteServiceClick: handleFavoriteServiceClick, onRecentServiceClick: handleRecentServiceClick }))] }));
|
|
46
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.root, "data-test-id": constants_1.FAVORITES_TEST_IDS.root, children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.header, headerClassName), "data-test-id": constants_1.FAVORITES_TEST_IDS.header, children: [(0, jsx_runtime_1.jsx)(segment_control_1.SegmentControl, { size: 'm', width: segment_control_1.WIDTH.Full, value: segment, onChange: setSegment, className: styles_module_scss_1.default.segmentControl, "data-test-id": constants_1.FAVORITES_TEST_IDS.segmentControl, items: segmentControlItems }), favorite.actions && ((0, jsx_runtime_1.jsx)(list_1.Droplist, { ...favorite.actions, size: isMobile ? 'm' : 's', closeDroplistOnItemClick: true, itemRender: isMobile ? undefined : ListCustom_1.renderListItemCustom, groupItemRender: isMobile ? undefined : ListCustom_1.renderListItemGroupCustom, children: (0, jsx_runtime_1.jsx)(button_1.Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: (0, jsx_runtime_1.jsx)(system_1.KebabSVG, { size: 24 }), "data-test-id": constants_1.FAVORITES_TEST_IDS.settingsButton, disabled: loading }) }))] }), loading ? ((0, jsx_runtime_1.jsx)(components_1.FavoritesItemsSkeleton, {})) : ((0, jsx_runtime_1.jsx)(components_1.Content, { isMobile: isMobile, favoriteIds: favorite.value, onFavoriteChange: favorite.onChange, favoriteItems: favoriteItems, recentItems: recentItems, segment: resolvedSegment, setSegment: setSegment, onFavoriteServiceClick: handleFavoriteServiceClick, onRecentServiceClick: handleRecentServiceClick }))] }));
|
|
47
47
|
}
|
|
@@ -49,5 +49,5 @@ function UserMenu({ profile = {}, open: openProp, setOpen: setOpenProp, onLogout
|
|
|
49
49
|
appearance: 'primary',
|
|
50
50
|
}
|
|
51
51
|
: undefined, "data-test-id": constants_1.TEST_IDS.userMenu.button, icon: (0, jsx_runtime_1.jsx)(avatar_1.Avatar, { appearance: 'red', size: 's', name: fullName, showTwoSymbols: true }), "data-pressed": open })), [fullName, inviteCount, onClick, open, setOpen, isMobile, triggerTooltip]);
|
|
52
|
-
return ((0, jsx_runtime_1.jsx)(list_1.Droplist, { open: open, onOpenChange: setOpen, size: 's', selection: SELECTION_STUB, pinTop: pinTop, items: menuItems, pinBottom: pinBottom, scroll: !isMobile, trigger: 'click', placement: 'bottom-end', className: styles_module_scss_1.default.userMenuDroplist, closeOnPopstate: true, "data-test-id": constants_1.TEST_IDS.userMenu.root, label: t('user'), snapPoints: list_1.SNAP_POINTS_PRESET.full, withDividers: false, triggerClassName: styles_module_scss_1.default.userMenuDroplistTrigger, itemRender: ListCustom_1.renderListItemCustom, groupItemRender: ListCustom_1.renderListItemGroupCustom, children: trigger }));
|
|
52
|
+
return ((0, jsx_runtime_1.jsx)(list_1.Droplist, { open: open, onOpenChange: setOpen, size: isMobile ? 'm' : 's', selection: SELECTION_STUB, pinTop: pinTop, items: menuItems, pinBottom: pinBottom, scroll: !isMobile, trigger: 'click', placement: 'bottom-end', className: styles_module_scss_1.default.userMenuDroplist, closeOnPopstate: true, "data-test-id": constants_1.TEST_IDS.userMenu.root, label: t('user'), snapPoints: list_1.SNAP_POINTS_PRESET.full, withDividers: false, triggerClassName: styles_module_scss_1.default.userMenuDroplistTrigger, itemRender: isMobile ? undefined : ListCustom_1.renderListItemCustom, groupItemRender: isMobile ? undefined : ListCustom_1.renderListItemGroupCustom, children: trigger }));
|
|
53
53
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { BaseItemProps } from '@cloud-ru/ds-list';
|
|
2
2
|
import { UserProfileProps } from '../types';
|
|
3
|
-
export declare function useProfileItem({ fullName, email, itemWrapRender, onClick, }: UserProfileProps
|
|
3
|
+
export declare function useProfileItem({ fullName, email, itemWrapRender, onClick, isMobile, }: UserProfileProps & {
|
|
4
|
+
isMobile?: boolean;
|
|
5
|
+
}): BaseItemProps;
|
|
@@ -10,16 +10,23 @@ const system_1 = require("@cloud-ru/ds-icons/interface/system");
|
|
|
10
10
|
const truncate_string_1 = require("@cloud-ru/ds-truncate-string");
|
|
11
11
|
const react_1 = require("react");
|
|
12
12
|
const styles_module_scss_1 = __importDefault(require('../styles.module.css'));
|
|
13
|
-
function useProfileItem({ fullName = '', email = '', itemWrapRender, onClick, }) {
|
|
13
|
+
function useProfileItem({ fullName = '', email = '', itemWrapRender, onClick, isMobile, }) {
|
|
14
14
|
return (0, react_1.useMemo)(() => ({
|
|
15
|
-
//
|
|
16
|
-
// а `className` айтема на `.label` не действует.
|
|
17
|
-
|
|
15
|
+
// Desktop + ListCustom: ReactNode — иначе ContentWrapperCustom рисует label с
|
|
16
|
+
// `regular-body-s`, а `className` айтема на `.label` не действует.
|
|
17
|
+
// Mobile (size=m, без ListCustom): структурный content → дефолтный ItemContent.
|
|
18
|
+
content: isMobile ? ({
|
|
19
|
+
label: fullName,
|
|
20
|
+
description: email,
|
|
21
|
+
truncate: {
|
|
22
|
+
description: 1,
|
|
23
|
+
},
|
|
24
|
+
}) : ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.userItemContent, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.userItemHeadline, children: (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, { className: styles_module_scss_1.default.userItemLabel, text: fullName, maxLines: 1 }) }), email ? (0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, { className: styles_module_scss_1.default.userItemDescription, text: email, maxLines: 1 }) : null] })),
|
|
18
25
|
onClick,
|
|
19
26
|
beforeContent: (0, jsx_runtime_1.jsx)(avatar_1.Avatar, { appearance: 'red', size: 's', name: fullName, showTwoSymbols: true }),
|
|
20
27
|
afterContent: (0, jsx_runtime_1.jsx)(system_1.SettingsSVG, { className: styles_module_scss_1.default.profileSettingsIcon }),
|
|
21
28
|
itemWrapRender,
|
|
22
29
|
id: 'header__user-menu__button',
|
|
23
30
|
'data-test-id': 'header__user-menu__manage-profile',
|
|
24
|
-
}), [email, fullName, itemWrapRender, onClick]);
|
|
31
|
+
}), [email, fullName, isMobile, itemWrapRender, onClick]);
|
|
25
32
|
}
|
|
@@ -14,7 +14,7 @@ const DIVIDER_ITEM = {
|
|
|
14
14
|
items: [],
|
|
15
15
|
};
|
|
16
16
|
function useUserMenuItems({ profile, theme, onLogout, topItems = emptyArray_1.EMPTY_ARRAY, organizationItems = emptyArray_1.EMPTY_ARRAY, bottomItems = emptyArray_1.EMPTY_ARRAY, isMobile, onClose, settingItems = emptyArray_1.EMPTY_ARRAY, }) {
|
|
17
|
-
const profileItem = (0, useProfileItem_1.useProfileItem)(profile);
|
|
17
|
+
const profileItem = (0, useProfileItem_1.useProfileItem)({ ...profile, isMobile });
|
|
18
18
|
const themeItem = (0, useThemeItem_1.useThemeItem)({ ...(theme || {}), isMobile, onClose });
|
|
19
19
|
const logoutItem = (0, useLogoutItem_1.useLogoutItem)({ onLogout });
|
|
20
20
|
return (0, react_1.useMemo)(() => {
|
|
@@ -1,33 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GroupItemRenderProps, ItemContentProps, ItemRenderProps } from '@cloud-ru/ds-list';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
afterContent?: ReactNode;
|
|
13
|
-
/** Заголовок строки / группы */
|
|
14
|
-
label?: string | number;
|
|
15
|
-
/** Аннотация справа от label */
|
|
16
|
-
caption?: string;
|
|
17
|
-
/** Описание под label */
|
|
18
|
-
description?: string;
|
|
19
|
-
/** Настройки усечения длинных строк */
|
|
20
|
-
truncate?: TruncateProps;
|
|
21
|
-
/** Готовый узел вместо структурного текста (результат `contentRender` и т.п.) */
|
|
22
|
-
contentNode?: ReactNode;
|
|
3
|
+
/**
|
|
4
|
+
* Приватный слот before + текст + after.
|
|
5
|
+
* Текстовые поля и truncate — из `ItemContentProps`; слоты строки — из `ItemRenderProps`;
|
|
6
|
+
* `groupVariant` — из `GroupItemRenderProps`. Своё: `layout`, `selectButton`.
|
|
7
|
+
* `label` опционален: при `contentNode` структурный текст не собирается.
|
|
8
|
+
*/
|
|
9
|
+
export type ContentWrapperCustomProps = Partial<Pick<ItemContentProps, 'label'>> & Pick<ItemContentProps, 'caption' | 'description' | 'truncate' | 'disabled' | 'className'> & Pick<ItemRenderProps, 'beforeContent' | 'afterContent'> & Pick<GroupItemRenderProps, 'groupVariant'> & {
|
|
10
|
+
/** Готовый узел вместо структурного текста; у группы обычно не задаётся */
|
|
11
|
+
contentNode?: ItemRenderProps['contentNode'];
|
|
23
12
|
/** Слот справа в групповом заголовке (bulk select) */
|
|
24
13
|
selectButton?: ReactNode;
|
|
25
14
|
/** Раскладка: строка списка или заголовок группы */
|
|
26
15
|
layout?: 'item' | 'group';
|
|
27
|
-
/** Визуальный стиль подписи группы */
|
|
28
|
-
groupVariant?: 'subtitle' | 'subtitleTertiary';
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
className?: string;
|
|
31
16
|
};
|
|
32
17
|
export declare function ContentWrapperCustom({ beforeContent, afterContent, label, caption, description, truncate: truncateProp, contentNode, selectButton, layout, groupVariant, disabled, className, }: ContentWrapperCustomProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
-
export {};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { isContentItem, isPrimitiveContent, TEST_IDS } from '@cloud-ru/ds-list';
|
|
2
|
+
import { isContentItem, isPrimitiveContent, MODE, TEST_IDS } from '@cloud-ru/ds-list';
|
|
3
3
|
import { Checkbox } from '@cloud-ru/ds-toggles';
|
|
4
4
|
import cn from 'classnames';
|
|
5
5
|
import { ContentWrapperCustom } from '../ContentWrapperCustom/index.js';
|
|
6
|
-
import { SELECTION_MODE } from './constants.js';
|
|
7
6
|
import styles from './styles.module.css';
|
|
8
7
|
function resolveStructuredContent(content, contentFromRender) {
|
|
9
8
|
if (contentFromRender) {
|
|
@@ -21,10 +20,10 @@ function resolveStructuredContent(content, contentFromRender) {
|
|
|
21
20
|
* Кастомная оболочка строки `List`/`Droplist` (Figma `listItemCustom`).
|
|
22
21
|
* Маркер (single) и чекбокс (multiple) рисуются внутри по `selectionMode` / `checked` / `disabled`.
|
|
23
22
|
*/
|
|
24
|
-
export function ListItemCustom({ selectionMode =
|
|
23
|
+
export function ListItemCustom({ selectionMode = MODE.None, checked = false, disabled = false, content, contentNode, contentFromRender, beforeContent, afterContent, dragHandle, switchControl, expandIcon, onExpandIconClick, inactive, open, isParentNode, level = 0, className, itemRef, tabIndex = -1, style, onClick, onMouseDown, onKeyDown, onFocus, 'data-test-id': dataTestId, }) {
|
|
25
24
|
const structuredContent = resolveStructuredContent(content, contentFromRender);
|
|
26
|
-
const isSingle = selectionMode ===
|
|
27
|
-
const isMultiple = selectionMode ===
|
|
25
|
+
const isSingle = selectionMode === MODE.Single;
|
|
26
|
+
const isMultiple = selectionMode === MODE.Multiple;
|
|
28
27
|
// Figma: activated-подложка только у single + checked + !disabled; multiple всегда emptyNeutral.
|
|
29
28
|
const stateLayerState = isSingle && checked && !disabled && !isParentNode && !switchControl
|
|
30
29
|
? 'activatedOnBackground'
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ItemRenderProps, Mode } from '@cloud-ru/ds-list';
|
|
2
|
-
export type SelectionMode = Mode;
|
|
3
2
|
/**
|
|
4
3
|
* Пропы оболочки. Совместимы с `ItemRenderProps` списка (адаптер — spread).
|
|
5
4
|
* Для Playground часть полей опциональна: `contentNode` / `selectionMode` / `size` / `tabIndex` / `level`.
|
|
@@ -37,5 +37,5 @@ export function Favorites({ favorite, servicesById, headerClassName, isMobile })
|
|
|
37
37
|
favorite.onFavoriteServiceClick?.(service.id, event);
|
|
38
38
|
service.onClick(event);
|
|
39
39
|
});
|
|
40
|
-
return (_jsxs("div", { className: styles.root, "data-test-id": FAVORITES_TEST_IDS.root, children: [_jsxs("div", { className: cn(styles.header, headerClassName), "data-test-id": FAVORITES_TEST_IDS.header, children: [_jsx(SegmentControl, { size: 'm', width: WIDTH.Full, value: segment, onChange: setSegment, className: styles.segmentControl, "data-test-id": FAVORITES_TEST_IDS.segmentControl, items: segmentControlItems }), favorite.actions && (_jsx(Droplist, { ...favorite.actions, size: 's', closeDroplistOnItemClick: true, itemRender: renderListItemCustom, groupItemRender: renderListItemGroupCustom, children: _jsx(Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: _jsx(KebabSVG, { size: 24 }), "data-test-id": FAVORITES_TEST_IDS.settingsButton, disabled: loading }) }))] }), loading ? (_jsx(FavoritesItemsSkeleton, {})) : (_jsx(Content, { isMobile: isMobile, favoriteIds: favorite.value, onFavoriteChange: favorite.onChange, favoriteItems: favoriteItems, recentItems: recentItems, segment: resolvedSegment, setSegment: setSegment, onFavoriteServiceClick: handleFavoriteServiceClick, onRecentServiceClick: handleRecentServiceClick }))] }));
|
|
40
|
+
return (_jsxs("div", { className: styles.root, "data-test-id": FAVORITES_TEST_IDS.root, children: [_jsxs("div", { className: cn(styles.header, headerClassName), "data-test-id": FAVORITES_TEST_IDS.header, children: [_jsx(SegmentControl, { size: 'm', width: WIDTH.Full, value: segment, onChange: setSegment, className: styles.segmentControl, "data-test-id": FAVORITES_TEST_IDS.segmentControl, items: segmentControlItems }), favorite.actions && (_jsx(Droplist, { ...favorite.actions, size: isMobile ? 'm' : 's', closeDroplistOnItemClick: true, itemRender: isMobile ? undefined : renderListItemCustom, groupItemRender: isMobile ? undefined : renderListItemGroupCustom, children: _jsx(Button, { view: 'simple', size: 'm', appearance: 'neutral', icon: _jsx(KebabSVG, { size: 24 }), "data-test-id": FAVORITES_TEST_IDS.settingsButton, disabled: loading }) }))] }), loading ? (_jsx(FavoritesItemsSkeleton, {})) : (_jsx(Content, { isMobile: isMobile, favoriteIds: favorite.value, onFavoriteChange: favorite.onChange, favoriteItems: favoriteItems, recentItems: recentItems, segment: resolvedSegment, setSegment: setSegment, onFavoriteServiceClick: handleFavoriteServiceClick, onRecentServiceClick: handleRecentServiceClick }))] }));
|
|
41
41
|
}
|
|
@@ -43,5 +43,5 @@ export function UserMenu({ profile = {}, open: openProp, setOpen: setOpenProp, o
|
|
|
43
43
|
appearance: 'primary',
|
|
44
44
|
}
|
|
45
45
|
: undefined, "data-test-id": TEST_IDS.userMenu.button, icon: _jsx(Avatar, { appearance: 'red', size: 's', name: fullName, showTwoSymbols: true }), "data-pressed": open })), [fullName, inviteCount, onClick, open, setOpen, isMobile, triggerTooltip]);
|
|
46
|
-
return (_jsx(Droplist, { open: open, onOpenChange: setOpen, size: 's', selection: SELECTION_STUB, pinTop: pinTop, items: menuItems, pinBottom: pinBottom, scroll: !isMobile, trigger: 'click', placement: 'bottom-end', className: styles.userMenuDroplist, closeOnPopstate: true, "data-test-id": TEST_IDS.userMenu.root, label: t('user'), snapPoints: SNAP_POINTS_PRESET.full, withDividers: false, triggerClassName: styles.userMenuDroplistTrigger, itemRender: renderListItemCustom, groupItemRender: renderListItemGroupCustom, children: trigger }));
|
|
46
|
+
return (_jsx(Droplist, { open: open, onOpenChange: setOpen, size: isMobile ? 'm' : 's', selection: SELECTION_STUB, pinTop: pinTop, items: menuItems, pinBottom: pinBottom, scroll: !isMobile, trigger: 'click', placement: 'bottom-end', className: styles.userMenuDroplist, closeOnPopstate: true, "data-test-id": TEST_IDS.userMenu.root, label: t('user'), snapPoints: SNAP_POINTS_PRESET.full, withDividers: false, triggerClassName: styles.userMenuDroplistTrigger, itemRender: isMobile ? undefined : renderListItemCustom, groupItemRender: isMobile ? undefined : renderListItemGroupCustom, children: trigger }));
|
|
47
47
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { BaseItemProps } from '@cloud-ru/ds-list';
|
|
2
2
|
import { UserProfileProps } from '../types.js';
|
|
3
|
-
export declare function useProfileItem({ fullName, email, itemWrapRender, onClick, }: UserProfileProps
|
|
3
|
+
export declare function useProfileItem({ fullName, email, itemWrapRender, onClick, isMobile, }: UserProfileProps & {
|
|
4
|
+
isMobile?: boolean;
|
|
5
|
+
}): BaseItemProps;
|
|
@@ -4,16 +4,23 @@ import { SettingsSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
|
4
4
|
import { TruncateString } from '@cloud-ru/ds-truncate-string';
|
|
5
5
|
import { useMemo } from 'react';
|
|
6
6
|
import styles from '../styles.module.css';
|
|
7
|
-
export function useProfileItem({ fullName = '', email = '', itemWrapRender, onClick, }) {
|
|
7
|
+
export function useProfileItem({ fullName = '', email = '', itemWrapRender, onClick, isMobile, }) {
|
|
8
8
|
return useMemo(() => ({
|
|
9
|
-
//
|
|
10
|
-
// а `className` айтема на `.label` не действует.
|
|
11
|
-
|
|
9
|
+
// Desktop + ListCustom: ReactNode — иначе ContentWrapperCustom рисует label с
|
|
10
|
+
// `regular-body-s`, а `className` айтема на `.label` не действует.
|
|
11
|
+
// Mobile (size=m, без ListCustom): структурный content → дефолтный ItemContent.
|
|
12
|
+
content: isMobile ? ({
|
|
13
|
+
label: fullName,
|
|
14
|
+
description: email,
|
|
15
|
+
truncate: {
|
|
16
|
+
description: 1,
|
|
17
|
+
},
|
|
18
|
+
}) : (_jsxs("div", { className: styles.userItemContent, children: [_jsx("div", { className: styles.userItemHeadline, children: _jsx(TruncateString, { className: styles.userItemLabel, text: fullName, maxLines: 1 }) }), email ? _jsx(TruncateString, { className: styles.userItemDescription, text: email, maxLines: 1 }) : null] })),
|
|
12
19
|
onClick,
|
|
13
20
|
beforeContent: _jsx(Avatar, { appearance: 'red', size: 's', name: fullName, showTwoSymbols: true }),
|
|
14
21
|
afterContent: _jsx(SettingsSVG, { className: styles.profileSettingsIcon }),
|
|
15
22
|
itemWrapRender,
|
|
16
23
|
id: 'header__user-menu__button',
|
|
17
24
|
'data-test-id': 'header__user-menu__manage-profile',
|
|
18
|
-
}), [email, fullName, itemWrapRender, onClick]);
|
|
25
|
+
}), [email, fullName, isMobile, itemWrapRender, onClick]);
|
|
19
26
|
}
|
|
@@ -11,7 +11,7 @@ const DIVIDER_ITEM = {
|
|
|
11
11
|
items: [],
|
|
12
12
|
};
|
|
13
13
|
export function useUserMenuItems({ profile, theme, onLogout, topItems = EMPTY_ARRAY, organizationItems = EMPTY_ARRAY, bottomItems = EMPTY_ARRAY, isMobile, onClose, settingItems = EMPTY_ARRAY, }) {
|
|
14
|
-
const profileItem = useProfileItem(profile);
|
|
14
|
+
const profileItem = useProfileItem({ ...profile, isMobile });
|
|
15
15
|
const themeItem = useThemeItem({ ...(theme || {}), isMobile, onClose });
|
|
16
16
|
const logoutItem = useLogoutItem({ onLogout });
|
|
17
17
|
return useMemo(() => {
|