@cloud-ru/uikit-product-header 5.0.17

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.
Files changed (240) hide show
  1. package/CHANGELOG.md +3498 -0
  2. package/LICENSE +201 -0
  3. package/README.md +322 -0
  4. package/dist/cjs/components/HeaderLayout/HeaderLayout.d.ts +12 -0
  5. package/dist/cjs/components/HeaderLayout/HeaderLayout.js +25 -0
  6. package/dist/cjs/components/HeaderLayout/index.d.ts +1 -0
  7. package/dist/cjs/components/HeaderLayout/index.js +17 -0
  8. package/dist/cjs/components/HeaderLayout/styles.module.css +35 -0
  9. package/dist/cjs/components/Logo/Logo.d.ts +20 -0
  10. package/dist/cjs/components/Logo/Logo.js +61 -0
  11. package/dist/cjs/components/Logo/index.d.ts +1 -0
  12. package/dist/cjs/components/Logo/index.js +17 -0
  13. package/dist/cjs/components/Logo/styles.module.css +28 -0
  14. package/dist/cjs/components/MainMenu/Content/Content.d.ts +20 -0
  15. package/dist/cjs/components/MainMenu/Content/Content.js +36 -0
  16. package/dist/cjs/components/MainMenu/Content/index.d.ts +1 -0
  17. package/dist/cjs/components/MainMenu/Content/index.js +17 -0
  18. package/dist/cjs/components/MainMenu/Content/styles.module.css +40 -0
  19. package/dist/cjs/components/MainMenu/MainMenu.d.ts +4 -0
  20. package/dist/cjs/components/MainMenu/MainMenu.js +16 -0
  21. package/dist/cjs/components/MainMenu/MenuDesktop/MenuDesktop.d.ts +2 -0
  22. package/dist/cjs/components/MainMenu/MenuDesktop/MenuDesktop.js +34 -0
  23. package/dist/cjs/components/MainMenu/MenuDesktop/index.d.ts +1 -0
  24. package/dist/cjs/components/MainMenu/MenuDesktop/index.js +17 -0
  25. package/dist/cjs/components/MainMenu/MenuDesktop/styles.module.css +94 -0
  26. package/dist/cjs/components/MainMenu/MenuMobile/MenuMobile.d.ts +2 -0
  27. package/dist/cjs/components/MainMenu/MenuMobile/MenuMobile.js +31 -0
  28. package/dist/cjs/components/MainMenu/MenuMobile/index.d.ts +1 -0
  29. package/dist/cjs/components/MainMenu/MenuMobile/index.js +17 -0
  30. package/dist/cjs/components/MainMenu/MenuMobile/styles.module.css +23 -0
  31. package/dist/cjs/components/MainMenu/Search/SearchDesktop/SearchDesktop.d.ts +2 -0
  32. package/dist/cjs/components/MainMenu/Search/SearchDesktop/SearchDesktop.js +18 -0
  33. package/dist/cjs/components/MainMenu/Search/SearchDesktop/index.d.ts +1 -0
  34. package/dist/cjs/components/MainMenu/Search/SearchDesktop/index.js +17 -0
  35. package/dist/cjs/components/MainMenu/Search/SearchDesktop/styles.module.css +17 -0
  36. package/dist/cjs/components/MainMenu/Search/SearchMobile/SearchMobile.d.ts +2 -0
  37. package/dist/cjs/components/MainMenu/Search/SearchMobile/SearchMobile.js +42 -0
  38. package/dist/cjs/components/MainMenu/Search/SearchMobile/constants.d.ts +4 -0
  39. package/dist/cjs/components/MainMenu/Search/SearchMobile/constants.js +7 -0
  40. package/dist/cjs/components/MainMenu/Search/SearchMobile/hooks.d.ts +12 -0
  41. package/dist/cjs/components/MainMenu/Search/SearchMobile/hooks.js +40 -0
  42. package/dist/cjs/components/MainMenu/Search/SearchMobile/index.d.ts +1 -0
  43. package/dist/cjs/components/MainMenu/Search/SearchMobile/index.js +17 -0
  44. package/dist/cjs/components/MainMenu/Search/SearchMobile/styles.module.css +57 -0
  45. package/dist/cjs/components/MainMenu/Search/SearchSettingsButton/SearchSettingsButton.d.ts +4 -0
  46. package/dist/cjs/components/MainMenu/Search/SearchSettingsButton/SearchSettingsButton.js +13 -0
  47. package/dist/cjs/components/MainMenu/Search/SearchSettingsButton/index.d.ts +1 -0
  48. package/dist/cjs/components/MainMenu/Search/SearchSettingsButton/index.js +17 -0
  49. package/dist/cjs/components/MainMenu/Search/SearchSettingsButton/styles.module.css +11 -0
  50. package/dist/cjs/components/MainMenu/Search/index.d.ts +3 -0
  51. package/dist/cjs/components/MainMenu/Search/index.js +19 -0
  52. package/dist/cjs/components/MainMenu/Search/types.d.ts +14 -0
  53. package/dist/cjs/components/MainMenu/Search/types.js +2 -0
  54. package/dist/cjs/components/MainMenu/Search/useSearch.d.ts +8 -0
  55. package/dist/cjs/components/MainMenu/Search/useSearch.js +169 -0
  56. package/dist/cjs/components/MainMenu/hooks.d.ts +10 -0
  57. package/dist/cjs/components/MainMenu/hooks.js +108 -0
  58. package/dist/cjs/components/MainMenu/index.d.ts +4 -0
  59. package/dist/cjs/components/MainMenu/index.js +20 -0
  60. package/dist/cjs/components/MainMenu/styles.module.css +28 -0
  61. package/dist/cjs/components/MainMenu/types.d.ts +49 -0
  62. package/dist/cjs/components/MainMenu/types.js +2 -0
  63. package/dist/cjs/components/PathBreadcrumbs/PathBreadcrumbs.d.ts +7 -0
  64. package/dist/cjs/components/PathBreadcrumbs/PathBreadcrumbs.js +12 -0
  65. package/dist/cjs/components/PathBreadcrumbs/index.d.ts +1 -0
  66. package/dist/cjs/components/PathBreadcrumbs/index.js +17 -0
  67. package/dist/cjs/components/PathBreadcrumbs/styles.module.css +5 -0
  68. package/dist/cjs/components/PlatformLogo/Container.d.ts +12 -0
  69. package/dist/cjs/components/PlatformLogo/Container.js +28 -0
  70. package/dist/cjs/components/PlatformLogo/index.d.ts +4 -0
  71. package/dist/cjs/components/PlatformLogo/index.js +9 -0
  72. package/dist/cjs/components/PlatformLogo/styles.module.css +11 -0
  73. package/dist/cjs/components/UserMenu/UserMenu.d.ts +14 -0
  74. package/dist/cjs/components/UserMenu/UserMenu.js +54 -0
  75. package/dist/cjs/components/UserMenu/hooks/useLogoutItem.d.ts +6 -0
  76. package/dist/cjs/components/UserMenu/hooks/useLogoutItem.js +21 -0
  77. package/dist/cjs/components/UserMenu/hooks/useProfileItem.d.ts +3 -0
  78. package/dist/cjs/components/UserMenu/hooks/useProfileItem.js +29 -0
  79. package/dist/cjs/components/UserMenu/hooks/useThemeItem.d.ts +6 -0
  80. package/dist/cjs/components/UserMenu/hooks/useThemeItem.js +75 -0
  81. package/dist/cjs/components/UserMenu/hooks/useUserMenuItems.d.ts +13 -0
  82. package/dist/cjs/components/UserMenu/hooks/useUserMenuItems.js +42 -0
  83. package/dist/cjs/components/UserMenu/index.d.ts +2 -0
  84. package/dist/cjs/components/UserMenu/index.js +18 -0
  85. package/dist/cjs/components/UserMenu/styles.module.css +21 -0
  86. package/dist/cjs/components/UserMenu/types.d.ts +20 -0
  87. package/dist/cjs/components/UserMenu/types.js +8 -0
  88. package/dist/cjs/components/index.d.ts +6 -0
  89. package/dist/cjs/components/index.js +22 -0
  90. package/dist/cjs/hooks/index.d.ts +1 -0
  91. package/dist/cjs/hooks/index.js +17 -0
  92. package/dist/cjs/hooks/useLocalStorage.d.ts +1 -0
  93. package/dist/cjs/hooks/useLocalStorage.js +13 -0
  94. package/dist/cjs/index.d.ts +2 -0
  95. package/dist/cjs/index.js +18 -0
  96. package/dist/esm/components/HeaderLayout/HeaderLayout.d.ts +12 -0
  97. package/dist/esm/components/HeaderLayout/HeaderLayout.js +19 -0
  98. package/dist/esm/components/HeaderLayout/index.d.ts +1 -0
  99. package/dist/esm/components/HeaderLayout/index.js +1 -0
  100. package/dist/esm/components/HeaderLayout/styles.module.css +35 -0
  101. package/dist/esm/components/Logo/Logo.d.ts +20 -0
  102. package/dist/esm/components/Logo/Logo.js +54 -0
  103. package/dist/esm/components/Logo/index.d.ts +1 -0
  104. package/dist/esm/components/Logo/index.js +1 -0
  105. package/dist/esm/components/Logo/styles.module.css +28 -0
  106. package/dist/esm/components/MainMenu/Content/Content.d.ts +20 -0
  107. package/dist/esm/components/MainMenu/Content/Content.js +30 -0
  108. package/dist/esm/components/MainMenu/Content/index.d.ts +1 -0
  109. package/dist/esm/components/MainMenu/Content/index.js +1 -0
  110. package/dist/esm/components/MainMenu/Content/styles.module.css +40 -0
  111. package/dist/esm/components/MainMenu/MainMenu.d.ts +4 -0
  112. package/dist/esm/components/MainMenu/MainMenu.js +13 -0
  113. package/dist/esm/components/MainMenu/MenuDesktop/MenuDesktop.d.ts +2 -0
  114. package/dist/esm/components/MainMenu/MenuDesktop/MenuDesktop.js +28 -0
  115. package/dist/esm/components/MainMenu/MenuDesktop/index.d.ts +1 -0
  116. package/dist/esm/components/MainMenu/MenuDesktop/index.js +1 -0
  117. package/dist/esm/components/MainMenu/MenuDesktop/styles.module.css +94 -0
  118. package/dist/esm/components/MainMenu/MenuMobile/MenuMobile.d.ts +2 -0
  119. package/dist/esm/components/MainMenu/MenuMobile/MenuMobile.js +25 -0
  120. package/dist/esm/components/MainMenu/MenuMobile/index.d.ts +1 -0
  121. package/dist/esm/components/MainMenu/MenuMobile/index.js +1 -0
  122. package/dist/esm/components/MainMenu/MenuMobile/styles.module.css +23 -0
  123. package/dist/esm/components/MainMenu/Search/SearchDesktop/SearchDesktop.d.ts +2 -0
  124. package/dist/esm/components/MainMenu/Search/SearchDesktop/SearchDesktop.js +12 -0
  125. package/dist/esm/components/MainMenu/Search/SearchDesktop/index.d.ts +1 -0
  126. package/dist/esm/components/MainMenu/Search/SearchDesktop/index.js +1 -0
  127. package/dist/esm/components/MainMenu/Search/SearchDesktop/styles.module.css +17 -0
  128. package/dist/esm/components/MainMenu/Search/SearchMobile/SearchMobile.d.ts +2 -0
  129. package/dist/esm/components/MainMenu/Search/SearchMobile/SearchMobile.js +36 -0
  130. package/dist/esm/components/MainMenu/Search/SearchMobile/constants.d.ts +4 -0
  131. package/dist/esm/components/MainMenu/Search/SearchMobile/constants.js +4 -0
  132. package/dist/esm/components/MainMenu/Search/SearchMobile/hooks.d.ts +12 -0
  133. package/dist/esm/components/MainMenu/Search/SearchMobile/hooks.js +34 -0
  134. package/dist/esm/components/MainMenu/Search/SearchMobile/index.d.ts +1 -0
  135. package/dist/esm/components/MainMenu/Search/SearchMobile/index.js +1 -0
  136. package/dist/esm/components/MainMenu/Search/SearchMobile/styles.module.css +57 -0
  137. package/dist/esm/components/MainMenu/Search/SearchSettingsButton/SearchSettingsButton.d.ts +4 -0
  138. package/dist/esm/components/MainMenu/Search/SearchSettingsButton/SearchSettingsButton.js +7 -0
  139. package/dist/esm/components/MainMenu/Search/SearchSettingsButton/index.d.ts +1 -0
  140. package/dist/esm/components/MainMenu/Search/SearchSettingsButton/index.js +1 -0
  141. package/dist/esm/components/MainMenu/Search/SearchSettingsButton/styles.module.css +11 -0
  142. package/dist/esm/components/MainMenu/Search/index.d.ts +3 -0
  143. package/dist/esm/components/MainMenu/Search/index.js +3 -0
  144. package/dist/esm/components/MainMenu/Search/types.d.ts +14 -0
  145. package/dist/esm/components/MainMenu/Search/types.js +1 -0
  146. package/dist/esm/components/MainMenu/Search/useSearch.d.ts +8 -0
  147. package/dist/esm/components/MainMenu/Search/useSearch.js +161 -0
  148. package/dist/esm/components/MainMenu/hooks.d.ts +10 -0
  149. package/dist/esm/components/MainMenu/hooks.js +101 -0
  150. package/dist/esm/components/MainMenu/index.d.ts +4 -0
  151. package/dist/esm/components/MainMenu/index.js +4 -0
  152. package/dist/esm/components/MainMenu/styles.module.css +28 -0
  153. package/dist/esm/components/MainMenu/types.d.ts +49 -0
  154. package/dist/esm/components/MainMenu/types.js +1 -0
  155. package/dist/esm/components/PathBreadcrumbs/PathBreadcrumbs.d.ts +7 -0
  156. package/dist/esm/components/PathBreadcrumbs/PathBreadcrumbs.js +6 -0
  157. package/dist/esm/components/PathBreadcrumbs/index.d.ts +1 -0
  158. package/dist/esm/components/PathBreadcrumbs/index.js +1 -0
  159. package/dist/esm/components/PathBreadcrumbs/styles.module.css +5 -0
  160. package/dist/esm/components/PlatformLogo/Container.d.ts +12 -0
  161. package/dist/esm/components/PlatformLogo/Container.js +20 -0
  162. package/dist/esm/components/PlatformLogo/index.d.ts +4 -0
  163. package/dist/esm/components/PlatformLogo/index.js +6 -0
  164. package/dist/esm/components/PlatformLogo/styles.module.css +11 -0
  165. package/dist/esm/components/UserMenu/UserMenu.d.ts +14 -0
  166. package/dist/esm/components/UserMenu/UserMenu.js +48 -0
  167. package/dist/esm/components/UserMenu/hooks/useLogoutItem.d.ts +6 -0
  168. package/dist/esm/components/UserMenu/hooks/useLogoutItem.js +18 -0
  169. package/dist/esm/components/UserMenu/hooks/useProfileItem.d.ts +3 -0
  170. package/dist/esm/components/UserMenu/hooks/useProfileItem.js +23 -0
  171. package/dist/esm/components/UserMenu/hooks/useThemeItem.d.ts +6 -0
  172. package/dist/esm/components/UserMenu/hooks/useThemeItem.js +72 -0
  173. package/dist/esm/components/UserMenu/hooks/useUserMenuItems.d.ts +13 -0
  174. package/dist/esm/components/UserMenu/hooks/useUserMenuItems.js +39 -0
  175. package/dist/esm/components/UserMenu/index.d.ts +2 -0
  176. package/dist/esm/components/UserMenu/index.js +2 -0
  177. package/dist/esm/components/UserMenu/styles.module.css +21 -0
  178. package/dist/esm/components/UserMenu/types.d.ts +20 -0
  179. package/dist/esm/components/UserMenu/types.js +5 -0
  180. package/dist/esm/components/index.d.ts +6 -0
  181. package/dist/esm/components/index.js +6 -0
  182. package/dist/esm/hooks/index.d.ts +1 -0
  183. package/dist/esm/hooks/index.js +1 -0
  184. package/dist/esm/hooks/useLocalStorage.d.ts +1 -0
  185. package/dist/esm/hooks/useLocalStorage.js +10 -0
  186. package/dist/esm/index.d.ts +2 -0
  187. package/dist/esm/index.js +2 -0
  188. package/package.json +68 -0
  189. package/src/components/HeaderLayout/HeaderLayout.tsx +46 -0
  190. package/src/components/HeaderLayout/index.ts +1 -0
  191. package/src/components/HeaderLayout/styles.module.scss +38 -0
  192. package/src/components/Logo/Logo.tsx +93 -0
  193. package/src/components/Logo/index.ts +1 -0
  194. package/src/components/Logo/styles.module.scss +30 -0
  195. package/src/components/MainMenu/Content/Content.tsx +137 -0
  196. package/src/components/MainMenu/Content/index.ts +1 -0
  197. package/src/components/MainMenu/Content/styles.module.scss +35 -0
  198. package/src/components/MainMenu/MainMenu.tsx +51 -0
  199. package/src/components/MainMenu/MenuDesktop/MenuDesktop.tsx +120 -0
  200. package/src/components/MainMenu/MenuDesktop/index.ts +1 -0
  201. package/src/components/MainMenu/MenuDesktop/styles.module.scss +108 -0
  202. package/src/components/MainMenu/MenuMobile/MenuMobile.tsx +83 -0
  203. package/src/components/MainMenu/MenuMobile/index.ts +1 -0
  204. package/src/components/MainMenu/MenuMobile/styles.module.scss +26 -0
  205. package/src/components/MainMenu/Search/SearchDesktop/SearchDesktop.tsx +46 -0
  206. package/src/components/MainMenu/Search/SearchDesktop/index.ts +1 -0
  207. package/src/components/MainMenu/Search/SearchDesktop/styles.module.scss +21 -0
  208. package/src/components/MainMenu/Search/SearchMobile/SearchMobile.tsx +102 -0
  209. package/src/components/MainMenu/Search/SearchMobile/constants.ts +4 -0
  210. package/src/components/MainMenu/Search/SearchMobile/hooks.ts +43 -0
  211. package/src/components/MainMenu/Search/SearchMobile/index.ts +1 -0
  212. package/src/components/MainMenu/Search/SearchMobile/styles.module.scss +72 -0
  213. package/src/components/MainMenu/Search/SearchSettingsButton/SearchSettingsButton.tsx +22 -0
  214. package/src/components/MainMenu/Search/SearchSettingsButton/index.ts +1 -0
  215. package/src/components/MainMenu/Search/SearchSettingsButton/styles.module.scss +13 -0
  216. package/src/components/MainMenu/Search/index.ts +3 -0
  217. package/src/components/MainMenu/Search/types.ts +20 -0
  218. package/src/components/MainMenu/Search/useSearch.tsx +212 -0
  219. package/src/components/MainMenu/hooks.tsx +135 -0
  220. package/src/components/MainMenu/index.ts +4 -0
  221. package/src/components/MainMenu/styles.module.scss +28 -0
  222. package/src/components/MainMenu/types.ts +62 -0
  223. package/src/components/PathBreadcrumbs/PathBreadcrumbs.tsx +21 -0
  224. package/src/components/PathBreadcrumbs/index.ts +1 -0
  225. package/src/components/PathBreadcrumbs/styles.module.scss +10 -0
  226. package/src/components/PlatformLogo/Container.tsx +32 -0
  227. package/src/components/PlatformLogo/index.ts +8 -0
  228. package/src/components/PlatformLogo/styles.module.scss +13 -0
  229. package/src/components/UserMenu/UserMenu.tsx +138 -0
  230. package/src/components/UserMenu/hooks/useLogoutItem.tsx +28 -0
  231. package/src/components/UserMenu/hooks/useProfileItem.tsx +41 -0
  232. package/src/components/UserMenu/hooks/useThemeItem.tsx +116 -0
  233. package/src/components/UserMenu/hooks/useUserMenuItems.ts +77 -0
  234. package/src/components/UserMenu/index.ts +2 -0
  235. package/src/components/UserMenu/styles.module.scss +21 -0
  236. package/src/components/UserMenu/types.ts +24 -0
  237. package/src/components/index.ts +6 -0
  238. package/src/hooks/index.ts +1 -0
  239. package/src/hooks/useLocalStorage.ts +15 -0
  240. package/src/index.ts +2 -0
