@cloud-ru/ds-uikit-product-header-legacy 0.1.4 → 0.1.6

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 CHANGED
@@ -7,12 +7,12 @@
7
7
  ## Когда использовать
8
8
 
9
9
  - Нужна обратимо совместимая шапка и меню навигации старого кабинета на стеке `@ds/*`.
10
- - Собирается MainMenu с селектором платформ и категориями сервисов: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer.
10
+ - Собирается MainMenu с селектором платформ и категориями сервисов: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer (или новое bottom-sheet-меню через `customMobileMenu`).
11
11
 
12
12
  Когда **не** нужен пакет:
13
13
 
14
14
  - Новая продуктовая шапка без legacy-контрактов:
15
- - используйте актуальные layout/header-пакеты Product UI Kit.
15
+ - используйте **`@cloud-ru/ds-uikit-product-header`**.
16
16
  - Отдельная карточка сервиса вне меню:
17
17
  - используйте **`@cloud-ru/ds-uikit-product-card-predefined`**.
18
18
 
@@ -36,7 +36,8 @@ import {
36
36
 
37
37
  ## Смотри также
38
38
 
39
- - **`MainMenu`** — desktop/mobile drawer и слоты `leftTop` / `search`.
39
+ - **`MainMenu`** — desktop/mobile drawer, слоты `leftTop` / `search`, интеграция с **`MenuMobile`** через `customMobileMenu`.
40
+ - **`@cloud-ru/ds-uikit-product-header`** — новая шапка и mobile bottom sheet для поэтапной миграции.
40
41
  - **`@cloud-ru/ds-uikit-product-card-predefined`** — `CardServiceLight` в сетке категорий.
41
42
  - **`@cloud-ru/ds-drawer`** — drawer, на котором собран MainMenu.
42
43
  - **`@cloud-ru/ds-adaptive`** — `AdaptiveProvider` / `layoutType` для поверхности MainMenu.
@@ -249,9 +250,9 @@ Legacy MainMenu — кнопка MainMenuSVG и адаптивный drawer на
249
250
  Legacy MainMenu (Figma `navigationOldDrawer` / `navigationOldDrawerMobile`). Кнопка с `MainMenuSVG` открывает drawer навигации.
250
251
 
251
252
  - **Desktop** — двухколоночный `@cloud-ru/ds-drawer` (`DrawerCustom`): левая колонка 256px, divider, правая с поиском и категориями.
252
- - **Mobile** — левый одноколоночный drawer (не BottomSheet): заголовок «Навигация», scroll-body со sticky-поиском.
253
+ - **Mobile** — по умолчанию левый одноколоночный drawer (не BottomSheet): заголовок «Навигация», scroll-body со sticky-поиском. Через `customMobileMenu` можно подставить mobile-меню из **`@cloud-ru/ds-uikit-product-header`** (bottom sheet).
253
254
 
254
- Поверхность выбирается через `AdaptiveProvider` (`layoutType`); проп `isMobile` — legacy override.
255
+ Поверхность выбирается через `AdaptiveProvider` (`layoutType`).
255
256
 
256
257
  ### Когда использовать
257
258
 
@@ -263,7 +264,7 @@ Legacy MainMenu (Figma `navigationOldDrawer` / `navigationOldDrawerMobile`). К
263
264
  - Только верхняя полоса без drawer:
264
265
  - используйте **`HeaderLayout`**.
265
266
  - Новая продуктовая навигация без legacy-контрактов:
266
- - используйте актуальные layout/header-пакеты Product UI Kit.
267
+ - используйте **`@cloud-ru/ds-uikit-product-header`**.
267
268
 
268
269
  ### Анатомия
269
270
 
@@ -292,11 +293,19 @@ Legacy MainMenu (Figma `navigationOldDrawer` / `navigationOldDrawerMobile`). К
292
293
  1. `leftTop` — в микрофронте и Figma: два `PlatformSelector` (платформа + проект с `avatarName`).
293
294
  2. `search` — свёрнутый `NavigationSearch`; при скролле остаётся sticky (`position: sticky`).
294
295
  3. `rightTop` — баннеры в колонку (`data-mobile` на контейнере).
295
- 4. `serviceGroups` — те же категории; favorite на карточках всегда виден.
296
- 5. `settingItems` — `@cloud-ru/ds-list` с divider внизу.
296
+ 4. `serviceGroups` — те же категории в сетке из одной колонки (`data-mobile` на `.services`); favorite на карточках всегда виден.
297
+ 5. `settingItems` — `CardServiceLight` + `Divider` внизу scroll-body.
297
298
 
298
299
  `sidebarBottomSlot` на mobile **не** рендерится (legacy-поведение).
299
300
 
301
+ #### customMobileMenu
302
+
303
+ Только на mobile: заменяет встроенный legacy `MenuMobile` (левый drawer). Типичный сценарий — микрофронт с legacy `HeaderLayout` и новым mobile-меню из `@cloud-ru/ds-uikit-product-header`.
304
+
305
+ - `MenuMobile` импортируется из `@cloud-ru/ds-uikit-product-header`, **не** из `@cloud-ru/ds-uikit-product-header-legacy`.
306
+ - Передаются те же controlled `open` / `setOpen`, что и в `MainMenu` — иначе кнопка-триггер и drawer разойдутся.
307
+ - Данные для `MenuMobile` маппятся на API нового header (`segments`, `settingItems` и т.д.) отдельно от legacy-пропов `MainMenu`.
308
+
300
309
  #### open / setOpen
301
310
 
302
311
  Controlled-открытие drawer. Без `open` состояние держит сам компонент. В примерах drawer закрыт до клика по trigger.
@@ -496,12 +505,44 @@ export function MobileSurface() {
496
505
  }
497
506
  ```
498
507
 
508
+ #### Новое mobile-меню через `customMobileMenu`
509
+
510
+ Controlled-состояние drawer общее для trigger и mobile-меню:
511
+
512
+ ```tsx
513
+ import { useState } from 'react';
514
+ import { MainMenu } from '@cloud-ru/ds-uikit-product-header-legacy';
515
+ import { MenuMobile } from '@cloud-ru/ds-uikit-product-header';
516
+
517
+ function HeaderMainMenu() {
518
+ const [open, setOpen] = useState(false);
519
+
520
+ return (
521
+ <MainMenu
522
+ open={open}
523
+ setOpen={setOpen}
524
+ serviceGroups={legacyServiceGroups}
525
+ /* …остальные legacy-пропы для desktop… */
526
+ customMobileMenu={
527
+ <MenuMobile
528
+ open={open}
529
+ setOpen={setOpen}
530
+ segments={headerSegments}
531
+ /* …пропы API @cloud-ru/ds-uikit-product-header… */
532
+ />
533
+ }
534
+ />
535
+ );
536
+ }
537
+ ```
538
+
499
539
  ### Props
500
540
 
501
541
  **WithSupportProps**
502
542
 
503
543
  | Prop | Type | Default | Description |
504
544
  |------|------|---------|-------------|
545
+ | `customMobileMenu` | `ReactNode` | — | Только mobile: заменяет legacy `MenuMobile` (левый drawer). <br/> Например, `MenuMobile` из `@cloud-ru/ds-uikit-product-header` (bottom sheet). <br/> Передавайте те же `open` / `setOpen`, что и в `MainMenu` (controlled), иначе триггер и кастомное меню разойдутся. |
505
546
  | `data-test-id` | `string` | — | |
506
547
  | `disabled` | `boolean` | — | |
507
548
  | `favorite` | `{ value: string[]; onChange: (productId: string) => (addingValue: boolean) => void; }` | — | |
@@ -513,7 +554,7 @@ export function MobileSurface() {
513
554
  | `search` | `SearchProps` | — | |
514
555
  | `serviceGroups` | `LinksGroup[]` | — | Основные группы облачных сервисов (инфраструктура, сеть, хранилище и т.п.). <br/> Всегда видны в сетке карточек при пустом поиске; участвуют в избранном и боковой навигации. <br/> При поиске фильтруются вместе с остальными группами и показываются **первыми** в выдаче. |
515
556
  | `setOpen` | `((open: boolean) => void)` | — | |
516
- | `settingItems` | `LinksGroup` | — | Административные сервисы (одна группа, например «Административные сервисы»). <br/> Без поиска: пункты в нижней части левой колонки (desktop), не в сетке карточек. <br/> С поиском: группа попадает в результаты только при совпадении; отображается **последней** <br/> (ниже `serviceGroups` и `platformGroups`). Обычно `favoritesEnabled: false`. |
557
+ | `settingItems` | `LinksGroup` | — | Административные сервисы (одна группа, например «Административные сервисы»). <br/> Без поиска: пункты в нижней части левой колонки (desktop), не в сетке карточек. <br/> С поиском: группа попадает в результаты только при совпадении; отображается **последней** <br/> (ниже `serviceGroups` и `platformGroups`). Обычно `favoritesEnabled: false`. <br/> Mobile: `CardServiceLight` + `Divider` внизу scroll-body. |
517
558
  | `sidebarBottomSlot` | `ReactNode` | — | Нижний слот левой колонки sidebar (Figma `bottom > items`). |
518
559
 
519
560
  ### Storybook
@@ -525,18 +566,23 @@ WithSampleContent (Figma mobile composition):
525
566
  Desktop (`navigationOldDrawer`):
526
567
 
527
568
  Mobile (`navigationOldDrawerMobile`):
569
+
570
+ ### Смотри также
571
+
572
+ - **`@cloud-ru/ds-uikit-product-header` / MainMenu** — новое меню и экспорт `MenuMobile` (bottom sheet) для `customMobileMenu`.
573
+ - **`@cloud-ru/ds-uikit-product-card-predefined`** — `CardServiceLight` в сетке категорий и в `settingItems` на mobile.
528
574
  ### Адаптивность
529
575
 
530
576
  Desktop-first: раскладку берёт `AdaptiveProvider` в корне приложения / Storybook. Переключение toolbar `layoutType=mobile` показывает mobile-поверхность без смены API.
531
577
 
532
578
  | Проп | Desktop | Mobile |
533
579
  |------|---------|--------|
534
- | `isMobile` | Явный override поверхности; без пропа — из контекста | То же |
580
+ | `customMobileMenu` | | Заменяет legacy `MenuMobile`; без пропа — левый drawer |
535
581
  | `sidebarBottomSlot` | Нижний слот левой колонки | Не рендерится |
536
- | `settingItems` | Карточки в левой колонке | `@cloud-ru/ds-list` внизу scroll-body |
582
+ | `settingItems` | Карточки в левой колонке | `CardServiceLight` + `Divider` внизу scroll-body |
537
583
  | `leftTop` | Один селектор платформы | Платформа + проект (два `PlatformSelector`) |
538
584
  | `search` | Вне Scroll, всегда развёрнут | Sticky в scroll-body, сначала свёрнут |
539
- | `rightTop` / `serviceGroups` | Правая колонка | Одноколоночный scroll-body |
585
+ | `rightTop` / `serviceGroups` | Правая колонка | Одноколоночный scroll-body; сетка сервисов — 1 колонка |
540
586
 
541
587
  Форс конкретной раскладки в Storybook — toolbar-global `layoutType` или вложенный `AdaptiveProvider` / `withLayoutType`.
542
588
 
@@ -4,6 +4,6 @@ import { MainMenuProps } from './types';
4
4
  /**
5
5
  * Legacy MainMenu: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer.
6
6
  */
7
- export declare function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, disabled, ...rest }: WithSupportProps<MainMenuProps & {
7
+ export declare function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, customMobileMenu, disabled, ...rest }: WithSupportProps<MainMenuProps & {
8
8
  disabled?: boolean;
9
9
  }>): ReactElement;
@@ -12,9 +12,21 @@ const MenuMobile_1 = require("./helperComponents/MenuMobile");
12
12
  /**
13
13
  * Legacy MainMenu: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer.
14
14
  */
15
- function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, disabled, ...rest }) {
15
+ function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, customMobileMenu, disabled, ...rest }) {
16
16
  const [open = false, setOpen] = (0, utils_1.useValueControl)({ value: openProp, onChange: setOpenProp });
17
17
  const isMobile = (0, useMobileLayout_1.useMobileLayout)();
18
- const MenuComponent = isMobile ? MenuMobile_1.MenuMobile : MenuDesktop_1.MenuDesktop;
19
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, utils_1.extractSupportProps)(rest), appearance: 'neutral', view: 'simple', size: 'm', disabled: disabled, icon: (0, jsx_runtime_1.jsx)(product_1.MainMenuSVG, {}), onClick: () => setOpen(true), "data-test-id": constants_1.TEST_IDS.trigger }), (0, jsx_runtime_1.jsx)(MenuComponent, { open: open, setOpen: setOpen, leftTop: leftTop, rightTop: rightTop, settingItems: settingItems, serviceGroups: serviceGroups, platformGroups: platformGroups, onLinkChange: onLinkChange, favorite: favorite, search: search, sidebarBottomSlot: sidebarBottomSlot })] }));
18
+ const menuProps = {
19
+ open,
20
+ setOpen,
21
+ leftTop,
22
+ rightTop,
23
+ settingItems,
24
+ serviceGroups,
25
+ platformGroups,
26
+ onLinkChange,
27
+ favorite,
28
+ search,
29
+ sidebarBottomSlot,
30
+ };
31
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { ...(0, utils_1.extractSupportProps)(rest), appearance: 'neutral', view: 'simple', size: 'm', disabled: disabled, icon: (0, jsx_runtime_1.jsx)(product_1.MainMenuSVG, {}), onClick: () => setOpen(true), "data-test-id": constants_1.TEST_IDS.trigger }), isMobile ? (customMobileMenu ?? (0, jsx_runtime_1.jsx)(MenuMobile_1.MenuMobile, { ...menuProps })) : (0, jsx_runtime_1.jsx)(MenuDesktop_1.MenuDesktop, { ...menuProps })] }));
20
32
  }
@@ -102,6 +102,8 @@ export type MainMenuProps = {
102
102
  * Без поиска: пункты в нижней части левой колонки (desktop), не в сетке карточек.
103
103
  * С поиском: группа попадает в результаты только при совпадении; отображается **последней**
104
104
  * (ниже `serviceGroups` и `platformGroups`). Обычно `favoritesEnabled: false`.
105
+ *
106
+ * Mobile: `CardServiceLight` + `Divider` внизу scroll-body.
105
107
  */
106
108
  settingItems?: LinksGroup;
107
109
  /**
@@ -127,5 +129,12 @@ export type MainMenuProps = {
127
129
  search?: SearchProps;
128
130
  /** Нижний слот левой колонки sidebar (Figma `bottom > items`). */
129
131
  sidebarBottomSlot?: ReactNode;
132
+ /**
133
+ * Только mobile: заменяет legacy `MenuMobile` (левый drawer).
134
+ * Например, `MenuMobile` из `@cloud-ru/ds-uikit-product-header` (bottom sheet).
135
+ *
136
+ * Передавайте те же `open` / `setOpen`, что и в `MainMenu` (controlled), иначе триггер и кастомное меню разойдутся.
137
+ */
138
+ customMobileMenu?: ReactNode;
130
139
  };
131
140
  export {};
@@ -4,6 +4,6 @@ import { MainMenuProps } from './types.js';
4
4
  /**
5
5
  * Legacy MainMenu: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer.
6
6
  */
7
- export declare function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, disabled, ...rest }: WithSupportProps<MainMenuProps & {
7
+ export declare function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, customMobileMenu, disabled, ...rest }: WithSupportProps<MainMenuProps & {
8
8
  disabled?: boolean;
9
9
  }>): ReactElement;
@@ -9,9 +9,21 @@ import { MenuMobile } from './helperComponents/MenuMobile/index.js';
9
9
  /**
10
10
  * Legacy MainMenu: desktop — двухколоночный drawer; mobile — левый одноколоночный drawer.
11
11
  */
12
- export function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, disabled, ...rest }) {
12
+ export function MainMenu({ open: openProp, setOpen: setOpenProp, leftTop, rightTop, settingItems, serviceGroups, platformGroups, onLinkChange, favorite, search, sidebarBottomSlot, customMobileMenu, disabled, ...rest }) {
13
13
  const [open = false, setOpen] = useValueControl({ value: openProp, onChange: setOpenProp });
14
14
  const isMobile = useMobileLayout();
15
- const MenuComponent = isMobile ? MenuMobile : MenuDesktop;
16
- return (_jsxs(_Fragment, { children: [_jsx(Button, { ...extractSupportProps(rest), appearance: 'neutral', view: 'simple', size: 'm', disabled: disabled, icon: _jsx(MainMenuSVG, {}), onClick: () => setOpen(true), "data-test-id": TEST_IDS.trigger }), _jsx(MenuComponent, { open: open, setOpen: setOpen, leftTop: leftTop, rightTop: rightTop, settingItems: settingItems, serviceGroups: serviceGroups, platformGroups: platformGroups, onLinkChange: onLinkChange, favorite: favorite, search: search, sidebarBottomSlot: sidebarBottomSlot })] }));
15
+ const menuProps = {
16
+ open,
17
+ setOpen,
18
+ leftTop,
19
+ rightTop,
20
+ settingItems,
21
+ serviceGroups,
22
+ platformGroups,
23
+ onLinkChange,
24
+ favorite,
25
+ search,
26
+ sidebarBottomSlot,
27
+ };
28
+ return (_jsxs(_Fragment, { children: [_jsx(Button, { ...extractSupportProps(rest), appearance: 'neutral', view: 'simple', size: 'm', disabled: disabled, icon: _jsx(MainMenuSVG, {}), onClick: () => setOpen(true), "data-test-id": TEST_IDS.trigger }), isMobile ? (customMobileMenu ?? _jsx(MenuMobile, { ...menuProps })) : _jsx(MenuDesktop, { ...menuProps })] }));
17
29
  }
@@ -102,6 +102,8 @@ export type MainMenuProps = {
102
102
  * Без поиска: пункты в нижней части левой колонки (desktop), не в сетке карточек.
103
103
  * С поиском: группа попадает в результаты только при совпадении; отображается **последней**
104
104
  * (ниже `serviceGroups` и `platformGroups`). Обычно `favoritesEnabled: false`.
105
+ *
106
+ * Mobile: `CardServiceLight` + `Divider` внизу scroll-body.
105
107
  */
106
108
  settingItems?: LinksGroup;
107
109
  /**
@@ -127,5 +129,12 @@ export type MainMenuProps = {
127
129
  search?: SearchProps;
128
130
  /** Нижний слот левой колонки sidebar (Figma `bottom > items`). */
129
131
  sidebarBottomSlot?: ReactNode;
132
+ /**
133
+ * Только mobile: заменяет legacy `MenuMobile` (левый drawer).
134
+ * Например, `MenuMobile` из `@cloud-ru/ds-uikit-product-header` (bottom sheet).
135
+ *
136
+ * Передавайте те же `open` / `setOpen`, что и в `MainMenu` (controlled), иначе триггер и кастомное меню разойдутся.
137
+ */
138
+ customMobileMenu?: ReactNode;
130
139
  };
131
140
  export {};