@jetbrains/kotlin-web-site-ui 4.3.0 → 4.4.0-alpha.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.
Files changed (30) hide show
  1. package/out/components/footer/index.css +6 -3
  2. package/out/components/header/full-search/full-search.js +8 -1
  3. package/out/components/header/header.js +7 -16
  4. package/out/components/header/header.module.pcss.js +1 -2
  5. package/out/components/header/index.css +120 -71
  6. package/out/components/header/index.js +1 -1
  7. package/out/components/header/logo-small/kotlin-logo-small.svg.js +18 -16
  8. package/out/components/header/logo-small/logo-small.js +1 -1
  9. package/out/components/header/menu-popup/menu-button/menu-button.js +8 -5
  10. package/out/components/header/menu-popup/menu-list/menu-list.js +33 -0
  11. package/out/components/header/menu-popup/menu-list/menu-list.module.pcss.js +4 -0
  12. package/out/components/header/menu-popup/menu-list-item/menu-list-item.js +28 -0
  13. package/out/components/header/menu-popup/menu-list-item/menu-list-item.module.pcss.js +7 -0
  14. package/out/components/header/menu-popup/menu-popup.js +3 -43
  15. package/out/components/header/menu-popup/menu-popup.module.pcss.js +0 -4
  16. package/out/components/header/nav-scheme.js +9 -3
  17. package/out/components/header/search-button/search-button.js +13 -2
  18. package/out/components/header/search-button/search-button.module.pcss.js +2 -1
  19. package/out/components/top-menu/index.css +92 -125
  20. package/out/components/top-menu/top-menu.js +20 -13
  21. package/out/components/top-menu/{dropdown-menu → vertical-menu}/arrow-dropdown-icon.svg.js +0 -0
  22. package/out/components/top-menu/vertical-menu/vertical-menu.js +123 -0
  23. package/out/components/top-menu/vertical-menu/vertical-menu.module.pcss.js +13 -0
  24. package/out/components/typography/index.css +2 -1
  25. package/out/components/youtube-player/index.css +2 -1
  26. package/package.json +1 -1
  27. package/out/components/header/menu-popup/menu-button/close-icon.svg.js +0 -35
  28. package/out/components/header/menu-popup/menu-button/hamburger-icon.svg.js +0 -35
  29. package/out/components/top-menu/dropdown-menu/dropdown-menu.js +0 -71
  30. package/out/components/top-menu/dropdown-menu/dropdown-menu.module.pcss.js +0 -15
@@ -1,4 +1,6 @@
1
1
  import { PLAYGROUND_URL, KOTLINLANG_URL } from './consts.js';
2
+ const HOME_TITLE = 'Home';
3
+ const HOME_URL = '/';
2
4
  const SOLUTIONS_TITLE = 'Solutions';
3
5
  const MULTIPLATFORM_MOBILE_TITLE = 'Multiplatform Mobile';
4
6
  const MULTIPLATFORM_MOBILE_URL = `/lp/mobile/`;
@@ -32,6 +34,9 @@ const KOTLIN_DOCS_URL = `/docs/home.html`;
32
34
  const KMM_DOCS_TITLE = 'KMM';
33
35
  const KMM_DOCS_URL = `/docs/mobile/home.html`;