@@ -0,0 +1,138 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
4
+ import { MobileDrawerCustom } from '@cloud-ru/uikit-product-mobile-drawer';
5
+ import { Avatar } from '@snack-uikit/avatar';
6
+ import { ButtonFunction } from '@snack-uikit/button';
7
+ import { BaseItemProps, Droplist, List, ListProps } from '@snack-uikit/list';
8
+ import { Scroll } from '@snack-uikit/scroll';
9
+ import { useValueControl } from '@snack-uikit/utils';
10
+
11
+ import { useUserMenuItems } from './hooks/useUserMenuItems';
12
+ import styles from './styles.module.scss';
13
+ import { ThemeProps, UserProfileProps } from './types';
14
+
15
+ export type UserMenuProps = {
16
+ profile?: UserProfileProps;
17
+
18
+ theme?: ThemeProps;
19
+
20
+ items?: ListProps['items'];
21
+
22
+ settingItems?: BaseItemProps[];
23
+
24
+ onLogout?(): void;
25
+
26
+ open?: boolean;
27
+ setOpen?(open: boolean): void;
28
+
29
+ onClick?(): void;
30
+
31
+ isMobile?: boolean;
32
+ };
33
+
34
+ export function UserMenu({
35
+ profile = {},
36
+ open: openProp,
37
+ setOpen: setOpenProp,
38
+ onLogout,
39
+ items,
40
+ settingItems,
41
+ theme,
42
+ isMobile,
43
+ onClick,
44
+ }: UserMenuProps) {
45
+ const { t } = useLocale('Header');
46
+
47
+ const [open = false, setOpen] = useValueControl<boolean>({ value: openProp, onChange: setOpenProp });
48
+
49
+ const { fullName = '', inviteCount } = profile;
50
+
51
+ const userMenuItems = useUserMenuItems({
52
+ isMobile,
53
+ profile,
54
+ theme,
55
+ items,
56
+ settingItems,
57
+ onClose: () => {
58
+ setOpen(false);
59
+ },
60
+ onLogout,
61
+ });
62
+
63
+ const trigger = useMemo(
64
+ () => (
65
+ <ButtonFunction
66
+ size='m'
67
+ onClick={() => {
68
+ setOpen?.(true);
69
+ onClick?.();
70
+ }}
71
+ counter={
72
+ Number(inviteCount)
73
+ ? {
74
+ value: Number(inviteCount),
75
+ appearance: 'primary',
76
+ }
77
+ : undefined
78
+ }
79
+ data-test-id='header__user-menu__button'
80
+ icon={<Avatar size='xs' name={fullName} showTwoSymbols />}
81
+ />
82
+ ),
83
+ [fullName, inviteCount, onClick, setOpen],
84
+ );
85
+
86
+ if (isMobile) {
87
+ return (
88
+ <>
89
+ {trigger}
90
+
91
+ <MobileDrawerCustom
92
+ open={open}
93
+ onClose={() => {
94
+ setOpen(false);
95
+ }}
96
+ position='right'
97
+ swipeEnabled={false}
98
+ data-test-id='header__user-menu-mobile'
99
+ closeOnPopstate
100
+ >
101
+ <MobileDrawerCustom.Header title={t('user')} />
102
+ <Scroll barHideStrategy='never'>
103
+ <div className={styles.mobileList}>
104
+ <List
105
+ items={userMenuItems}
106
+ selection={{
107
+ mode: 'single',
108
+ value: 'null',
109
+ }}
110
+ size='m'
111
+ />
112
+ </div>
113
+ </Scroll>
114
+ </MobileDrawerCustom>
115
+ </>
116
+ );
117
+ }
118
+
119
+ return (
120
+ <>
121
+ <Droplist
122
+ items={userMenuItems}
123
+ selection={{
124
+ mode: 'single',
125
+ value: 'null',
126
+ }}
127
+ trigger='click'
128
+ placement='bottom-end'
129
+ className={styles.userMenuDroplist}
130
+ closeOnPopstate
131
+ closeDroplistOnItemClick
132
+ data-test-id='header__user-menu'
133
+ >
134
+ {trigger}
135
+ </Droplist>
136
+ </>
137
+ );
138
+ }
@@ -0,0 +1,28 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { ExitSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
5
+ import { ListProps } from '@snack-uikit/list';
6
+
7
+ type UseLogoutItemProps = {
8
+ onLogout?(): void;
9
+ };
10
+
11
+ export function useLogoutItem({ onLogout }: UseLogoutItemProps): ListProps['items'] {
12
+ const { t } = useLocale('Header');
13
+
14
+ return useMemo(
15
+ () => [
16
+ { type: 'group', divider: true, items: [] },
17
+ {
18
+ content: {
19
+ option: t('logout'),
20
+ },
21
+ beforeContent: <ExitSVG />,
22
+ onClick: onLogout,
23
+ 'data-test-id': 'header__user-menu__logout',
24
+ },
25
+ ],
26
+ [onLogout, t],
27
+ );
28
+ }
@@ -0,0 +1,41 @@
1
+ import { useMemo } from 'react';
2
+
3
+ import { SettingsSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { Avatar } from '@snack-uikit/avatar';
5
+ import { BaseItemProps } from '@snack-uikit/list';
6
+
7
+ import styles from '../styles.module.scss';
8
+ import { UserProfileProps } from '../types';
9
+
10
+ export function useProfileItem({
11
+ fullName = '',
12
+ email = '',
13
+ itemWrapRender,
14
+ onClick,
15
+ }: UserProfileProps): BaseItemProps {
16
+ return useMemo(
17
+ () => ({
18
+ content: {
19
+ option: fullName,
20
+ description: email,
21
+ truncate: {
22
+ description: 1,
23
+ },
24
+ },
25
+ onClick,
26
+ beforeContent: <Avatar size='xs' name={fullName} showTwoSymbols />,
27
+ afterContent: (
28
+ <div className={styles.settingIcon}>
29
+ <SettingsSVG />
30
+ </div>
31
+ ),
32
+ itemWrapRender,
33
+
34
+ id: 'header__user-menu__button',
35
+ 'data-test-id': 'header__user-menu__manage-profile',
36
+
37
+ className: styles.userMenuInfoItem,
38
+ }),
39
+ [email, fullName, itemWrapRender, onClick],
40
+ );
41
+ }
@@ -0,0 +1,116 @@
1
+ import { ReactNode, useCallback, useMemo, useState } from 'react';
2
+
3
+ import { ChevronRightSVG, DaySVG, LaptopPhoneSVG, NightSVG, ThemeContrastSVG } from '@cloud-ru/uikit-product-icons';
4
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
5
+ import { MobileModalCustom } from '@cloud-ru/uikit-product-mobile-modal';
6
+ import { DroplistProps, List } from '@snack-uikit/list';
7
+
8
+ import { THEME_MODE, ThemeMode, ThemeProps } from '../types';
9
+
10
+ export function useThemeItem({
11
+ value: themeMode,
12
+ onChange,
13
+ isMobile,
14
+ onClose,
15
+ }: ThemeProps & { isMobile?: boolean; onClose?(): void }): DroplistProps['items'][0] {
16
+ const { t } = useLocale('Header');
17
+
18
+ const [open, setOpen] = useState(false);
19
+
20
+ const handleClick = useCallback(
21
+ (themeMode: ThemeMode) => () => {
22
+ onChange?.(themeMode);
23
+ !isMobile && onClose?.();
24
+ },
25
+ [isMobile, onChange, onClose],
26
+ );
27
+
28
+ const themeModeOptions = useMemo(
29
+ () => [
30
+ {
31
+ beforeContent: <DaySVG />,
32
+ content: {
33
+ option: t('themeModeLight'),
34
+ },
35
+ onClick: handleClick(THEME_MODE.Light),
36
+ checked: themeMode === THEME_MODE.Light,
37
+ 'data-test-id': 'header__user-menu__theme-mode__light-option',
38
+ },
39
+ {
40
+ beforeContent: <NightSVG />,
41
+ content: {
42
+ option: t('themeModeDark'),
43
+ },
44
+ checked: themeMode === THEME_MODE.Dark,
45
+ onClick: handleClick(THEME_MODE.Dark),
46
+ 'data-test-id': 'header__user-menu__theme-mode__dark-option',
47
+ },
48
+ {
49
+ beforeContent: <LaptopPhoneSVG />,
50
+ content: {
51
+ option: t('themeModeSystem'),
52
+ },
53
+ checked: themeMode === THEME_MODE.System,
54
+ onClick: handleClick(THEME_MODE.System),
55
+ 'data-test-id': 'header__user-menu__theme-mode__system-option',
56
+ },
57
+ ],
58
+ [handleClick, t, themeMode],
59
+ );
60
+
61
+ const themeItem = useMemo(
62
+ () => ({
63
+ type: 'next-list',
64
+ content: {
65
+ option: t('themeModeLabel'),
66
+ },
67
+ placement: 'left-start',
68
+ beforeContent: <ThemeContrastSVG />,
69
+ 'data-test-id': 'header__user-menu__theme-mode',
70
+ items: themeModeOptions,
71
+ }),
72
+ [t, themeModeOptions],
73
+ );
74
+
75
+ const mobileThemeItem = useMemo(
76
+ () => ({
77
+ id: 'header__user-menu__theme-mode',
78
+ beforeContent: <ThemeContrastSVG />,
79
+ 'data-test-id': 'header__user-menu__theme-mode',
80
+ afterContent: (
81
+ <span
82
+ style={{
83
+ color: 'var(--sys-neutral-text-light)',
84
+ }}
85
+ >
86
+ <ChevronRightSVG />
87
+ </span>
88
+ ),
89
+ content: {
90
+ option: t('themeModeLabel'),
91
+ },
92
+ onClick: () => {
93
+ setOpen(true);
94
+ },
95
+ itemWrapRender: (node: ReactNode) => (
96
+ <>
97
+ {node}
98
+ <MobileModalCustom
99
+ open={open}
100
+ onClose={() => {
101
+ setOpen(false);
102
+ }}
103
+ closeButtonEnabled
104
+ closeOnPopstate
105
+ >
106
+ <MobileModalCustom.Header title={t('themeModeLabel')} />
107
+ <List items={themeModeOptions} size='l' selection={{ mode: 'single', value: themeMode }} />
108
+ </MobileModalCustom>
109
+ </>
110
+ ),
111
+ }),
112
+ [open, t, themeMode, themeModeOptions],
113
+ );
114
+
115
+ return isMobile ? mobileThemeItem : themeItem;
116
+ }
@@ -0,0 +1,77 @@
1
+ import { MouseEvent, useMemo } from 'react';
2
+
3
+ import { BaseItemProps, GroupItemProps, isBaseItemProps, ListProps } from '@snack-uikit/list';
4
+
5
+ import { ThemeProps, UserProfileProps } from '../types';
6
+ import { useLogoutItem } from './useLogoutItem';
7
+ import { useProfileItem } from './useProfileItem';
8
+ import { useThemeItem } from './useThemeItem';
9
+
10
+ type UseMenuItems = {
11
+ profile: UserProfileProps;
12
+
13
+ theme?: ThemeProps;
14
+
15
+ items?: ListProps['items'];
16
+
17
+ settingItems?: BaseItemProps[];
18
+
19
+ onLogout?(): void;
20
+
21
+ onClose?(): void;
22
+
23
+ isMobile?: boolean;
24
+ };
25
+
26
+ const DIVIDER_ITEM: GroupItemProps = {
27
+ type: 'group',
28
+ divider: true,
29
+ items: [],
30
+ };
31
+
32
+ export function useUserMenuItems({
33
+ profile,
34
+ theme,
35
+ onLogout,
36
+ items: itemsProp = [],
37
+ isMobile,
38
+ onClose,
39
+ settingItems = [],
40
+ }: UseMenuItems) {
41
+ const profileItem = useProfileItem(profile);
42
+ const themeItem = useThemeItem({ ...(theme || {}), isMobile, onClose });
43
+ const logoutItem = useLogoutItem({ onLogout });
44
+
45
+ const items = useMemo(() => {
46
+ let items: ListProps['items'] = [profileItem];
47
+
48
+ if (themeItem) {
49
+ items = items.concat([DIVIDER_ITEM, themeItem]);
50
+ }
51
+
52
+ items = items.concat(itemsProp);
53
+ items = items.concat(logoutItem);
54
+
55
+ if (isMobile && Boolean(settingItems?.length)) {
56
+ items = items.concat([DIVIDER_ITEM, ...settingItems]);
57
+ }
58
+
59
+ return items.map(item => {
60
+ if (isBaseItemProps(item) && item.id !== 'header__user-menu__theme-mode') {
61
+ return {
62
+ ...item,
63
+ onClick: (e: MouseEvent<HTMLElement>) => {
64
+ item.onClick?.(e);
65
+
66
+ if (!e.metaKey) {
67
+ onClose?.();
68
+ }
69
+ },
70
+ };
71
+ }
72
+ return item;
73
+ });
74
+ }, [isMobile, itemsProp, logoutItem, onClose, profileItem, settingItems, themeItem]);
75
+
76
+ return items;
77
+ }
@@ -0,0 +1,2 @@
1
+ export * from './UserMenu';
2
+ export * from './types';
@@ -0,0 +1,21 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/components/styles-tokens-element' as ste;
2
+
3
+ .userMenuDroplist {
4
+ width: 272px;
5
+ }
6
+
7
+ .mobileList {
8
+ padding: 16px;
9
+ padding-top: 0;
10
+ }
11
+
12
+ .settingIcon {
13
+ color: ste.$sys-neutral-text-light;
14
+ }
15
+
16
+ .userMenuInfoItem {
17
+ [data-test-id='list__base-item-option'] {
18
+ // TODO: подумать как "нормально" прокидывать стили/типографику
19
+ @include ste.composite-var(ste.$sans-label-m);
20
+ }
21
+ }
@@ -0,0 +1,24 @@
1
+ import { MouseEvent, ReactNode } from 'react';
2
+
3
+ export type UserProfileProps = {
4
+ fullName?: string;
5
+ email?: string;
6
+ inviteCount?: number;
7
+ onClick?(e: MouseEvent<HTMLElement>): void;
8
+ itemWrapRender?(node: ReactNode): ReactNode;
9
+ };
10
+
11
+ type ValueOf<T> = T[keyof T];
12
+
13
+ export const THEME_MODE = {
14
+ Light: 'light',
15
+ Dark: 'dark',
16
+ System: 'system',
17
+ } as const;
18
+
19
+ export type ThemeMode = ValueOf<typeof THEME_MODE>;
20
+
21
+ export type ThemeProps = {
22
+ value?: ThemeMode;
23
+ onChange?(themeMode: ThemeMode): void;
24
+ };
@@ -0,0 +1,6 @@
1
+ export * from './HeaderLayout';
2
+ export * from './MainMenu';
3
+ export * from './UserMenu';
4
+ export * from './Logo';
5
+ export * from './PathBreadcrumbs';
6
+ export * from './PlatformLogo';
@@ -0,0 +1 @@
1
+ export * from './useLocalStorage';
@@ -0,0 +1,15 @@
1
+ import { useCallback, useState } from 'react';
2
+
3
+ export function useLocalStorage<T extends string = string>(key: string, defaultValue: T): [T, (newValue: T) => void] {
4
+ const [value, setValueState] = useState((localStorage.getItem(key) as T) ?? defaultValue);
5
+
6
+ const setValue = useCallback(
7
+ (newValue: T) => {
8
+ localStorage.setItem(key, newValue);
9
+ setValueState(newValue);
10
+ },
11
+ [key],
12
+ );
13
+
14
+ return [value, setValue];
15
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './components';
2
+ export * from './hooks';