@jetbrains/kotlin-web-site-ui 0.0.0-foundation-changes.1
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/CHANGELOG.md +61 -0
- package/LICENSE.txt +202 -0
- package/README.md +16 -0
- package/out/blocks/formik-wrapper/index.css +8 -0
- package/out/blocks/formik-wrapper/index.js +4 -0
- package/out/blocks/formik-wrapper/input.js +39 -0
- package/out/blocks/formik-wrapper/privacy-checkbox.js +48 -0
- package/out/blocks/formik-wrapper/privacy-notice.js +40 -0
- package/out/blocks/formik-wrapper/privacy-notice.module.pcss.js +6 -0
- package/out/blocks/formik-wrapper/submit-button.js +21 -0
- package/out/components/breakpoints/constants.js +20 -0
- package/out/components/breakpoints/hooks.js +32 -0
- package/out/components/breakpoints/index.js +2 -0
- package/out/components/breakpoints/media.pcss +14 -0
- package/out/components/cta-block/index.css +254 -0
- package/out/components/cta-block/index.js +7 -0
- package/out/components/cta-block/v1/cta-block.js +29 -0
- package/out/components/cta-block/v1/cta-block.module.pcss.js +8 -0
- package/out/components/footer/footer.js +55 -0
- package/out/components/footer/footer.module.pcss.js +13 -0
- package/out/components/footer/index.css +290 -0
- package/out/components/footer/index.js +3 -0
- package/out/components/footer/logo/jetbrains-logo.svg.js +38 -0
- package/out/components/footer/logo/logo.js +12 -0
- package/out/components/footer/logo/logo.module.pcss.js +4 -0
- package/out/components/footer/nav/nav-data.js +30 -0
- package/out/components/footer/nav/nav-item.js +27 -0
- package/out/components/footer/nav/nav-item.module.pcss.js +5 -0
- package/out/components/footer/nav/nav-list.js +15 -0
- package/out/components/footer/nav/nav-list.module.pcss.js +4 -0
- package/out/components/footer/social-list/social-data.js +38 -0
- package/out/components/footer/social-list/social-item/social-item.js +21 -0
- package/out/components/footer/social-list/social-item/social-item.module.pcss.js +5 -0
- package/out/components/footer/social-list/social-list.js +13 -0
- package/out/components/footer/social-list/social-list.module.pcss.js +4 -0
- package/out/components/footer/social-list/svg/github-logo.svg.js +35 -0
- package/out/components/footer/social-list/svg/reddit-logo.svg.js +33 -0
- package/out/components/footer/social-list/svg/slack-logo.svg.js +33 -0
- package/out/components/footer/social-list/svg/stackoverflow-logo.svg.js +36 -0
- package/out/components/footer/social-list/svg/twitter-logo.svg.js +33 -0
- package/out/components/footer/social-list/svg/youtube-logo.svg.js +35 -0
- package/out/components/grid/index.css +1081 -0
- package/out/components/grid/index.js +1 -0
- package/out/components/header/consts.js +3 -0
- package/out/components/header/full-search/chapters/chapters.js +59 -0
- package/out/components/header/full-search/chapters/chapters.module.pcss.js +12 -0
- package/out/components/header/full-search/empty/empty.js +22 -0
- package/out/components/header/full-search/empty/empty.module.pcss.js +6 -0
- package/out/components/header/full-search/empty/full-search-empty.svg.js +1539 -0
- package/out/components/header/full-search/full-search.js +115 -0
- package/out/components/header/full-search/full-search.module.pcss.js +10 -0
- package/out/components/header/full-search/hit-list/get-extended-hits.js +55 -0
- package/out/components/header/full-search/hit-list/hit-list.js +49 -0
- package/out/components/header/full-search/hit-list/hit-list.module.pcss.js +6 -0
- package/out/components/header/full-search/loading/loading.js +13 -0
- package/out/components/header/full-search/loading/loading.module.pcss.js +4 -0
- package/out/components/header/full-search/results-list/results-list.js +25 -0
- package/out/components/header/header.js +121 -0
- package/out/components/header/header.module.pcss.js +5 -0
- package/out/components/header/horizontal-menu/horizontal-menu.js +101 -0
- package/out/components/header/horizontal-menu/horizontal-menu.module.pcss.js +16 -0
- package/out/components/header/index.css +949 -0
- package/out/components/header/index.js +4 -0
- package/out/components/header/is-macos.js +5 -0
- package/out/components/header/key-codes.js +3 -0
- package/out/components/header/logo-large/kotlin-logo-large.svg.js +55 -0
- package/out/components/header/logo-large/logo-large.js +34 -0
- package/out/components/header/logo-large/logo-large.module.pcss.js +6 -0
- package/out/components/header/logo-small/kotlin-logo-small.svg.js +49 -0
- package/out/components/header/logo-small/logo-small.js +27 -0
- package/out/components/header/logo-small/logo-small.module.pcss.js +7 -0
- package/out/components/header/menu-popup/menu-button/menu-button.js +23 -0
- package/out/components/header/menu-popup/menu-button/menu-button.module.pcss.js +4 -0
- package/out/components/header/menu-popup/menu-list/menu-list.js +33 -0
- package/out/components/header/menu-popup/menu-list/menu-list.module.pcss.js +4 -0
- package/out/components/header/menu-popup/menu-list-item/menu-list-item.js +28 -0
- package/out/components/header/menu-popup/menu-list-item/menu-list-item.module.pcss.js +7 -0
- package/out/components/header/menu-popup/menu-popup.js +55 -0
- package/out/components/header/menu-popup/menu-popup.module.pcss.js +5 -0
- package/out/components/header/nav-scheme.js +133 -0
- package/out/components/header/quick-search/empty/empty.js +17 -0
- package/out/components/header/quick-search/empty/empty.module.pcss.js +5 -0
- package/out/components/header/quick-search/list/list.js +37 -0
- package/out/components/header/quick-search/list/list.module.pcss.js +7 -0
- package/out/components/header/quick-search/loading/loading.js +14 -0
- package/out/components/header/quick-search/loading/loading.module.pcss.js +4 -0
- package/out/components/header/quick-search/quick-search.js +48 -0
- package/out/components/header/quick-search/quick-search.module.pcss.js +5 -0
- package/out/components/header/quick-search/result/result.js +30 -0
- package/out/components/header/quick-search/result/result.module.pcss.js +6 -0
- package/out/components/header/search-box/search-box.js +76 -0
- package/out/components/header/search-box/search-box.module.pcss.js +7 -0
- package/out/components/header/search-button/search-button.js +32 -0
- package/out/components/header/search-button/search-button.module.pcss.js +5 -0
- package/out/components/header/search-button/search.svg.js +34 -0
- package/out/components/header/search-wrapper/init-search.js +60 -0
- package/out/components/header/search-wrapper/search-const.js +13 -0
- package/out/components/header/search-wrapper/search-context.js +18 -0
- package/out/components/header/search-wrapper/search-with-algolia.js +58 -0
- package/out/components/header/search-wrapper/search-wrapper.js +40 -0
- package/out/components/header/search-wrapper/use-search.js +85 -0
- package/out/components/layout/index.css +52 -0
- package/out/components/layout/index.js +1 -0
- package/out/components/popup/index.css +35 -0
- package/out/components/popup/index.js +3 -0
- package/out/components/popup/popup.js +55 -0
- package/out/components/popup/popup.module.pcss.js +6 -0
- package/out/components/quotes-slider/index.css +83 -0
- package/out/components/quotes-slider/index.js +3 -0
- package/out/components/quotes-slider/quote.svg.js +33 -0
- package/out/components/quotes-slider/quotes-slider.js +85 -0
- package/out/components/quotes-slider/quotes-slider.module.pcss.js +13 -0
- package/out/components/top-menu/horizontal-menu/horizontal-menu.js +44 -0
- package/out/components/top-menu/horizontal-menu/horizontal-menu.module.pcss.js +6 -0
- package/out/components/top-menu/index.css +232 -0
- package/out/components/top-menu/index.js +3 -0
- package/out/components/top-menu/top-menu.js +54 -0
- package/out/components/top-menu/top-menu.module.pcss.js +6 -0
- package/out/components/top-menu/vertical-menu/arrow-dropdown-icon.svg.js +34 -0
- package/out/components/top-menu/vertical-menu/vertical-menu.js +129 -0
- package/out/components/top-menu/vertical-menu/vertical-menu.module.pcss.js +14 -0
- package/out/components/typography/create-text-cn.js +26 -0
- package/out/components/typography/hooks.js +6 -0
- package/out/components/typography/index.css +192 -0
- package/out/components/typography/index.js +3 -0
- package/out/components/youtube-player/index.css +135 -0
- package/out/components/youtube-player/index.js +3 -0
- package/out/components/youtube-player/loading_24.svg.js +31 -0
- package/out/components/youtube-player/play_24.svg.js +31 -0
- package/out/components/youtube-player/utils.js +28 -0
- package/out/components/youtube-player/youtube-player.js +145 -0
- package/out/components/youtube-player/youtube-player.module.pcss.js +16 -0
- package/out/packages/data-services/index.js +9 -0
- package/out/packages/data-services/marketo-submiter.js +62 -0
- package/out/packages/data-services/privacy-consent-ids.json.js +5 -0
- package/out/packages/data-services/privacy-consent-service.js +44 -0
- package/out/packages/data-services/urls.js +4 -0
- package/out/svg/kotlin_64.svg +10 -0
- package/package.json +141 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React__default, { useState, useContext, useRef, useCallback, useLayoutEffect, useEffect } from 'react';
|
|
2
|
+
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
|
|
3
|
+
import useScrollbarSize from 'react-scrollbar-size';
|
|
4
|
+
import { ThemeProvider } from '@rescui/ui-contexts';
|
|
5
|
+
import Input from '@rescui/input';
|
|
6
|
+
import Button from '@rescui/button';
|
|
7
|
+
import Switcher from '@rescui/switcher';
|
|
8
|
+
import { CloseIcon, ErrorIcon } from '@rescui/icons';
|
|
9
|
+
import { useSearch } from '../search-wrapper/use-search.js';
|
|
10
|
+
import { ResultsList } from './results-list/results-list.js';
|
|
11
|
+
import SearchContext from '../search-wrapper/search-context.js';
|
|
12
|
+
import styles from './full-search.module.pcss.js';
|
|
13
|
+
|
|
14
|
+
const FullSearch = ({
|
|
15
|
+
searchString,
|
|
16
|
+
killSearch
|
|
17
|
+
}) => {
|
|
18
|
+
const [isScrollbarCompensated, setIsScrollbarCompensated] = useState(false);
|
|
19
|
+
const [inputValue, setInputValue] = useState(searchString);
|
|
20
|
+
const {
|
|
21
|
+
hits,
|
|
22
|
+
placeholder
|
|
23
|
+
} = useSearch(inputValue, 75);
|
|
24
|
+
const {
|
|
25
|
+
matching,
|
|
26
|
+
matchingOptions,
|
|
27
|
+
setMatching
|
|
28
|
+
} = useContext(SearchContext);
|
|
29
|
+
const ref = useRef(null);
|
|
30
|
+
const headerRef = useRef(null);
|
|
31
|
+
const listRef = useRef(null);
|
|
32
|
+
const isResultsVisible = hits.length > 0 && inputValue;
|
|
33
|
+
const handleSwitcherChange = useCallback(value => {
|
|
34
|
+
setMatching(value);
|
|
35
|
+
}, []);
|
|
36
|
+
const clearSearch = useCallback(() => {
|
|
37
|
+
setInputValue('');
|
|
38
|
+
}, []);
|
|
39
|
+
const handleInputChange = useCallback(e => {
|
|
40
|
+
setInputValue(e.target.value);
|
|
41
|
+
}, [inputValue]); // Scrollbar compensation
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
width
|
|
45
|
+
} = useScrollbarSize();
|
|
46
|
+
useLayoutEffect(() => {
|
|
47
|
+
if (headerRef.current && listRef.current) {
|
|
48
|
+
const countedHeight = headerRef.current.offsetHeight + listRef.current.offsetHeight;
|
|
49
|
+
|
|
50
|
+
if (isResultsVisible) {
|
|
51
|
+
setIsScrollbarCompensated(countedHeight < window.innerWidth);
|
|
52
|
+
} else {
|
|
53
|
+
setIsScrollbarCompensated(true);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, [hits, inputValue]);
|
|
57
|
+
useLayoutEffect(() => {
|
|
58
|
+
if (ref.current) disableBodyScroll(ref.current);
|
|
59
|
+
}, [ref]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
return clearAllBodyScrollLocks;
|
|
62
|
+
}, []);
|
|
63
|
+
return React__default.createElement(ThemeProvider, {
|
|
64
|
+
theme: 'light'
|
|
65
|
+
}, React__default.createElement("div", {
|
|
66
|
+
className: styles.fullSearch,
|
|
67
|
+
style: {
|
|
68
|
+
paddingRight: isScrollbarCompensated ? `${width}px` : 0
|
|
69
|
+
},
|
|
70
|
+
tabIndex: 1000,
|
|
71
|
+
ref: ref,
|
|
72
|
+
"data-test": 'full-search'
|
|
73
|
+
}, React__default.createElement("div", {
|
|
74
|
+
className: styles.header,
|
|
75
|
+
ref: headerRef
|
|
76
|
+
}, React__default.createElement("div", {
|
|
77
|
+
className: styles.closeSearch
|
|
78
|
+
}, React__default.createElement(Button, {
|
|
79
|
+
mode: 'clear',
|
|
80
|
+
size: 'l',
|
|
81
|
+
icon: React__default.createElement(CloseIcon, null),
|
|
82
|
+
onClick: killSearch,
|
|
83
|
+
"data-test": 'close-full-search'
|
|
84
|
+
})), React__default.createElement("div", {
|
|
85
|
+
className: styles.wrapper,
|
|
86
|
+
"data-test": 'full-search-input'
|
|
87
|
+
}, React__default.createElement(Input, {
|
|
88
|
+
placeholder: 'Search',
|
|
89
|
+
value: inputValue,
|
|
90
|
+
onChange: handleInputChange,
|
|
91
|
+
onClear: clearSearch,
|
|
92
|
+
clearIcon: React__default.createElement("button", {
|
|
93
|
+
className: styles.fullSearchClearButton
|
|
94
|
+
}, React__default.createElement(ErrorIcon, {
|
|
95
|
+
size: 'l'
|
|
96
|
+
})),
|
|
97
|
+
size: 'l',
|
|
98
|
+
autoFocus: true
|
|
99
|
+
}), isResultsVisible && React__default.createElement("div", {
|
|
100
|
+
className: styles.switcher
|
|
101
|
+
}, React__default.createElement(Switcher, {
|
|
102
|
+
value: matching,
|
|
103
|
+
onChange: handleSwitcherChange,
|
|
104
|
+
options: matchingOptions,
|
|
105
|
+
size: 'xs'
|
|
106
|
+
})))), React__default.createElement("div", {
|
|
107
|
+
className: styles.wrapper,
|
|
108
|
+
ref: listRef
|
|
109
|
+
}, inputValue && React__default.createElement(ResultsList, {
|
|
110
|
+
placeholder: placeholder,
|
|
111
|
+
hits: hits
|
|
112
|
+
}))));
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export { FullSearch };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var styles = {
|
|
2
|
+
"fullSearch": "ktl-full-search-module_fullSearch_MTU8t",
|
|
3
|
+
"closeSearch": "ktl-full-search-module_closeSearch_5vYDG",
|
|
4
|
+
"fullSearchClearButton": "ktl-full-search-module_fullSearchClearButton_DGS6T",
|
|
5
|
+
"wrapper": "ktl-full-search-module_wrapper_9rxXb",
|
|
6
|
+
"header": "ktl-full-search-module_header_Wltw0",
|
|
7
|
+
"results": "ktl-full-search-module_results_svcSE",
|
|
8
|
+
"switcher": "ktl-full-search-module_switcher_o1RgM"
|
|
9
|
+
};
|
|
10
|
+
export { styles as default };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const groupHitsByPageId = ungroupedHits => ungroupedHits.reduce((groups, currentHit) => {
|
|
2
|
+
const currentGroup = groups.find(group => group.name === currentHit.mainTitle);
|
|
3
|
+
|
|
4
|
+
if (currentGroup) {
|
|
5
|
+
currentGroup.hits.push(currentHit);
|
|
6
|
+
return groups;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const newGroup = {
|
|
10
|
+
name: currentHit.mainTitle,
|
|
11
|
+
hits: [currentHit]
|
|
12
|
+
};
|
|
13
|
+
return [...groups, newGroup];
|
|
14
|
+
}, []);
|
|
15
|
+
|
|
16
|
+
const getChapterName = fullName => fullName.split(':')[1] || fullName;
|
|
17
|
+
|
|
18
|
+
const highlightChaptersTitles = chapters => chapters.map(chapter => ({ ...chapter,
|
|
19
|
+
highlightedTitle: getChapterName(chapter.highlightedTitle)
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const getExtendedHits = hits => {
|
|
23
|
+
try {
|
|
24
|
+
const groupedHits = groupHitsByPageId(hits);
|
|
25
|
+
return groupedHits.map(group => {
|
|
26
|
+
const mainHit = group.hits.find(hit => hit.title === group.name);
|
|
27
|
+
|
|
28
|
+
if (mainHit) {
|
|
29
|
+
const chapters = group.hits.filter(hit => hit.title !== group.name);
|
|
30
|
+
return { ...mainHit,
|
|
31
|
+
title: mainHit.highlightedTitle,
|
|
32
|
+
chapters: highlightChaptersTitles(chapters)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
url,
|
|
38
|
+
breadcrumb,
|
|
39
|
+
...restHitProps
|
|
40
|
+
} = group.hits[0];
|
|
41
|
+
return { ...restHitProps,
|
|
42
|
+
title: group.name,
|
|
43
|
+
url: url.split('#')[0],
|
|
44
|
+
breadcrumb,
|
|
45
|
+
chapters: highlightChaptersTitles(group.hits)
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// reportError(error, { func: 'getExtendedHits' });
|
|
50
|
+
console.log('error');
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { getExtendedHits as default };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { useTextStyles } from '@rescui/typography';
|
|
4
|
+
import getExtendedHits from './get-extended-hits.js';
|
|
5
|
+
import { Chapters } from '../chapters/chapters.js';
|
|
6
|
+
import styles from './hit-list.module.pcss.js';
|
|
7
|
+
|
|
8
|
+
const HitList = ({
|
|
9
|
+
hits
|
|
10
|
+
}) => {
|
|
11
|
+
const textCn = useTextStyles();
|
|
12
|
+
const extendedHits = getExtendedHits(hits);
|
|
13
|
+
return React__default.createElement("div", {
|
|
14
|
+
"data-test": 'full-search-results'
|
|
15
|
+
}, extendedHits.map(({
|
|
16
|
+
title,
|
|
17
|
+
snippet,
|
|
18
|
+
chapters = [],
|
|
19
|
+
url,
|
|
20
|
+
breadcrumb
|
|
21
|
+
}, pageIndex) => {
|
|
22
|
+
const isHitWithChapters = chapters.length > 0;
|
|
23
|
+
return React__default.createElement("div", {
|
|
24
|
+
className: styles.hitList,
|
|
25
|
+
key: pageIndex
|
|
26
|
+
}, React__default.createElement("h3", {
|
|
27
|
+
className: textCn('rs-h3')
|
|
28
|
+
}, React__default.createElement("a", {
|
|
29
|
+
className: classNames(styles.titleLink, textCn('rs-link', {
|
|
30
|
+
mode: 'clear',
|
|
31
|
+
hardness: 'hard'
|
|
32
|
+
})),
|
|
33
|
+
href: url,
|
|
34
|
+
dangerouslySetInnerHTML: {
|
|
35
|
+
__html: title
|
|
36
|
+
}
|
|
37
|
+
})), isHitWithChapters ? React__default.createElement(Chapters, {
|
|
38
|
+
chapters: chapters,
|
|
39
|
+
hitIndex: pageIndex
|
|
40
|
+
}) : React__default.createElement("div", {
|
|
41
|
+
className: classNames(textCn('rs-text-2'), styles.snippet),
|
|
42
|
+
dangerouslySetInnerHTML: {
|
|
43
|
+
__html: snippet
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
}));
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { HitList };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { LoadingIcon } from '@rescui/icons';
|
|
3
|
+
import styles from './loading.module.pcss.js';
|
|
4
|
+
|
|
5
|
+
const FullSearchLoader = () => {
|
|
6
|
+
return React__default.createElement("div", {
|
|
7
|
+
className: styles.loader
|
|
8
|
+
}, React__default.createElement(LoadingIcon, {
|
|
9
|
+
size: 'l'
|
|
10
|
+
}));
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { FullSearchLoader };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
import { FullSearchLoader } from '../loading/loading.js';
|
|
3
|
+
import { FullSearchEmpty } from '../empty/empty.js';
|
|
4
|
+
import { HitList } from '../hit-list/hit-list.js';
|
|
5
|
+
|
|
6
|
+
const ResultsList = ({
|
|
7
|
+
placeholder,
|
|
8
|
+
hits
|
|
9
|
+
}) => {
|
|
10
|
+
if (placeholder) {
|
|
11
|
+
return React__default.createElement(FullSearchEmpty, {
|
|
12
|
+
placeholder: placeholder
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (hits.length) {
|
|
17
|
+
return React__default.createElement(HitList, {
|
|
18
|
+
hits: hits
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return React__default.createElement(FullSearchLoader, null);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { ResultsList };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React__default, { forwardRef, useState, useMemo, useRef, useImperativeHandle, useLayoutEffect, useCallback, useEffect } from 'react';
|
|
2
|
+
import { ThemeProvider } from '@rescui/ui-contexts';
|
|
3
|
+
import FocusManager from '@rescui/focus-manager';
|
|
4
|
+
import useResizeObserver from '@react-hook/resize-observer';
|
|
5
|
+
import OutsideClickHandler from 'react-outside-click-handler';
|
|
6
|
+
import { LogoLarge } from './logo-large/logo-large.js';
|
|
7
|
+
import styles from './header.module.pcss.js';
|
|
8
|
+
import { getNavScheme } from './nav-scheme.js';
|
|
9
|
+
import { HorizontalMenu } from './horizontal-menu/horizontal-menu.js';
|
|
10
|
+
import { SearchButton } from './search-button/search-button.js';
|
|
11
|
+
import { SearchBox } from './search-box/search-box.js';
|
|
12
|
+
import { MenuPopup } from './menu-popup/menu-popup.js';
|
|
13
|
+
import { LogoSmall } from './logo-small/logo-small.js';
|
|
14
|
+
import classNames from 'classnames';
|
|
15
|
+
import { SearchWrapper } from './search-wrapper/search-wrapper.js';
|
|
16
|
+
import { isMacOs } from './is-macos.js';
|
|
17
|
+
import { KEY_K_CODE } from './key-codes.js';
|
|
18
|
+
var SearchResultView;
|
|
19
|
+
|
|
20
|
+
(function (SearchResultView) {
|
|
21
|
+
SearchResultView[SearchResultView["Narrow"] = 0] = "Narrow";
|
|
22
|
+
SearchResultView[SearchResultView["Wide"] = 1] = "Wide";
|
|
23
|
+
})(SearchResultView || (SearchResultView = {}));
|
|
24
|
+
|
|
25
|
+
const MENU_POPUP_BREAKPOINT = 640;
|
|
26
|
+
const Header = forwardRef(({
|
|
27
|
+
productWebUrl,
|
|
28
|
+
hasSearch = false,
|
|
29
|
+
currentUrl,
|
|
30
|
+
currentTitle,
|
|
31
|
+
className,
|
|
32
|
+
hasBorder = true,
|
|
33
|
+
dropdownTheme = 'dark',
|
|
34
|
+
linkHandler,
|
|
35
|
+
isPlayground,
|
|
36
|
+
isUrlActive,
|
|
37
|
+
searchConfig,
|
|
38
|
+
resultViewType = SearchResultView.Narrow
|
|
39
|
+
}, forwardedRef) => {
|
|
40
|
+
const [menuPopupExpanded, setMenuPopupExpanded] = useState(false);
|
|
41
|
+
const [isSearchBoxVisible, setSearchBoxVisible] = useState(false);
|
|
42
|
+
const [fullSearchActive, setFullSearchActive] = useState(false);
|
|
43
|
+
const items = useMemo(() => getNavScheme(isUrlActive, currentUrl, isPlayground), [isUrlActive, currentUrl, isPlayground]);
|
|
44
|
+
const itemsWithoutHomeSection = useMemo(() => items.slice(1), [items]);
|
|
45
|
+
const headerRef = useRef(null);
|
|
46
|
+
useImperativeHandle(forwardedRef, () => headerRef.current);
|
|
47
|
+
const [isMenuPopupVisible, setMenuPopupVisible] = useState(false);
|
|
48
|
+
useLayoutEffect(() => {
|
|
49
|
+
const headerWidth = headerRef.current?.getBoundingClientRect?.().width ?? 0;
|
|
50
|
+
setMenuPopupVisible(!!headerWidth && headerWidth <= MENU_POPUP_BREAKPOINT);
|
|
51
|
+
}, [headerRef]);
|
|
52
|
+
useResizeObserver(headerRef, entry => setMenuPopupVisible(!!entry.contentRect.width && entry.contentRect.width <= MENU_POPUP_BREAKPOINT));
|
|
53
|
+
const handleSearchButtonClick = useCallback(() => {
|
|
54
|
+
setSearchBoxVisible(!isSearchBoxVisible);
|
|
55
|
+
}, []);
|
|
56
|
+
const handleSearchClose = useCallback(() => {
|
|
57
|
+
setSearchBoxVisible(false);
|
|
58
|
+
setFullSearchActive(false);
|
|
59
|
+
}, []);
|
|
60
|
+
const fullSearchKeyHandler = useCallback(event => {
|
|
61
|
+
const isMacOsHotkeyPressed = isMacOs() && event.keyCode === KEY_K_CODE && event.metaKey;
|
|
62
|
+
const isOtherPlatformsHotkeyPressed = !isMacOs() && event.keyCode === KEY_K_CODE && event.ctrlKey;
|
|
63
|
+
|
|
64
|
+
if (isMacOsHotkeyPressed || isOtherPlatformsHotkeyPressed) {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
event.stopPropagation();
|
|
67
|
+
setSearchBoxVisible(true);
|
|
68
|
+
setFullSearchActive(true);
|
|
69
|
+
}
|
|
70
|
+
}, []);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (typeof document !== `undefined` && resultViewType === SearchResultView.Narrow) {
|
|
73
|
+
document.addEventListener('keydown', fullSearchKeyHandler);
|
|
74
|
+
const focusManager = new FocusManager();
|
|
75
|
+
return () => {
|
|
76
|
+
document.removeEventListener('keydown', fullSearchKeyHandler);
|
|
77
|
+
focusManager.destroy();
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}, [fullSearchKeyHandler]);
|
|
81
|
+
return React__default.createElement(ThemeProvider, {
|
|
82
|
+
theme: 'dark'
|
|
83
|
+
}, React__default.createElement(SearchWrapper, {
|
|
84
|
+
searchConfig: searchConfig
|
|
85
|
+
}, React__default.createElement("header", {
|
|
86
|
+
ref: headerRef,
|
|
87
|
+
className: classNames(styles.headerMenu, className, {
|
|
88
|
+
[styles.withMenuPopup]: menuPopupExpanded,
|
|
89
|
+
[styles.border]: hasBorder || menuPopupExpanded
|
|
90
|
+
}),
|
|
91
|
+
"data-test": 'header'
|
|
92
|
+
}, isMenuPopupVisible && currentTitle && currentUrl && !menuPopupExpanded ? React__default.createElement(LogoSmall, {
|
|
93
|
+
homeTitle: currentTitle,
|
|
94
|
+
homeUrl: currentUrl
|
|
95
|
+
}) : React__default.createElement(LogoLarge, {
|
|
96
|
+
productWebUrl: productWebUrl
|
|
97
|
+
}), isSearchBoxVisible ? React__default.createElement(OutsideClickHandler, {
|
|
98
|
+
onOutsideClick: handleSearchClose
|
|
99
|
+
}, React__default.createElement(SearchBox, {
|
|
100
|
+
closeHandler: handleSearchClose,
|
|
101
|
+
isMobile: isMenuPopupVisible,
|
|
102
|
+
fullSearchActive: fullSearchActive,
|
|
103
|
+
setFullSearchActive: setFullSearchActive,
|
|
104
|
+
searchBoxViewType: resultViewType
|
|
105
|
+
})) : React__default.createElement(React__default.Fragment, null, !isMenuPopupVisible && React__default.createElement(HorizontalMenu, {
|
|
106
|
+
items: itemsWithoutHomeSection,
|
|
107
|
+
theme: dropdownTheme,
|
|
108
|
+
linkHandler: linkHandler
|
|
109
|
+
}), !menuPopupExpanded && React__default.createElement(SearchButton, {
|
|
110
|
+
isMobile: isMenuPopupVisible,
|
|
111
|
+
onClick: handleSearchButtonClick,
|
|
112
|
+
isActive: hasSearch
|
|
113
|
+
}), isMenuPopupVisible && React__default.createElement(MenuPopup, {
|
|
114
|
+
items: items,
|
|
115
|
+
setExpand: setMenuPopupExpanded,
|
|
116
|
+
isExpanded: menuPopupExpanded,
|
|
117
|
+
headerRef: headerRef,
|
|
118
|
+
linkHandler: linkHandler
|
|
119
|
+
})))));
|
|
120
|
+
});
|
|
121
|
+
export { Header, SearchResultView };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React__default, { useState, useEffect } from 'react';
|
|
3
|
+
import styles from './horizontal-menu.module.pcss.js';
|
|
4
|
+
import { useTextStyles } from '@rescui/typography';
|
|
5
|
+
|
|
6
|
+
const DropdownMenu = ({
|
|
7
|
+
items,
|
|
8
|
+
isExpanded,
|
|
9
|
+
alignRight,
|
|
10
|
+
linkHandler
|
|
11
|
+
}) => {
|
|
12
|
+
const textCn = useTextStyles();
|
|
13
|
+
return React__default.createElement("ul", {
|
|
14
|
+
className: classNames(styles.dropdownMenu, textCn('rs-text-2'), {
|
|
15
|
+
[styles.dropdownMenuExpanded]: isExpanded,
|
|
16
|
+
[styles.dropdownMenuAlignRight]: alignRight
|
|
17
|
+
})
|
|
18
|
+
}, items.map((item, key) => {
|
|
19
|
+
const Tag = !item.isActive && item.url ? 'a' : 'span';
|
|
20
|
+
return React__default.createElement("li", {
|
|
21
|
+
key: key
|
|
22
|
+
}, React__default.createElement(Tag, {
|
|
23
|
+
className: classNames(styles.dropdownMenuItem, {
|
|
24
|
+
[styles.active]: item.isActive
|
|
25
|
+
}),
|
|
26
|
+
...(item.url ? {
|
|
27
|
+
href: item.url,
|
|
28
|
+
onClick: linkHandler ? event => item.url && linkHandler(event, item.url) : undefined
|
|
29
|
+
} : {})
|
|
30
|
+
}, item.title));
|
|
31
|
+
}));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const HorizontalMenuItem = ({
|
|
35
|
+
item,
|
|
36
|
+
onMouseEnter,
|
|
37
|
+
onMouseLeave,
|
|
38
|
+
isExpanded,
|
|
39
|
+
isLast,
|
|
40
|
+
linkHandler
|
|
41
|
+
}) => {
|
|
42
|
+
const Tag = item.isActive || !item.url ? 'span' : 'a';
|
|
43
|
+
const textCn = useTextStyles();
|
|
44
|
+
|
|
45
|
+
const handleEnter = () => onMouseEnter(item);
|
|
46
|
+
|
|
47
|
+
return React__default.createElement("li", {
|
|
48
|
+
className: styles.menuItemWrap,
|
|
49
|
+
onMouseEnter: handleEnter,
|
|
50
|
+
onMouseLeave: onMouseLeave
|
|
51
|
+
}, React__default.createElement(Tag, { ...(item.url ? {
|
|
52
|
+
href: item.url,
|
|
53
|
+
onClick: linkHandler ? event => item.url && linkHandler(event, item.url) : undefined
|
|
54
|
+
} : {}),
|
|
55
|
+
key: item.title,
|
|
56
|
+
className: classNames(styles.menuItem, textCn('rs-text-2'), {
|
|
57
|
+
[styles.itemActive]: item.isActive,
|
|
58
|
+
[styles.expanded]: isExpanded && !!item.items?.length
|
|
59
|
+
})
|
|
60
|
+
}, item.title), !!item.items?.length && React__default.createElement(DropdownMenu, {
|
|
61
|
+
items: item.items,
|
|
62
|
+
isExpanded: isExpanded,
|
|
63
|
+
alignRight: isLast,
|
|
64
|
+
linkHandler: linkHandler
|
|
65
|
+
}));
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const HorizontalMenu = ({
|
|
69
|
+
items,
|
|
70
|
+
theme,
|
|
71
|
+
linkHandler
|
|
72
|
+
}) => {
|
|
73
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
74
|
+
const [debouncedActiveIndex, setDebouncedActiveIndex] = useState(activeIndex);
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const handler = setTimeout(() => setDebouncedActiveIndex(activeIndex), activeIndex !== -1 ? 200 : 400);
|
|
77
|
+
return () => clearTimeout(handler);
|
|
78
|
+
}, [activeIndex]);
|
|
79
|
+
|
|
80
|
+
const handleEnter = item => setActiveIndex(items.findIndex(val => val === item));
|
|
81
|
+
|
|
82
|
+
const handleLeave = () => setActiveIndex(-1);
|
|
83
|
+
|
|
84
|
+
return React__default.createElement("nav", {
|
|
85
|
+
className: classNames(styles.nav, {
|
|
86
|
+
[styles.darkTheme]: theme === 'dark'
|
|
87
|
+
})
|
|
88
|
+
}, React__default.createElement("ul", {
|
|
89
|
+
className: styles.menuList
|
|
90
|
+
}, items.map((item, index) => React__default.createElement(HorizontalMenuItem, {
|
|
91
|
+
item: item,
|
|
92
|
+
onMouseEnter: handleEnter,
|
|
93
|
+
onMouseLeave: handleLeave,
|
|
94
|
+
isExpanded: index === debouncedActiveIndex,
|
|
95
|
+
isLast: index === items.length - 1,
|
|
96
|
+
key: index,
|
|
97
|
+
linkHandler: linkHandler
|
|
98
|
+
}))));
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export { HorizontalMenu };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var styles = {
|
|
2
|
+
"nav": "ktl-horizontal-menu-module_nav_gbA7M",
|
|
3
|
+
"menuList": "ktl-horizontal-menu-module_menu-list_TJnOF",
|
|
4
|
+
"menuItemWrap": "ktl-horizontal-menu-module_menu-item-wrap_j6zB-",
|
|
5
|
+
"menuItem": "ktl-horizontal-menu-module_menu-item_CXDEW",
|
|
6
|
+
"expanded": "ktl-horizontal-menu-module_expanded_3GFPc",
|
|
7
|
+
"itemActive": "ktl-horizontal-menu-module_item-active_Zca2K",
|
|
8
|
+
"dropdownMenu": "ktl-horizontal-menu-module_dropdown-menu_jwdWI",
|
|
9
|
+
"fadeIn": "ktl-horizontal-menu-module_fade-in_FGwhC",
|
|
10
|
+
"darkTheme": "ktl-horizontal-menu-module_dark-theme_gfxx6",
|
|
11
|
+
"dropdownMenuItem": "ktl-horizontal-menu-module_dropdown-menu-item_9gjwH",
|
|
12
|
+
"active": "ktl-horizontal-menu-module_active_m5fs-",
|
|
13
|
+
"dropdownMenuExpanded": "ktl-horizontal-menu-module_dropdown-menu-expanded_eX8Jy",
|
|
14
|
+
"dropdownMenuAlignRight": "ktl-horizontal-menu-module_dropdown-menu-align-right_YeB-9"
|
|
15
|
+
};
|
|
16
|
+
export { styles as default };
|