34
36
  const navScheme = [{
37
+ title: HOME_TITLE,
38
+ url: HOME_URL
39
+ }, {
35
40
  title: SOLUTIONS_TITLE,
36
41
  url: null,
37
42
  items: [{
@@ -80,8 +85,9 @@ const navScheme = [{
80
85
  }]
81
86
  }];
82
87
 
83
- function getNavScheme(isUrlActive = (url, currentUrl) => url === currentUrl, currentUrl, isPlayground) {
84
- return navScheme.map(({
88
+ function getNavScheme(isUrlActive = (url, currentUrl) => url === currentUrl, currentUrl, isPlayground, withoutHomeSection) {
89
+ const controlledNavScheme = withoutHomeSection ? navScheme.slice(1) : navScheme;
90
+ return controlledNavScheme.map(({
85
91
  title,
86
92
  url,
87
93
  items
@@ -132,4 +138,4 @@ function makeExternalUrl(url, currentUrl, isPlayground) {
132
138
  return url;
133
139
  }
134
140
 
135
- export { ANDROID_TITLE, ANDROID_URL, COMMUNITY_TITLE, COMMUNITY_URL, DATA_SCIENCE_TITLE, DATA_SCIENCE_URL, DOCS_TITLE, DOCS_URL, KMM_DOCS_TITLE, KMM_DOCS_URL, KOTLIN_DOCS_TITLE, KOTLIN_DOCS_URL, MULTIPLATFORM_MOBILE_TITLE, MULTIPLATFORM_MOBILE_URL, MULTIPLATFORM_OTHERS_TITLE, MULTIPLATFORM_OTHERS_URL, PLAY_EXAMPLES_TITLE, PLAY_EXAMPLES_URL, PLAY_HANDSON_TITLE, PLAY_HANDSON_URL, PLAY_KOANS_TITLE, PLAY_KOANS_URL, PLAY_TITLE, PLAY_TITLE_FULL, PLAY_URL, SERVER_SIDE_TITLE, SERVER_SIDE_URL, SOLUTIONS_TITLE, TEACH_TITLE, TEACH_URL, WEB_FRONTEND_TITLE, WEB_FRONTEND_URL, getNavScheme };
141
+ export { ANDROID_TITLE, ANDROID_URL, COMMUNITY_TITLE, COMMUNITY_URL, DATA_SCIENCE_TITLE, DATA_SCIENCE_URL, DOCS_TITLE, DOCS_URL, HOME_TITLE, HOME_URL, KMM_DOCS_TITLE, KMM_DOCS_URL, KOTLIN_DOCS_TITLE, KOTLIN_DOCS_URL, MULTIPLATFORM_MOBILE_TITLE, MULTIPLATFORM_MOBILE_URL, MULTIPLATFORM_OTHERS_TITLE, MULTIPLATFORM_OTHERS_URL, PLAY_EXAMPLES_TITLE, PLAY_EXAMPLES_URL, PLAY_HANDSON_TITLE, PLAY_HANDSON_URL, PLAY_KOANS_TITLE, PLAY_KOANS_URL, PLAY_TITLE, PLAY_TITLE_FULL, PLAY_URL, SERVER_SIDE_TITLE, SERVER_SIDE_URL, SOLUTIONS_TITLE, TEACH_TITLE, TEACH_URL, WEB_FRONTEND_TITLE, WEB_FRONTEND_URL, getNavScheme };
@@ -2,13 +2,15 @@ import React__default from 'react';
2
2
  import styles from './search-button.module.pcss.js';
3
3
  import classNames from 'classnames';
4
4
  import SvgSearch from './search.svg.js';
5
+ import { SearchIcon } from '@rescui/icons';
6
+ import Button from '@rescui/button';
5
7
  const DATA_TEST_HEADER_SEARCH_BUTTON = 'header-search-button';
6
8
 
7
9
  const SearchButton = ({
8
10
  onClick,
9
11
  isActive
10
12
  }) => {
11
- return React__default.createElement("button", {
13
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement("button", {
12
14
  type: "button",
13
15
  className: classNames(styles.button, {
14
16
  [styles.active]: isActive
@@ -16,7 +18,16 @@ const SearchButton = ({
16
18
  "data-test": DATA_TEST_HEADER_SEARCH_BUTTON,
17
19
  "aria-label": "Search",
18
20
  onClick: onClick
19
- }, React__default.createElement(SvgSearch, null));
21
+ }, React__default.createElement(SvgSearch, null)), React__default.createElement("div", {
22
+ className: styles.mobileButton
23
+ }, React__default.createElement(Button, {
24
+ "data-test": DATA_TEST_HEADER_SEARCH_BUTTON,
25
+ "aria-label": "Search",
26
+ onClick: onClick,
27
+ mode: 'clear',
28
+ size: 'l',
29
+ icon: React__default.createElement(SearchIcon, null)
30
+ })));
20
31
  };
21
32
 
22
33
  export { DATA_TEST_HEADER_SEARCH_BUTTON, SearchButton };
@@ -1,5 +1,6 @@
1
1
  var styles = {
2
2
  "button": "ktl-search-button-module_button_YHJPv",
3
- "active": "ktl-search-button-module_active_lUmdh"
3
+ "active": "ktl-search-button-module_active_lUmdh",
4
+ "mobileButton": "ktl-search-button-module_mobileButton_KT2YP"
4
5
  };
5
6
  export { styles as default };
@@ -14,7 +14,8 @@
14
14
  --ktl-overlay-z-index: 900;
15
15
  --ktl-top-menu-z-index: 905;
16
16
  --ktl-header-z-index: 906;
17
- --ktl-header-height-mobile: 48px;
17
+ --ktl-mobile-dropdown-list-z-index: 907;
18
+ --ktl-header-height-mobile: 52px;
18
19
  --ktl-font-family-inter: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Droid Sans', 'Helvetica Neue', Arial, sans-serif;
19
20
  --rs-font-family-ui: var(--ktl-font-family-inter);
20
21
  }
@@ -30,15 +31,14 @@
30
31
  height: 64px;
31
32
  background: #ffffff;
32
33
  padding: 0 32px;
33
- z-index: var(--ktl-top-menu-z-index);
34
- box-shadow: inset 0 -1px 0 0 var(--ktl-light-dark-20);
34
+ box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.3);
35
35
  transition: color var(--ktl-transition-fast),
36
36
  background-color var(--ktl-transition-fast);
37
37
  }
38
38
 
39
39
  .ktl-top-menu-module_top-menu-dark-theme_aNBxr {
40
40
  background: #1b1b1b;
41
- box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.2);
41
+ box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.3);
42
42
  }
43
43
 
44
44
  .ktl-top-menu-module_logo_CNH2W {
@@ -49,8 +49,8 @@
49
49
 
50
50
  @media (max-width: 640px) {
51
51
  .ktl-top-menu-module_top-menu_PRX9X {
52
- height: 48px;
53
- padding: 0 16px;
52
+ height: var(--ktl-header-height-mobile);
53
+ padding: 0 6px 0 4px;
54
54
  grid-gap: 16px;
55
55
  grid-template-columns: 1fr auto;
56
56
  }
@@ -76,12 +76,6 @@
76
76
  color: var(--ktl-color-primary-light-theme);
77
77
  }
78
78
 
79
- @media (max-width: 640px) {
80
- .ktl-horizontal-menu-module_horizontal-menu_pB2-S {
81
- display: none;
82
- }
83
- }
84
-
85
79
  :root {
86
80
  --ktl-light-grey: #f4f4f4;
87
81
  --ktl-dark-100: rgba(39, 40, 44, 1);
@@ -98,140 +92,113 @@
98
92
  --ktl-overlay-z-index: 900;
99
93
  --ktl-top-menu-z-index: 905;
100
94
  --ktl-header-z-index: 906;
101
- --ktl-header-height-mobile: 48px;
95
+ --ktl-mobile-dropdown-list-z-index: 907;
96
+ --ktl-header-height-mobile: 52px;
102
97
  --ktl-font-family-inter: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Droid Sans', 'Helvetica Neue', Arial, sans-serif;
103
98
  --rs-font-family-ui: var(--ktl-font-family-inter);
104
99
  }
105
100
 
106
- .ktl-dropdown-menu-module_dropdown-menu_tq2uU {
107
- display: none;
108
- height: 100%;
109
- justify-self: flex-start;
110
- white-space: nowrap;
111
- min-width: 0;
112
- max-width: 100%;
113
- }
114
-
115
- .ktl-dropdown-menu-module_button_OYsuv {
116
- border: none;
117
- background: none;
118
- height: 100%;
119
- max-width: 100%;
120
- padding: 0;
121
- margin: 0;
122
- display: flex;
123
- align-items: center;
124
- justify-content: space-between;
125
- cursor: pointer;
126
- }
127
-
128
- .ktl-dropdown-menu-module_button-text_SJmh- {
129
- overflow: hidden;
130
- text-overflow: ellipsis;
131
- flex: 0 1 auto;
132
- }
133
-
134
- .ktl-dropdown-menu-module_icon_GGhMI {
135
- width: 12px;
136
- height: 6px;
137
- margin-left: 6px;
138
- transition: transform ease-in-out var(--ktl-transition-xfast);
139
- flex: 0 0 auto;
101
+ .ktl-vertical-menu-module_vertical-menu_aLIbw {
102
+ display: block;
103
+ height: 100%;
104
+ justify-self: flex-start;
105
+ white-space: nowrap;
106
+ width: 100%;
107
+ min-width: 0;
108
+ max-width: 100%;
109
+ }
110
+
111
+ .ktl-vertical-menu-module_button_zqr20 {
112
+ border: none;
113
+ background: none;
114
+ height: 52px;
115
+ width: 100%;
116
+ max-width: 100%;
117
+ padding: 0 0 0 12px;
118
+ margin: 0;
119
+ display: flex;
120
+ align-items: center;
121
+ cursor: pointer;
122
+ color: #fff;
140
123
  }
141
124
 
142
- .ktl-dropdown-menu-module_dropdown-list_Ylkvt {
143
- display: none;
144
- position: absolute;
145
- left: 0;
146
- right: 0;
147
- background: #ffffff;
148
- opacity: 0;
149
- -webkit-animation: ktl-dropdown-menu-module_fadein_MySnq ease-out var(--ktl-transition-fast) forwards;
150
- animation: ktl-dropdown-menu-module_fadein_MySnq ease-out var(--ktl-transition-fast) forwards;
125
+ .ktl-vertical-menu-module_button-text_aXith {
126
+ overflow: hidden;
127
+ text-overflow: ellipsis;
128
+ flex: 0 1 auto;
151
129
  }
152
130
 
153
- .ktl-dropdown-menu-module_dropdown-item_X3tZ- {
154
- padding: 8px 16px;
155
- text-decoration: none;
156
- transition: color var(--ktl-transition-xfast),
157
- background-color var(--ktl-transition-xfast);
131
+ .ktl-vertical-menu-module_icon_-Ieat {
132
+ width: 14px;
133
+ height: 8px;
134
+ margin-left: 13px;
135
+ transition: transform ease-in-out var(--ktl-transition-xfast);
136
+ flex: 0 0 auto;
158
137
  }
159
138
 
160
- .ktl-dropdown-menu-module_dropdown-item_X3tZ-:hover {
161
- background: rgba(39, 40, 44, 0.1);
162
- color: #27282c;
163
- }
164
-
165
- .ktl-dropdown-menu-module_dropdown-item_X3tZ-.ktl-dropdown-menu-module_dropdown-item-active_99q9X {
166
- background: var(--ktl-dark-100);
139
+ .ktl-vertical-menu-module_dropdown-header_77lTy {
140
+ /* workaround */
141
+ margin-top: calc(var(--ktl-header-height-mobile) * -1);
142
+ display: flex;
167
143
  color: #ffffff;
168
- }
169
-
170
- .ktl-dropdown-menu-module_overlay_segRo {
171
- display: none;
172
- position: fixed;
173
- top: 0;
174
- right: 0;
175
- bottom: 0;
176
- left: 0;
177
- width: 100%;
178
- height: 100%;
179
- opacity: 0;
180
- background-color: var(--ktl-color-dark-40);
181
- z-index: var(--ktl-overlay-z-index);
182
- -webkit-animation: ktl-dropdown-menu-module_fadein_MySnq ease-out var(--ktl-transition-fast) forwards;
183
- animation: ktl-dropdown-menu-module_fadein_MySnq ease-out var(--ktl-transition-fast) forwards;
184
- }
185
-
186
- .ktl-dropdown-menu-module_overlay-visible_MjwEF {
187
- display: block;
188
- opacity: 1;
189
- }
190
-
191
- .ktl-dropdown-menu-module_dropdown-menu-expanded_EQefy .ktl-dropdown-menu-module_icon_GGhMI {
192
- transform: scale(1, -1);
193
- }
144
+ align-items: center;
145
+ height: var(--ktl-header-height-mobile);
146
+ padding: 0 0 0 16px;
147
+ border-bottom: 1px solid rgba(255, 255, 255, 0.3);
148
+ justify-content: space-between;
149
+ background: #ffffff;
150
+ margin-bottom: 8px;
151
+ }
194
152
 
195
- .ktl-dropdown-menu-module_dropdown-menu-expanded_EQefy .ktl-dropdown-menu-module_dropdown-list_Ylkvt {
153
+ .ktl-vertical-menu-module_dropdown-list_N3KWV {
196
154
  display: flex;
197
155
  flex-direction: column;
198
156
  opacity: 1;
199
- }
200
-
201
- .ktl-dropdown-menu-module_dropdown-list-dark-theme_P60ol {
202
- background: var(--ktl-dark-bg-hard);
157
+ position: fixed;
158
+ top: 0;
159
+ left: 0;
160
+ right: 0;
161
+ bottom: 0;
162
+ background: #ffffff;
163
+ z-index: var(--ktl-mobile-dropdown-list-z-index);
164
+ }
165
+
166
+ .ktl-vertical-menu-module_dropdown-item_XLfp4 {
167
+ padding: 12px 16px;
168
+ text-decoration: none;
169
+ transition: color var(--ktl-transition-xfast),
170
+ background-color var(--ktl-transition-xfast);
203
171
  }
204
172
 
205
- .ktl-dropdown-menu-module_dropdown-list-dark-theme_P60ol .ktl-dropdown-menu-module_dropdown-item_X3tZ-:hover {
206
- background: rgba(255, 255, 255, 0.1);
207
- color: #ffffff;
173
+ .ktl-vertical-menu-module_dropdown-item_XLfp4:hover {
174
+ background: rgba(39, 40, 44, 0.1);
175
+ color: #27282c;
208
176
  }
209
177
 
210
- .ktl-dropdown-menu-module_dropdown-list-dark-theme_P60ol .ktl-dropdown-menu-module_dropdown-item_X3tZ-.ktl-dropdown-menu-module_dropdown-item-active_99q9X {
211
- color: var(--ktl-light-text-hard);
212
- background: #ffffff;
178
+ .ktl-vertical-menu-module_dropdown-item_XLfp4.ktl-vertical-menu-module_dropdown-item-active_iBUbj {
179
+ background: var(--ktl-dark-100);
180
+ color: #ffffff;
213
181
  }
214
182
 
215
- @media (max-width: 640px) {
216
- .ktl-dropdown-menu-module_dropdown-menu_tq2uU {
217
- display: block;
218
- }
219
- }
183
+ .ktl-vertical-menu-module_vertical-menu-expanded_kFaaI .ktl-vertical-menu-module_icon_-Ieat {
184
+ transform: scale(1, -1);
185
+ }
220
186
 
221
- @-webkit-keyframes ktl-dropdown-menu-module_fadein_MySnq {
222
- 0% {
223
- opacity: 0;
224
- }
225
- 100% {
226
- opacity: 1;
227
- }
187
+ .ktl-vertical-menu-module_dropdown-list-dark-theme_A1-Bw {
188
+ background: rgba(39, 40, 44, 1);
228
189
  }
229
190
 
230
- @keyframes ktl-dropdown-menu-module_fadein_MySnq {
231
- 0% {
232
- opacity: 0;
233
- }
234
- 100% {
235
- opacity: 1;
236
- }
237
- }
191
+ .ktl-vertical-menu-module_dropdown-list-dark-theme_A1-Bw .ktl-vertical-menu-module_dropdown-header_77lTy {
192
+ background: rgba(39, 40, 44, 1);
193
+ }
194
+
195
+ .ktl-vertical-menu-module_dropdown-list-dark-theme_A1-Bw .ktl-vertical-menu-module_dropdown-item_XLfp4:hover {
196
+ background: rgba(255, 255, 255, 0.1);
197
+ color: #ffffff;
198
+ }
199
+
200
+ .ktl-vertical-menu-module_dropdown-list-dark-theme_A1-Bw .ktl-vertical-menu-module_dropdown-item_XLfp4.ktl-vertical-menu-module_dropdown-item-active_iBUbj {
201
+ color: var(--ktl-light-text-hard);
202
+ background: #ffffff;
203
+ }
204
+
@@ -1,12 +1,13 @@
1
- import React__default from 'react';
1
+ import React__default, { forwardRef, useRef, useImperativeHandle, useState, useLayoutEffect } from 'react';
2
2
  import { useTheme } from '@rescui/ui-contexts';
3
3
  import classNames from 'classnames';
4
4
  import styles from './top-menu.module.pcss.js';
5
5
  import { useTextStyles } from '@rescui/typography';
6
6
  import { HorizontalMenu } from './horizontal-menu/horizontal-menu.js';
7
- import { DropdownMenu } from './dropdown-menu/dropdown-menu.js';
8
-
9
- const TopMenu = ({
7
+ import { VerticalMenu } from './vertical-menu/vertical-menu.js';
8
+ import useResizeObserver from '@react-hook/resize-observer';
9
+ const BREAKPOINT_XS = 640;
10
+ const TopMenu = forwardRef(({
10
11
  homeUrl,
11
12
  title,
12
13
  mobileTitle,
@@ -15,33 +16,39 @@ const TopMenu = ({
15
16
  linkHandler = () => {},
16
17
  className,
17
18
  children,
18
- forwardedRef,
19
19
  mobileOverview
20
- }) => {
20
+ }, forwardedRef) => {
21
21
  const theme = useTheme();
22
22
  const textCn = useTextStyles();
23
+ const menuRef = useRef(null);
24
+ useImperativeHandle(forwardedRef, () => menuRef.current);
25
+ const [isMobileMenuVisible, setMobileMenuVisible] = useState(false);
26
+ useLayoutEffect(() => {
27
+ setMobileMenuVisible((menuRef.current?.getBoundingClientRect?.().width ?? 0) <= BREAKPOINT_XS);
28
+ }, [menuRef]);
29
+ useResizeObserver(menuRef, entry => setMobileMenuVisible(entry.contentRect.width <= BREAKPOINT_XS));
23
30
  return React__default.createElement("div", {
31
+ ref: menuRef,
24
32
  className: classNames(styles.topMenu, className, {
25
33
  [styles.topMenuDarkTheme]: theme === 'dark'
26
- }),
27
- ref: forwardedRef
34
+ })
28
35
  }, React__default.createElement("a", {
29
36
  href: homeUrl,
30
37
  className: classNames(styles.logo, textCn('rs-h3')),
31
38
  onClick: event => linkHandler(event, homeUrl)
32
- }, title), React__default.createElement(DropdownMenu, {
39
+ }, title), isMobileMenuVisible ? React__default.createElement(VerticalMenu, {
33
40
  items: items,
34
41
  activeIndex: activeIndex,
35
42
  linkHandler: linkHandler,
36
43
  title: title,
37
44
  mobileTitle: mobileTitle,
38
45
  homeUrl: homeUrl,
39
- mobileOverview: mobileOverview
40
- }), React__default.createElement(HorizontalMenu, {
46
+ mobileOverview: mobileOverview,
47
+ topMenuRef: menuRef
48
+ }) : React__default.createElement(HorizontalMenu, {
41
49
  items: items,
42
50
  activeIndex: activeIndex,
43
51
  linkHandler: linkHandler
44
52
  }), children);
45
- };
46
-
53
+ });
47
54
  export { TopMenu };
@@ -0,0 +1,123 @@
1
+ import React__default, { useState, useCallback, useEffect, useRef, useLayoutEffect } from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './vertical-menu.module.pcss.js';
4
+ import { useTextStyles } from '@rescui/typography';
5
+ import SvgArrowDropdownIcon from './arrow-dropdown-icon.svg.js';
6
+ import { useTheme } from '@rescui/ui-contexts';
7
+ import Button from '@rescui/button';
8
+ import { CloseIcon } from '@rescui/icons';
9
+ import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
10
+ import { createPortal } from 'react-dom';
11
+
12
+ const VerticalMenu = ({
13
+ homeUrl,
14
+ title,
15
+ mobileTitle = 'Overview',
16
+ items,
17
+ activeIndex,
18
+ linkHandler,
19
+ mobileOverview = true,
20
+ topMenuRef
21
+ }) => {
22
+ const textCn = useTextStyles();
23
+
24
+ let _items = (mobileOverview ? [{
25
+ title: mobileTitle,
26
+ url: homeUrl
27
+ }] : []).concat(items);
28
+
29
+ const _activeIndex = mobileOverview ? activeIndex + 1 : activeIndex;
30
+
31
+ const activeItem = _items[_activeIndex];
32
+ const [isExpanded, setIsExpanded] = useState(false);
33
+ const [portalRoot, setPortalRoot] = useState(null);
34
+ const handleOpen = useCallback(() => {
35
+ setIsExpanded(true);
36
+ }, []);
37
+ const handleClose = useCallback(() => {
38
+ setIsExpanded(false);
39
+ }, []);
40
+ useEffect(() => {
41
+ if (typeof document !== `undefined`) {
42
+ setPortalRoot(document.body);
43
+ }
44
+ }, []);
45
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
46
+ className: classNames(styles.dropdownMenu, {
47
+ [styles.dropdownMenuExpanded]: isExpanded
48
+ })
49
+ }, React__default.createElement("button", {
50
+ className: classNames(styles.button),
51
+ "aria-haspopup": "true",
52
+ onClick: handleOpen
53
+ }, React__default.createElement("span", {
54
+ className: textCn('rs-text-2', {
55
+ hardness: 'hard'
56
+ })
57
+ }, activeItem.title), React__default.createElement(SvgArrowDropdownIcon, {
58
+ className: styles.icon
59
+ })), !!portalRoot && isExpanded && createPortal(React__default.createElement(VerticalMenuDropDown, {
60
+ title: title,
61
+ activeIndex: _activeIndex,
62
+ items: _items,
63
+ onClose: handleClose,
64
+ linkHandler: linkHandler,
65
+ topMenuRef: topMenuRef
66
+ }), portalRoot)));
67
+ };
68
+
69
+ const VerticalMenuDropDown = ({
70
+ title,
71
+ onClose,
72
+ items,
73
+ linkHandler,
74
+ activeIndex,
75
+ topMenuRef
76
+ }) => {
77
+ const textCn = useTextStyles();
78
+ const theme = useTheme();
79
+ const navRef = useRef(null);
80
+ const [navStyle, setNavStyle] = useState({});
81
+ useEffect(() => {
82
+ if (navRef.current) {
83
+ disableBodyScroll(navRef.current);
84
+ }
85
+
86
+ return clearAllBodyScrollLocks;
87
+ }, []);
88
+ useLayoutEffect(() => {
89
+ if (topMenuRef.current) {
90
+ setNavStyle({
91
+ top: topMenuRef.current.getBoundingClientRect().top
92
+ });
93
+ }
94
+ }, [topMenuRef]);
95
+ return React__default.createElement("nav", {
96
+ ref: navRef,
97
+ style: navStyle,
98
+ className: classNames(styles.dropdownList, {
99
+ [styles.dropdownListDarkTheme]: theme === 'dark'
100
+ })
101
+ }, React__default.createElement("div", {
102
+ className: styles.dropdownHeader
103
+ }, React__default.createElement("div", {
104
+ className: textCn('rs-text-2')
105
+ }, title), React__default.createElement(Button, {
106
+ mode: 'clear',
107
+ size: 'l',
108
+ icon: React__default.createElement(CloseIcon, null),
109
+ onClick: onClose
110
+ })), items.map((item, index) => React__default.createElement("a", {
111
+ key: item.url,
112
+ href: item.url,
113
+ className: classNames(styles.dropdownItem, textCn('rs-text-1', {
114
+ hardness: 'hard'
115
+ }), {
116
+ [styles.dropdownItemActive]: index === activeIndex
117
+ }),
118
+ onClick: event => linkHandler?.(event, item.url),
119
+ target: item.isExternal ? '_blank' : undefined
120
+ }, item.title)));
121
+ };
122
+
123
+ export { VerticalMenu };
@@ -0,0 +1,13 @@
1
+ var styles = {
2
+ "verticalMenu": "ktl-vertical-menu-module_vertical-menu_aLIbw",
3
+ "button": "ktl-vertical-menu-module_button_zqr20",
4
+ "buttonText": "ktl-vertical-menu-module_button-text_aXith",
5
+ "icon": "ktl-vertical-menu-module_icon_-Ieat",
6
+ "dropdownHeader": "ktl-vertical-menu-module_dropdown-header_77lTy",
7
+ "dropdownList": "ktl-vertical-menu-module_dropdown-list_N3KWV",
8
+ "dropdownItem": "ktl-vertical-menu-module_dropdown-item_XLfp4",
9
+ "dropdownItemActive": "ktl-vertical-menu-module_dropdown-item-active_iBUbj",
10
+ "verticalMenuExpanded": "ktl-vertical-menu-module_vertical-menu-expanded_kFaaI",
11
+ "dropdownListDarkTheme": "ktl-vertical-menu-module_dropdown-list-dark-theme_A1-Bw"
12
+ };
13
+ export { styles as default };
@@ -14,7 +14,8 @@
14
14
  --ktl-overlay-z-index: 900;
15
15
  --ktl-top-menu-z-index: 905;
16
16
  --ktl-header-z-index: 906;
17
- --ktl-header-height-mobile: 48px;
17
+ --ktl-mobile-dropdown-list-z-index: 907;
18
+ --ktl-header-height-mobile: 52px;
18
19
  --ktl-font-family-inter: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Droid Sans', 'Helvetica Neue', Arial, sans-serif;
19
20
  --rs-font-family-ui: var(--ktl-font-family-inter);
20
21
  }
@@ -14,7 +14,8 @@
14
14
  --ktl-overlay-z-index: 900;
15
15
  --ktl-top-menu-z-index: 905;
16
16
  --ktl-header-z-index: 906;
17
- --ktl-header-height-mobile: 48px;
17
+ --ktl-mobile-dropdown-list-z-index: 907;
18
+ --ktl-header-height-mobile: 52px;
18
19
  --ktl-font-family-inter: Inter, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Droid Sans', 'Helvetica Neue', Arial, sans-serif;
19
20
  --rs-font-family-ui: var(--ktl-font-family-inter);
20
21
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jetbrains/kotlin-web-site-ui",
3
3
  "description": "UI components for Kotlin web sites development",
4
- "version": "4.3.0",
4
+ "version": "4.4.0-alpha.0",
5
5
  "license": "Apache-2.0",
6
6
  "author": "JetBrains",
7
7
  "files": [
@@ -1,35 +0,0 @@
1
- import * as React from 'react';
2
-
3
- var _path;
4
-
5
- function _extends() {
6
- _extends = Object.assign || function (target) {
7
- for (var i = 1; i < arguments.length; i++) {
8
- var source = arguments[i];
9
-
10
- for (var key in source) {
11
- if (Object.prototype.hasOwnProperty.call(source, key)) {
12
- target[key] = source[key];
13
- }
14
- }
15
- }
16
-
17
- return target;
18
- };
19
-
20
- return _extends.apply(this, arguments);
21
- }
22
-
23
- const SvgCloseIcon = props => /*#__PURE__*/React.createElement("svg", _extends({
24
- width: 16,
25
- height: 16,
26
- fill: "none",
27
- xmlns: "http://www.w3.org/2000/svg"
28
- }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
29
- fillRule: "evenodd",
30
- clipRule: "evenodd",
31
- d: "M15.707 1.707 14.293.293 8 6.586 1.707.293.293 1.707 6.586 8 .293 14.293l1.414 1.414L8 9.414l6.293 6.293 1.414-1.414L9.414 8l6.293-6.293Z",
32
- fill: "currentColor"
33
- })));
34
-
35
- export { SvgCloseIcon as default };
@@ -1,35 +0,0 @@
1
- import * as React from 'react';
2
-
3
- var _path;
4
-
5
- function _extends() {
6
- _extends = Object.assign || function (target) {
7
- for (var i = 1; i < arguments.length; i++) {
8
- var source = arguments[i];
9
-
10
- for (var key in source) {
11
- if (Object.prototype.hasOwnProperty.call(source, key)) {
12
- target[key] = source[key];
13
- }
14
- }
15
- }
16
-
17
- return target;
18
- };
19
-
20
- return _extends.apply(this, arguments);
21
- }
22
-
23
- const SvgHamburgerIcon = props => /*#__PURE__*/React.createElement("svg", _extends({
24
- width: 24,
25
- height: 24,
26
- fill: "none",
27
- xmlns: "http://www.w3.org/2000/svg"
28
- }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
29
- fillRule: "evenodd",
30
- clipRule: "evenodd",
31
- d: "M4 5h16v2H4V5Zm0 6h16v2H4v-2Zm16 6H4v2h16v-2Z",
32
- fill: "currentColor"
33
- })));
34
-
35
- export { SvgHamburgerIcon as default };