@doyourjob/gravity-ui-page-constructor-addons 2.1.55 → 2.1.57
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/build/cjs/components/Navigation/components/popups/components/Search/Search.css +21 -0
- package/build/cjs/components/NewHeader/components/NHLoginButton/NHLoginButton.js +31 -20
- package/build/cjs/components/NewHeader/components/NHNavigation/NHNavigation.d.ts +1 -1
- package/build/cjs/components/NewHeader/components/NHNavigation/NHNavigation.js +34 -26
- package/build/cjs/components/NewHeader/components/NHNavigationItem/NHNavigationItem.js +8 -6
- package/build/cjs/components/NewHeader/components/NHNavigationPopup/NHNavigationPopup.d.ts +3 -1
- package/build/cjs/components/NewHeader/components/NHNavigationPopup/NHNavigationPopup.js +2 -2
- package/build/esm/components/Navigation/components/popups/components/Search/Search.css +21 -0
- package/build/esm/components/NewHeader/components/NHLoginButton/NHLoginButton.js +32 -21
- package/build/esm/components/NewHeader/components/NHNavigation/NHNavigation.d.ts +1 -1
- package/build/esm/components/NewHeader/components/NHNavigation/NHNavigation.js +35 -27
- package/build/esm/components/NewHeader/components/NHNavigationItem/NHNavigationItem.js +9 -7
- package/build/esm/components/NewHeader/components/NHNavigationPopup/NHNavigationPopup.d.ts +3 -1
- package/build/esm/components/NewHeader/components/NHNavigationPopup/NHNavigationPopup.js +2 -2
- package/package.json +1 -1
|
@@ -27,12 +27,33 @@ unpredictable css rules order in build */
|
|
|
27
27
|
width: 100%;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
.pc-addons-popup-search__search-suggest .g-text-input__control,
|
|
30
31
|
.pc-addons-popup-search__search-suggest .yc-text-input__control {
|
|
31
32
|
padding-right: 32px;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
@media (max-width: 768px) {
|
|
36
|
+
.pc-addons-popup-search__search-suggest .g-text-input,
|
|
37
|
+
.pc-addons-popup-search__search-suggest .yc-text-input {
|
|
38
|
+
--g-text-input-height: 44px;
|
|
39
|
+
}
|
|
40
|
+
.pc-addons-popup-search__search-suggest .g-text-input__control,
|
|
41
|
+
.pc-addons-popup-search__search-suggest .yc-text-input__control {
|
|
42
|
+
font-size: 16px;
|
|
43
|
+
line-height: 20px;
|
|
44
|
+
height: 42px;
|
|
45
|
+
padding-top: 10px;
|
|
46
|
+
padding-bottom: 10px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
34
49
|
.pc-addons-popup-search_size_s {
|
|
35
50
|
height: 36px;
|
|
36
51
|
width: 352px;
|
|
37
52
|
max-width: 100%;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media (max-width: 768px) {
|
|
56
|
+
.pc-addons-popup-search_size_s {
|
|
57
|
+
height: 44px;
|
|
58
|
+
}
|
|
38
59
|
}
|
|
@@ -13,50 +13,60 @@ const NHNavigationPopup_1 = require("../NHNavigationPopup/NHNavigationPopup");
|
|
|
13
13
|
const b = (0, cn_1.block)('nh-login-button');
|
|
14
14
|
const NHLoginButton = ({ data, headerRef, setupRouteChangeHandler }) => {
|
|
15
15
|
const [isActive, setIsActive] = (0, react_1.useState)(false);
|
|
16
|
-
const [pretendentActiveTab, setPretendentAciveTab] = (0, react_1.useState)(false);
|
|
17
16
|
const [previouslyFocusedElement, setPreviouslyFocusedElement] = (0, react_1.useState)(null);
|
|
18
17
|
const popupId = (0, uikit_1.useUniqId)();
|
|
18
|
+
const hoverTimerRef = (0, react_1.useRef)(null);
|
|
19
|
+
const clearHoverTimer = (0, react_1.useCallback)(() => {
|
|
20
|
+
if (hoverTimerRef.current) {
|
|
21
|
+
clearTimeout(hoverTimerRef.current);
|
|
22
|
+
hoverTimerRef.current = null;
|
|
23
|
+
}
|
|
24
|
+
}, []);
|
|
25
|
+
// Open/close run through a single cancelable timer so moving from the trigger into the
|
|
26
|
+
// portaled popup (across the gap) cannot force the menu closed.
|
|
19
27
|
const handleActiveTab = (0, react_1.useCallback)((val) => {
|
|
20
28
|
setPreviouslyFocusedElement(document.activeElement);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
setIsActive(
|
|
24
|
-
}
|
|
25
|
-
}, [
|
|
29
|
+
clearHoverTimer();
|
|
30
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
31
|
+
setIsActive(val);
|
|
32
|
+
}, constants_1.SWITCH_MENU_TAB_TIMEOUT);
|
|
33
|
+
}, [clearHoverTimer]);
|
|
26
34
|
const onEscapeKeyDown = (0, react_1.useCallback)((event) => {
|
|
27
35
|
if (event.key === 'Escape' && isActive) {
|
|
36
|
+
clearHoverTimer();
|
|
28
37
|
setIsActive(false);
|
|
29
|
-
setPretendentAciveTab(false);
|
|
30
38
|
previouslyFocusedElement === null || previouslyFocusedElement === void 0 ? void 0 : previouslyFocusedElement.focus({ preventScroll: true });
|
|
31
39
|
}
|
|
32
|
-
}, [isActive, previouslyFocusedElement]);
|
|
40
|
+
}, [clearHoverTimer, isActive, previouslyFocusedElement]);
|
|
33
41
|
const handleMouseEnter = (0, react_1.useCallback)(() => handleActiveTab(true), [handleActiveTab]);
|
|
34
|
-
const handleMouseLeave = (0, react_1.useCallback)(() =>
|
|
42
|
+
const handleMouseLeave = (0, react_1.useCallback)((event) => {
|
|
43
|
+
const popup = document.getElementById(popupId);
|
|
44
|
+
const nextHoveredElement = (event === null || event === void 0 ? void 0 : event.relatedTarget) || (event === null || event === void 0 ? void 0 : event.nativeEvent.relatedTarget);
|
|
45
|
+
if (nextHoveredElement instanceof Node && (popup === null || popup === void 0 ? void 0 : popup.contains(nextHoveredElement))) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
handleActiveTab(false);
|
|
49
|
+
}, [handleActiveTab, popupId]);
|
|
35
50
|
const handleMouseDown = (0, react_1.useCallback)((event) => {
|
|
36
51
|
event.preventDefault();
|
|
37
52
|
}, []);
|
|
38
53
|
const handleToggle = (0, react_1.useCallback)(() => {
|
|
39
54
|
const focusedElement = document.activeElement;
|
|
40
55
|
const nextIsActive = !isActive;
|
|
56
|
+
clearHoverTimer();
|
|
41
57
|
setPreviouslyFocusedElement(focusedElement);
|
|
42
|
-
setPretendentAciveTab(nextIsActive);
|
|
43
58
|
setIsActive(nextIsActive);
|
|
44
59
|
if (!nextIsActive) {
|
|
45
60
|
focusedElement === null || focusedElement === void 0 ? void 0 : focusedElement.focus({ preventScroll: true });
|
|
46
61
|
}
|
|
47
|
-
}, [isActive]);
|
|
62
|
+
}, [clearHoverTimer, isActive]);
|
|
48
63
|
const handleKeyDown = (0, react_1.useCallback)((event) => {
|
|
49
64
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
50
65
|
event.preventDefault();
|
|
51
66
|
handleToggle();
|
|
52
67
|
}
|
|
53
68
|
}, [handleToggle]);
|
|
54
|
-
(0, react_1.useEffect)(() =>
|
|
55
|
-
const timerId = setTimeout(() => {
|
|
56
|
-
setIsActive(pretendentActiveTab);
|
|
57
|
-
}, constants_1.SWITCH_MENU_TAB_TIMEOUT);
|
|
58
|
-
return () => clearTimeout(timerId);
|
|
59
|
-
}, [pretendentActiveTab]);
|
|
69
|
+
(0, react_1.useEffect)(() => () => clearHoverTimer(), [clearHoverTimer]);
|
|
60
70
|
(0, react_1.useEffect)(() => {
|
|
61
71
|
document.addEventListener('keydown', onEscapeKeyDown);
|
|
62
72
|
return () => {
|
|
@@ -64,13 +74,14 @@ const NHLoginButton = ({ data, headerRef, setupRouteChangeHandler }) => {
|
|
|
64
74
|
};
|
|
65
75
|
}, [onEscapeKeyDown]);
|
|
66
76
|
(0, react_1.useEffect)(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
clearHoverTimer();
|
|
78
|
+
setIsActive(false);
|
|
79
|
+
}), [clearHoverTimer, setupRouteChangeHandler]);
|
|
69
80
|
return (react_1.default.createElement("div", { className: b('wrapper'), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
70
81
|
react_1.default.createElement("button", { className: b(), type: "button", onMouseDown: handleMouseDown, onKeyDown: handleKeyDown, "aria-expanded": isActive, "aria-controls": popupId },
|
|
71
82
|
data.text,
|
|
72
83
|
react_1.default.createElement(uikit_1.Icon, { data: isActive ? ChevronUp_1.ChevronUp : ChevronDown_1.ChevronDown, size: 16 })),
|
|
73
|
-
isActive && (react_1.default.createElement(NHNavigationPopup_1.NHNavigationPopup, { headerRef: headerRef, id: popupId },
|
|
84
|
+
isActive && (react_1.default.createElement(NHNavigationPopup_1.NHNavigationPopup, { headerRef: headerRef, id: popupId, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
74
85
|
react_1.default.createElement(NHLoginPopup_1.NHLoginPopup, Object.assign({}, data))))));
|
|
75
86
|
};
|
|
76
87
|
exports.NHLoginButton = NHLoginButton;
|
|
@@ -7,7 +7,7 @@ interface NavigationProps {
|
|
|
7
7
|
headerRef?: RefObject<HTMLDivElement>;
|
|
8
8
|
navigationId: string;
|
|
9
9
|
setupRouteChangeHandler?: SetupRouteChangeHandler;
|
|
10
|
-
setActiveNavigationId:
|
|
10
|
+
setActiveNavigationId: React.Dispatch<React.SetStateAction<string | null>>;
|
|
11
11
|
}
|
|
12
12
|
export declare const NHNavigation: ({ activeNavigationId, data, headerRef, navigationId, setupRouteChangeHandler, setActiveNavigationId, }: NavigationProps) => React.JSX.Element;
|
|
13
13
|
export {};
|
|
@@ -22,50 +22,62 @@ const getPopupContent = (sectionData) => {
|
|
|
22
22
|
};
|
|
23
23
|
const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId, setupRouteChangeHandler, setActiveNavigationId, }) => {
|
|
24
24
|
const [activeTab, setActiveTab] = (0, react_1.useState)(constants_1.NO_MENU_TAB_SELECTED);
|
|
25
|
-
const [pretendentActiveTab, setPretendentAciveTab] = (0, react_1.useState)(constants_1.NO_MENU_TAB_SELECTED);
|
|
26
25
|
const [previouslyFocusedElement, setPreviouslyFocusedElement] = (0, react_1.useState)(null);
|
|
27
26
|
const [popupTabToFocus, setPopupTabToFocus] = (0, react_1.useState)(null);
|
|
27
|
+
const hoverTimerRef = (0, react_1.useRef)(null);
|
|
28
|
+
const clearHoverTimer = (0, react_1.useCallback)(() => {
|
|
29
|
+
if (hoverTimerRef.current) {
|
|
30
|
+
clearTimeout(hoverTimerRef.current);
|
|
31
|
+
hoverTimerRef.current = null;
|
|
32
|
+
}
|
|
33
|
+
}, []);
|
|
28
34
|
const setNavigationTab = (0, react_1.useCallback)((currentIndex) => {
|
|
29
|
-
setPretendentAciveTab(currentIndex);
|
|
30
35
|
setActiveTab(currentIndex);
|
|
31
36
|
setPopupTabToFocus(null);
|
|
32
|
-
setActiveNavigationId(currentIndex === constants_1.NO_MENU_TAB_SELECTED
|
|
37
|
+
setActiveNavigationId(currentIndex === constants_1.NO_MENU_TAB_SELECTED
|
|
38
|
+
? (prev) => (prev === navigationId ? null : prev)
|
|
39
|
+
: navigationId);
|
|
33
40
|
}, [navigationId, setActiveNavigationId]);
|
|
41
|
+
// Hover open/switch/close all run through a single cancelable timer: every new pointer
|
|
42
|
+
// event cancels the pending one, so a brief transit across the trigger->popup gap (or
|
|
43
|
+
// rapid movement between items) can no longer force the popup closed.
|
|
34
44
|
const handleActiveTab = (0, react_1.useCallback)((currentIndex) => {
|
|
35
45
|
setPreviouslyFocusedElement(document.activeElement);
|
|
36
|
-
|
|
46
|
+
clearHoverTimer();
|
|
47
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
37
48
|
setNavigationTab(currentIndex);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
setPretendentAciveTab(currentIndex);
|
|
41
|
-
}, [activeTab, setNavigationTab]);
|
|
49
|
+
}, constants_1.SWITCH_MENU_TAB_TIMEOUT);
|
|
50
|
+
}, [clearHoverTimer, setNavigationTab]);
|
|
42
51
|
const handleToggleTab = (0, react_1.useCallback)((currentIndex) => {
|
|
43
52
|
const focusedElement = document.activeElement;
|
|
44
53
|
const nextActiveTab = activeTab === currentIndex ? constants_1.NO_MENU_TAB_SELECTED : currentIndex;
|
|
54
|
+
clearHoverTimer();
|
|
45
55
|
setPreviouslyFocusedElement(focusedElement);
|
|
46
56
|
setNavigationTab(nextActiveTab);
|
|
47
57
|
if (nextActiveTab === constants_1.NO_MENU_TAB_SELECTED) {
|
|
48
58
|
focusedElement === null || focusedElement === void 0 ? void 0 : focusedElement.focus({ preventScroll: true });
|
|
49
59
|
}
|
|
50
|
-
}, [activeTab, setNavigationTab]);
|
|
60
|
+
}, [activeTab, clearHoverTimer, setNavigationTab]);
|
|
51
61
|
const handleFocusTabPopup = (0, react_1.useCallback)((currentIndex) => {
|
|
62
|
+
clearHoverTimer();
|
|
52
63
|
setPreviouslyFocusedElement(document.activeElement);
|
|
53
|
-
setPretendentAciveTab(currentIndex);
|
|
54
64
|
setActiveTab(currentIndex);
|
|
55
65
|
setPopupTabToFocus(currentIndex);
|
|
56
66
|
setActiveNavigationId(navigationId);
|
|
57
|
-
}, [navigationId, setActiveNavigationId]);
|
|
67
|
+
}, [clearHoverTimer, navigationId, setActiveNavigationId]);
|
|
58
68
|
const handleFocusTab = (0, react_1.useCallback)((currentIndex) => {
|
|
59
69
|
if (activeNavigationId === null) {
|
|
60
70
|
return;
|
|
61
71
|
}
|
|
72
|
+
clearHoverTimer();
|
|
62
73
|
setPreviouslyFocusedElement(document.activeElement);
|
|
63
74
|
setNavigationTab(currentIndex);
|
|
64
|
-
}, [activeNavigationId, setNavigationTab]);
|
|
75
|
+
}, [activeNavigationId, clearHoverTimer, setNavigationTab]);
|
|
65
76
|
const handleCloseTab = (0, react_1.useCallback)(() => {
|
|
77
|
+
clearHoverTimer();
|
|
66
78
|
setNavigationTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
67
79
|
previouslyFocusedElement === null || previouslyFocusedElement === void 0 ? void 0 : previouslyFocusedElement.focus({ preventScroll: true });
|
|
68
|
-
}, [previouslyFocusedElement, setNavigationTab]);
|
|
80
|
+
}, [clearHoverTimer, previouslyFocusedElement, setNavigationTab]);
|
|
69
81
|
const handleBlur = (0, react_1.useCallback)((event) => {
|
|
70
82
|
if (activeTab === constants_1.NO_MENU_TAB_SELECTED) {
|
|
71
83
|
return;
|
|
@@ -77,30 +89,26 @@ const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId, setup
|
|
|
77
89
|
(popup === null || popup === void 0 ? void 0 : popup.contains(nextFocusedElement)))) {
|
|
78
90
|
return;
|
|
79
91
|
}
|
|
92
|
+
clearHoverTimer();
|
|
80
93
|
setNavigationTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
81
|
-
}, [activeTab, setNavigationTab]);
|
|
94
|
+
}, [activeTab, clearHoverTimer, setNavigationTab]);
|
|
82
95
|
const onEscapeKeyDown = (0, react_1.useCallback)((event) => {
|
|
83
96
|
if (event.key === 'Escape' && activeTab !== constants_1.NO_MENU_TAB_SELECTED) {
|
|
84
97
|
handleCloseTab();
|
|
85
98
|
}
|
|
86
99
|
}, [activeTab, handleCloseTab]);
|
|
87
100
|
(0, react_1.useEffect)(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const timerId = setTimeout(() => {
|
|
92
|
-
setActiveTab(pretendentActiveTab);
|
|
93
|
-
setActiveNavigationId(pretendentActiveTab === constants_1.NO_MENU_TAB_SELECTED ? null : navigationId);
|
|
94
|
-
}, constants_1.SWITCH_MENU_TAB_TIMEOUT);
|
|
95
|
-
return () => clearTimeout(timerId);
|
|
96
|
-
}, [activeTab, navigationId, pretendentActiveTab, setActiveNavigationId]);
|
|
101
|
+
clearHoverTimer();
|
|
102
|
+
setNavigationTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
103
|
+
}), [setupRouteChangeHandler, clearHoverTimer, setNavigationTab]);
|
|
97
104
|
(0, react_1.useEffect)(() => {
|
|
98
105
|
if (activeNavigationId !== navigationId && activeTab !== constants_1.NO_MENU_TAB_SELECTED) {
|
|
106
|
+
clearHoverTimer();
|
|
99
107
|
setActiveTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
100
|
-
setPretendentAciveTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
101
108
|
setPopupTabToFocus(null);
|
|
102
109
|
}
|
|
103
|
-
}, [activeNavigationId, activeTab, navigationId]);
|
|
110
|
+
}, [activeNavigationId, activeTab, navigationId, clearHoverTimer]);
|
|
111
|
+
(0, react_1.useEffect)(() => () => clearHoverTimer(), [clearHoverTimer]);
|
|
104
112
|
(0, react_1.useEffect)(() => {
|
|
105
113
|
if (popupTabToFocus === null || activeTab !== popupTabToFocus) {
|
|
106
114
|
return;
|
|
@@ -117,6 +125,6 @@ const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId, setup
|
|
|
117
125
|
};
|
|
118
126
|
}, [onEscapeKeyDown]);
|
|
119
127
|
return (react_1.default.createElement("nav", { onBlur: handleBlur },
|
|
120
|
-
react_1.default.createElement("ul", { className: b() }, data.map((item, i) => (react_1.default.createElement(NHNavigationItem_1.NHNavigationItem, { key: i, item: item, handleActiveTab: handleActiveTab, handleFocusTabPopup: handleFocusTabPopup, handleFocusTab: handleFocusTab, handleToggleTab: handleToggleTab, index: i, isActive: activeTab === i, tooltipId: `${tooltipPrefixId}-${i}` }, activeTab === i && item.type !== models_1.NHNavigationItemType.Link && (react_1.default.createElement(NHNavigationPopup_1.NHNavigationPopup, { headerRef: headerRef, id: `${tooltipPrefixId}-${i}
|
|
128
|
+
react_1.default.createElement("ul", { className: b() }, data.map((item, i) => (react_1.default.createElement(NHNavigationItem_1.NHNavigationItem, { key: i, item: item, handleActiveTab: handleActiveTab, handleFocusTabPopup: handleFocusTabPopup, handleFocusTab: handleFocusTab, handleToggleTab: handleToggleTab, index: i, isActive: activeTab === i, tooltipId: `${tooltipPrefixId}-${i}` }, activeTab === i && item.type !== models_1.NHNavigationItemType.Link && (react_1.default.createElement(NHNavigationPopup_1.NHNavigationPopup, { headerRef: headerRef, id: `${tooltipPrefixId}-${i}`, onMouseEnter: () => handleActiveTab(i), onMouseLeave: () => handleActiveTab(constants_1.NO_MENU_TAB_SELECTED) }, getPopupContent(item)))))))));
|
|
121
129
|
};
|
|
122
130
|
exports.NHNavigation = NHNavigation;
|
|
@@ -7,16 +7,21 @@ const gravity_ui_page_constructor_1 = require("@doyourjob/gravity-ui-page-constr
|
|
|
7
7
|
const uikit_1 = require("@gravity-ui/uikit");
|
|
8
8
|
const cn_1 = require("../../../../utils/cn");
|
|
9
9
|
const constants_1 = require("../../constants");
|
|
10
|
-
const route_change_1 = require("../../contexts/route-change");
|
|
11
10
|
const models_1 = require("../../models");
|
|
12
11
|
const ChevronDown_1 = require("../ChevronDown");
|
|
13
12
|
const ChevronUp_1 = require("../ChevronUp");
|
|
14
13
|
const b = (0, cn_1.block)('nh-navigation-item');
|
|
15
14
|
const NHNavigationItem = ({ item, isActive, handleActiveTab, handleFocusTab, handleFocusTabPopup, handleToggleTab, index, children, tooltipId, }) => {
|
|
16
15
|
var _a, _b, _c, _d;
|
|
17
|
-
const setupRouteChangeHandler = (0, react_1.useContext)(route_change_1.RouteChangeHandlerContext);
|
|
18
16
|
const handleMouseEnter = (0, react_1.useCallback)(() => handleActiveTab(index), [handleActiveTab, index]);
|
|
19
|
-
const handleMouseLeave = (0, react_1.useCallback)(() =>
|
|
17
|
+
const handleMouseLeave = (0, react_1.useCallback)((event) => {
|
|
18
|
+
const popup = tooltipId ? document.getElementById(tooltipId) : null;
|
|
19
|
+
const nextHoveredElement = (event === null || event === void 0 ? void 0 : event.relatedTarget) || (event === null || event === void 0 ? void 0 : event.nativeEvent.relatedTarget);
|
|
20
|
+
if (nextHoveredElement instanceof Node && (popup === null || popup === void 0 ? void 0 : popup.contains(nextHoveredElement))) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
handleActiveTab(constants_1.NO_MENU_TAB_SELECTED);
|
|
24
|
+
}, [handleActiveTab, tooltipId]);
|
|
20
25
|
const handleMouseDown = (0, react_1.useCallback)((event) => {
|
|
21
26
|
event.preventDefault();
|
|
22
27
|
}, []);
|
|
@@ -32,9 +37,6 @@ const NHNavigationItem = ({ item, isActive, handleActiveTab, handleFocusTab, han
|
|
|
32
37
|
handleToggleTab(index);
|
|
33
38
|
}
|
|
34
39
|
}, [handleFocusTabPopup, handleToggleTab, index]);
|
|
35
|
-
(0, react_1.useEffect)(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
36
|
-
handleMouseLeave();
|
|
37
|
-
}), [handleMouseLeave, setupRouteChangeHandler]);
|
|
38
40
|
if (item.type === models_1.NHNavigationItemType.Link) {
|
|
39
41
|
return (react_1.default.createElement("li", { className: b({ disable: !((_a = item.data) === null || _a === void 0 ? void 0 : _a.url) }), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
40
42
|
react_1.default.createElement("a", Object.assign({ className: b('text', { active: isActive }), href: (_b = item.data) === null || _b === void 0 ? void 0 : _b.url, onFocus: handleLinkFocus }, (0, gravity_ui_page_constructor_1.getLinkProps)(((_c = item.data) === null || _c === void 0 ? void 0 : _c.url) || '', undefined, (_d = item.data) === null || _d === void 0 ? void 0 : _d.target)), item.title),
|
|
@@ -4,6 +4,8 @@ interface NavigationPopupProps {
|
|
|
4
4
|
headerRef?: RefObject<HTMLDivElement>;
|
|
5
5
|
children: React.ReactNode;
|
|
6
6
|
id?: string;
|
|
7
|
+
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
|
|
8
|
+
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
|
7
9
|
}
|
|
8
|
-
export declare const NHNavigationPopup: ({ headerRef, children, id }: NavigationPopupProps) => React.ReactPortal | null;
|
|
10
|
+
export declare const NHNavigationPopup: ({ headerRef, children, id, onMouseEnter, onMouseLeave, }: NavigationPopupProps) => React.ReactPortal | null;
|
|
9
11
|
export {};
|
|
@@ -15,7 +15,7 @@ const getNextIndex = (currentIndex, offset, elementsCount) => {
|
|
|
15
15
|
}
|
|
16
16
|
return (currentIndex + offset + elementsCount) % elementsCount;
|
|
17
17
|
};
|
|
18
|
-
const NHNavigationPopup = ({ headerRef, children, id }) => {
|
|
18
|
+
const NHNavigationPopup = ({ headerRef, children, id, onMouseEnter, onMouseLeave, }) => {
|
|
19
19
|
const popupRef = (0, react_1.useRef)(null);
|
|
20
20
|
const focusRelativeElement = (0, react_1.useCallback)((offset) => {
|
|
21
21
|
const popup = popupRef.current;
|
|
@@ -64,7 +64,7 @@ const NHNavigationPopup = ({ headerRef, children, id }) => {
|
|
|
64
64
|
};
|
|
65
65
|
}, [focusRelativeElement]);
|
|
66
66
|
return (headerRef === null || headerRef === void 0 ? void 0 : headerRef.current)
|
|
67
|
-
? react_dom_1.default.createPortal(react_1.default.createElement("div", { className: b(), id: id, ref: popupRef }, children), headerRef.current)
|
|
67
|
+
? react_dom_1.default.createPortal(react_1.default.createElement("div", { className: b(), id: id, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ref: popupRef }, children), headerRef.current)
|
|
68
68
|
: null;
|
|
69
69
|
};
|
|
70
70
|
exports.NHNavigationPopup = NHNavigationPopup;
|
|
@@ -27,12 +27,33 @@ unpredictable css rules order in build */
|
|
|
27
27
|
width: 100%;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
.pc-addons-popup-search__search-suggest .g-text-input__control,
|
|
30
31
|
.pc-addons-popup-search__search-suggest .yc-text-input__control {
|
|
31
32
|
padding-right: 32px;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
@media (max-width: 768px) {
|
|
36
|
+
.pc-addons-popup-search__search-suggest .g-text-input,
|
|
37
|
+
.pc-addons-popup-search__search-suggest .yc-text-input {
|
|
38
|
+
--g-text-input-height: 44px;
|
|
39
|
+
}
|
|
40
|
+
.pc-addons-popup-search__search-suggest .g-text-input__control,
|
|
41
|
+
.pc-addons-popup-search__search-suggest .yc-text-input__control {
|
|
42
|
+
font-size: 16px;
|
|
43
|
+
line-height: 20px;
|
|
44
|
+
height: 42px;
|
|
45
|
+
padding-top: 10px;
|
|
46
|
+
padding-bottom: 10px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
34
49
|
.pc-addons-popup-search_size_s {
|
|
35
50
|
height: 36px;
|
|
36
51
|
width: 352px;
|
|
37
52
|
max-width: 100%;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media (max-width: 768px) {
|
|
56
|
+
.pc-addons-popup-search_size_s {
|
|
57
|
+
height: 44px;
|
|
58
|
+
}
|
|
38
59
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { Icon, useUniqId } from '@gravity-ui/uikit';
|
|
3
3
|
import { block } from '../../../../utils/cn';
|
|
4
4
|
import { SWITCH_MENU_TAB_TIMEOUT } from '../../constants';
|
|
@@ -10,50 +10,60 @@ import './NHLoginButton.css';
|
|
|
10
10
|
const b = block('nh-login-button');
|
|
11
11
|
export const NHLoginButton = ({ data, headerRef, setupRouteChangeHandler }) => {
|
|
12
12
|
const [isActive, setIsActive] = useState(false);
|
|
13
|
-
const [pretendentActiveTab, setPretendentAciveTab] = useState(false);
|
|
14
13
|
const [previouslyFocusedElement, setPreviouslyFocusedElement] = useState(null);
|
|
15
14
|
const popupId = useUniqId();
|
|
15
|
+
const hoverTimerRef = useRef(null);
|
|
16
|
+
const clearHoverTimer = useCallback(() => {
|
|
17
|
+
if (hoverTimerRef.current) {
|
|
18
|
+
clearTimeout(hoverTimerRef.current);
|
|
19
|
+
hoverTimerRef.current = null;
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
// Open/close run through a single cancelable timer so moving from the trigger into the
|
|
23
|
+
// portaled popup (across the gap) cannot force the menu closed.
|
|
16
24
|
const handleActiveTab = useCallback((val) => {
|
|
17
25
|
setPreviouslyFocusedElement(document.activeElement);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
setIsActive(
|
|
21
|
-
}
|
|
22
|
-
}, [
|
|
26
|
+
clearHoverTimer();
|
|
27
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
28
|
+
setIsActive(val);
|
|
29
|
+
}, SWITCH_MENU_TAB_TIMEOUT);
|
|
30
|
+
}, [clearHoverTimer]);
|
|
23
31
|
const onEscapeKeyDown = useCallback((event) => {
|
|
24
32
|
if (event.key === 'Escape' && isActive) {
|
|
33
|
+
clearHoverTimer();
|
|
25
34
|
setIsActive(false);
|
|
26
|
-
setPretendentAciveTab(false);
|
|
27
35
|
previouslyFocusedElement === null || previouslyFocusedElement === void 0 ? void 0 : previouslyFocusedElement.focus({ preventScroll: true });
|
|
28
36
|
}
|
|
29
|
-
}, [isActive, previouslyFocusedElement]);
|
|
37
|
+
}, [clearHoverTimer, isActive, previouslyFocusedElement]);
|
|
30
38
|
const handleMouseEnter = useCallback(() => handleActiveTab(true), [handleActiveTab]);
|
|
31
|
-
const handleMouseLeave = useCallback(() =>
|
|
39
|
+
const handleMouseLeave = useCallback((event) => {
|
|
40
|
+
const popup = document.getElementById(popupId);
|
|
41
|
+
const nextHoveredElement = (event === null || event === void 0 ? void 0 : event.relatedTarget) || (event === null || event === void 0 ? void 0 : event.nativeEvent.relatedTarget);
|
|
42
|
+
if (nextHoveredElement instanceof Node && (popup === null || popup === void 0 ? void 0 : popup.contains(nextHoveredElement))) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
handleActiveTab(false);
|
|
46
|
+
}, [handleActiveTab, popupId]);
|
|
32
47
|
const handleMouseDown = useCallback((event) => {
|
|
33
48
|
event.preventDefault();
|
|
34
49
|
}, []);
|
|
35
50
|
const handleToggle = useCallback(() => {
|
|
36
51
|
const focusedElement = document.activeElement;
|
|
37
52
|
const nextIsActive = !isActive;
|
|
53
|
+
clearHoverTimer();
|
|
38
54
|
setPreviouslyFocusedElement(focusedElement);
|
|
39
|
-
setPretendentAciveTab(nextIsActive);
|
|
40
55
|
setIsActive(nextIsActive);
|
|
41
56
|
if (!nextIsActive) {
|
|
42
57
|
focusedElement === null || focusedElement === void 0 ? void 0 : focusedElement.focus({ preventScroll: true });
|
|
43
58
|
}
|
|
44
|
-
}, [isActive]);
|
|
59
|
+
}, [clearHoverTimer, isActive]);
|
|
45
60
|
const handleKeyDown = useCallback((event) => {
|
|
46
61
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
47
62
|
event.preventDefault();
|
|
48
63
|
handleToggle();
|
|
49
64
|
}
|
|
50
65
|
}, [handleToggle]);
|
|
51
|
-
useEffect(() =>
|
|
52
|
-
const timerId = setTimeout(() => {
|
|
53
|
-
setIsActive(pretendentActiveTab);
|
|
54
|
-
}, SWITCH_MENU_TAB_TIMEOUT);
|
|
55
|
-
return () => clearTimeout(timerId);
|
|
56
|
-
}, [pretendentActiveTab]);
|
|
66
|
+
useEffect(() => () => clearHoverTimer(), [clearHoverTimer]);
|
|
57
67
|
useEffect(() => {
|
|
58
68
|
document.addEventListener('keydown', onEscapeKeyDown);
|
|
59
69
|
return () => {
|
|
@@ -61,12 +71,13 @@ export const NHLoginButton = ({ data, headerRef, setupRouteChangeHandler }) => {
|
|
|
61
71
|
};
|
|
62
72
|
}, [onEscapeKeyDown]);
|
|
63
73
|
useEffect(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
clearHoverTimer();
|
|
75
|
+
setIsActive(false);
|
|
76
|
+
}), [clearHoverTimer, setupRouteChangeHandler]);
|
|
66
77
|
return (React.createElement("div", { className: b('wrapper'), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
67
78
|
React.createElement("button", { className: b(), type: "button", onMouseDown: handleMouseDown, onKeyDown: handleKeyDown, "aria-expanded": isActive, "aria-controls": popupId },
|
|
68
79
|
data.text,
|
|
69
80
|
React.createElement(Icon, { data: isActive ? ChevronUp : ChevronDown, size: 16 })),
|
|
70
|
-
isActive && (React.createElement(NHNavigationPopup, { headerRef: headerRef, id: popupId },
|
|
81
|
+
isActive && (React.createElement(NHNavigationPopup, { headerRef: headerRef, id: popupId, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
71
82
|
React.createElement(NHLoginPopup, Object.assign({}, data))))));
|
|
72
83
|
};
|
|
@@ -8,7 +8,7 @@ interface NavigationProps {
|
|
|
8
8
|
headerRef?: RefObject<HTMLDivElement>;
|
|
9
9
|
navigationId: string;
|
|
10
10
|
setupRouteChangeHandler?: SetupRouteChangeHandler;
|
|
11
|
-
setActiveNavigationId:
|
|
11
|
+
setActiveNavigationId: React.Dispatch<React.SetStateAction<string | null>>;
|
|
12
12
|
}
|
|
13
13
|
export declare const NHNavigation: ({ activeNavigationId, data, headerRef, navigationId, setupRouteChangeHandler, setActiveNavigationId, }: NavigationProps) => React.JSX.Element;
|
|
14
14
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { block } from '../../../../utils/cn';
|
|
3
3
|
import { NO_MENU_TAB_SELECTED, SWITCH_MENU_TAB_TIMEOUT } from '../../constants';
|
|
4
4
|
import { NHNavigationItemType } from '../../models';
|
|
@@ -19,50 +19,62 @@ const getPopupContent = (sectionData) => {
|
|
|
19
19
|
};
|
|
20
20
|
export const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId, setupRouteChangeHandler, setActiveNavigationId, }) => {
|
|
21
21
|
const [activeTab, setActiveTab] = useState(NO_MENU_TAB_SELECTED);
|
|
22
|
-
const [pretendentActiveTab, setPretendentAciveTab] = useState(NO_MENU_TAB_SELECTED);
|
|
23
22
|
const [previouslyFocusedElement, setPreviouslyFocusedElement] = useState(null);
|
|
24
23
|
const [popupTabToFocus, setPopupTabToFocus] = useState(null);
|
|
24
|
+
const hoverTimerRef = useRef(null);
|
|
25
|
+
const clearHoverTimer = useCallback(() => {
|
|
26
|
+
if (hoverTimerRef.current) {
|
|
27
|
+
clearTimeout(hoverTimerRef.current);
|
|
28
|
+
hoverTimerRef.current = null;
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
25
31
|
const setNavigationTab = useCallback((currentIndex) => {
|
|
26
|
-
setPretendentAciveTab(currentIndex);
|
|
27
32
|
setActiveTab(currentIndex);
|
|
28
33
|
setPopupTabToFocus(null);
|
|
29
|
-
setActiveNavigationId(currentIndex === NO_MENU_TAB_SELECTED
|
|
34
|
+
setActiveNavigationId(currentIndex === NO_MENU_TAB_SELECTED
|
|
35
|
+
? (prev) => (prev === navigationId ? null : prev)
|
|
36
|
+
: navigationId);
|
|
30
37
|
}, [navigationId, setActiveNavigationId]);
|
|
38
|
+
// Hover open/switch/close all run through a single cancelable timer: every new pointer
|
|
39
|
+
// event cancels the pending one, so a brief transit across the trigger->popup gap (or
|
|
40
|
+
// rapid movement between items) can no longer force the popup closed.
|
|
31
41
|
const handleActiveTab = useCallback((currentIndex) => {
|
|
32
42
|
setPreviouslyFocusedElement(document.activeElement);
|
|
33
|
-
|
|
43
|
+
clearHoverTimer();
|
|
44
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
34
45
|
setNavigationTab(currentIndex);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
setPretendentAciveTab(currentIndex);
|
|
38
|
-
}, [activeTab, setNavigationTab]);
|
|
46
|
+
}, SWITCH_MENU_TAB_TIMEOUT);
|
|
47
|
+
}, [clearHoverTimer, setNavigationTab]);
|
|
39
48
|
const handleToggleTab = useCallback((currentIndex) => {
|
|
40
49
|
const focusedElement = document.activeElement;
|
|
41
50
|
const nextActiveTab = activeTab === currentIndex ? NO_MENU_TAB_SELECTED : currentIndex;
|
|
51
|
+
clearHoverTimer();
|
|
42
52
|
setPreviouslyFocusedElement(focusedElement);
|
|
43
53
|
setNavigationTab(nextActiveTab);
|
|
44
54
|
if (nextActiveTab === NO_MENU_TAB_SELECTED) {
|
|
45
55
|
focusedElement === null || focusedElement === void 0 ? void 0 : focusedElement.focus({ preventScroll: true });
|
|
46
56
|
}
|
|
47
|
-
}, [activeTab, setNavigationTab]);
|
|
57
|
+
}, [activeTab, clearHoverTimer, setNavigationTab]);
|
|
48
58
|
const handleFocusTabPopup = useCallback((currentIndex) => {
|
|
59
|
+
clearHoverTimer();
|
|
49
60
|
setPreviouslyFocusedElement(document.activeElement);
|
|
50
|
-
setPretendentAciveTab(currentIndex);
|
|
51
61
|
setActiveTab(currentIndex);
|
|
52
62
|
setPopupTabToFocus(currentIndex);
|
|
53
63
|
setActiveNavigationId(navigationId);
|
|
54
|
-
}, [navigationId, setActiveNavigationId]);
|
|
64
|
+
}, [clearHoverTimer, navigationId, setActiveNavigationId]);
|
|
55
65
|
const handleFocusTab = useCallback((currentIndex) => {
|
|
56
66
|
if (activeNavigationId === null) {
|
|
57
67
|
return;
|
|
58
68
|
}
|
|
69
|
+
clearHoverTimer();
|
|
59
70
|
setPreviouslyFocusedElement(document.activeElement);
|
|
60
71
|
setNavigationTab(currentIndex);
|
|
61
|
-
}, [activeNavigationId, setNavigationTab]);
|
|
72
|
+
}, [activeNavigationId, clearHoverTimer, setNavigationTab]);
|
|
62
73
|
const handleCloseTab = useCallback(() => {
|
|
74
|
+
clearHoverTimer();
|
|
63
75
|
setNavigationTab(NO_MENU_TAB_SELECTED);
|
|
64
76
|
previouslyFocusedElement === null || previouslyFocusedElement === void 0 ? void 0 : previouslyFocusedElement.focus({ preventScroll: true });
|
|
65
|
-
}, [previouslyFocusedElement, setNavigationTab]);
|
|
77
|
+
}, [clearHoverTimer, previouslyFocusedElement, setNavigationTab]);
|
|
66
78
|
const handleBlur = useCallback((event) => {
|
|
67
79
|
if (activeTab === NO_MENU_TAB_SELECTED) {
|
|
68
80
|
return;
|
|
@@ -74,30 +86,26 @@ export const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId
|
|
|
74
86
|
(popup === null || popup === void 0 ? void 0 : popup.contains(nextFocusedElement)))) {
|
|
75
87
|
return;
|
|
76
88
|
}
|
|
89
|
+
clearHoverTimer();
|
|
77
90
|
setNavigationTab(NO_MENU_TAB_SELECTED);
|
|
78
|
-
}, [activeTab, setNavigationTab]);
|
|
91
|
+
}, [activeTab, clearHoverTimer, setNavigationTab]);
|
|
79
92
|
const onEscapeKeyDown = useCallback((event) => {
|
|
80
93
|
if (event.key === 'Escape' && activeTab !== NO_MENU_TAB_SELECTED) {
|
|
81
94
|
handleCloseTab();
|
|
82
95
|
}
|
|
83
96
|
}, [activeTab, handleCloseTab]);
|
|
84
97
|
useEffect(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const timerId = setTimeout(() => {
|
|
89
|
-
setActiveTab(pretendentActiveTab);
|
|
90
|
-
setActiveNavigationId(pretendentActiveTab === NO_MENU_TAB_SELECTED ? null : navigationId);
|
|
91
|
-
}, SWITCH_MENU_TAB_TIMEOUT);
|
|
92
|
-
return () => clearTimeout(timerId);
|
|
93
|
-
}, [activeTab, navigationId, pretendentActiveTab, setActiveNavigationId]);
|
|
98
|
+
clearHoverTimer();
|
|
99
|
+
setNavigationTab(NO_MENU_TAB_SELECTED);
|
|
100
|
+
}), [setupRouteChangeHandler, clearHoverTimer, setNavigationTab]);
|
|
94
101
|
useEffect(() => {
|
|
95
102
|
if (activeNavigationId !== navigationId && activeTab !== NO_MENU_TAB_SELECTED) {
|
|
103
|
+
clearHoverTimer();
|
|
96
104
|
setActiveTab(NO_MENU_TAB_SELECTED);
|
|
97
|
-
setPretendentAciveTab(NO_MENU_TAB_SELECTED);
|
|
98
105
|
setPopupTabToFocus(null);
|
|
99
106
|
}
|
|
100
|
-
}, [activeNavigationId, activeTab, navigationId]);
|
|
107
|
+
}, [activeNavigationId, activeTab, navigationId, clearHoverTimer]);
|
|
108
|
+
useEffect(() => () => clearHoverTimer(), [clearHoverTimer]);
|
|
101
109
|
useEffect(() => {
|
|
102
110
|
if (popupTabToFocus === null || activeTab !== popupTabToFocus) {
|
|
103
111
|
return;
|
|
@@ -114,5 +122,5 @@ export const NHNavigation = ({ activeNavigationId, data, headerRef, navigationId
|
|
|
114
122
|
};
|
|
115
123
|
}, [onEscapeKeyDown]);
|
|
116
124
|
return (React.createElement("nav", { onBlur: handleBlur },
|
|
117
|
-
React.createElement("ul", { className: b() }, data.map((item, i) => (React.createElement(NHNavigationItem, { key: i, item: item, handleActiveTab: handleActiveTab, handleFocusTabPopup: handleFocusTabPopup, handleFocusTab: handleFocusTab, handleToggleTab: handleToggleTab, index: i, isActive: activeTab === i, tooltipId: `${tooltipPrefixId}-${i}` }, activeTab === i && item.type !== NHNavigationItemType.Link && (React.createElement(NHNavigationPopup, { headerRef: headerRef, id: `${tooltipPrefixId}-${i}
|
|
125
|
+
React.createElement("ul", { className: b() }, data.map((item, i) => (React.createElement(NHNavigationItem, { key: i, item: item, handleActiveTab: handleActiveTab, handleFocusTabPopup: handleFocusTabPopup, handleFocusTab: handleFocusTab, handleToggleTab: handleToggleTab, index: i, isActive: activeTab === i, tooltipId: `${tooltipPrefixId}-${i}` }, activeTab === i && item.type !== NHNavigationItemType.Link && (React.createElement(NHNavigationPopup, { headerRef: headerRef, id: `${tooltipPrefixId}-${i}`, onMouseEnter: () => handleActiveTab(i), onMouseLeave: () => handleActiveTab(NO_MENU_TAB_SELECTED) }, getPopupContent(item)))))))));
|
|
118
126
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React, { useCallback
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
2
|
import { getLinkProps } from '@doyourjob/gravity-ui-page-constructor';
|
|
3
3
|
import { Icon } from '@gravity-ui/uikit';
|
|
4
4
|
import { block } from '../../../../utils/cn';
|
|
5
5
|
import { NO_MENU_TAB_SELECTED } from '../../constants';
|
|
6
|
-
import { RouteChangeHandlerContext } from '../../contexts/route-change';
|
|
7
6
|
import { NHNavigationItemType } from '../../models';
|
|
8
7
|
import { ChevronDown } from '../ChevronDown';
|
|
9
8
|
import { ChevronUp } from '../ChevronUp';
|
|
@@ -11,9 +10,15 @@ import './NHNavigationItem.css';
|
|
|
11
10
|
const b = block('nh-navigation-item');
|
|
12
11
|
export const NHNavigationItem = ({ item, isActive, handleActiveTab, handleFocusTab, handleFocusTabPopup, handleToggleTab, index, children, tooltipId, }) => {
|
|
13
12
|
var _a, _b, _c, _d;
|
|
14
|
-
const setupRouteChangeHandler = useContext(RouteChangeHandlerContext);
|
|
15
13
|
const handleMouseEnter = useCallback(() => handleActiveTab(index), [handleActiveTab, index]);
|
|
16
|
-
const handleMouseLeave = useCallback(() =>
|
|
14
|
+
const handleMouseLeave = useCallback((event) => {
|
|
15
|
+
const popup = tooltipId ? document.getElementById(tooltipId) : null;
|
|
16
|
+
const nextHoveredElement = (event === null || event === void 0 ? void 0 : event.relatedTarget) || (event === null || event === void 0 ? void 0 : event.nativeEvent.relatedTarget);
|
|
17
|
+
if (nextHoveredElement instanceof Node && (popup === null || popup === void 0 ? void 0 : popup.contains(nextHoveredElement))) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
handleActiveTab(NO_MENU_TAB_SELECTED);
|
|
21
|
+
}, [handleActiveTab, tooltipId]);
|
|
17
22
|
const handleMouseDown = useCallback((event) => {
|
|
18
23
|
event.preventDefault();
|
|
19
24
|
}, []);
|
|
@@ -29,9 +34,6 @@ export const NHNavigationItem = ({ item, isActive, handleActiveTab, handleFocusT
|
|
|
29
34
|
handleToggleTab(index);
|
|
30
35
|
}
|
|
31
36
|
}, [handleFocusTabPopup, handleToggleTab, index]);
|
|
32
|
-
useEffect(() => setupRouteChangeHandler === null || setupRouteChangeHandler === void 0 ? void 0 : setupRouteChangeHandler(() => {
|
|
33
|
-
handleMouseLeave();
|
|
34
|
-
}), [handleMouseLeave, setupRouteChangeHandler]);
|
|
35
37
|
if (item.type === NHNavigationItemType.Link) {
|
|
36
38
|
return (React.createElement("li", { className: b({ disable: !((_a = item.data) === null || _a === void 0 ? void 0 : _a.url) }), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
37
39
|
React.createElement("a", Object.assign({ className: b('text', { active: isActive }), href: (_b = item.data) === null || _b === void 0 ? void 0 : _b.url, onFocus: handleLinkFocus }, getLinkProps(((_c = item.data) === null || _c === void 0 ? void 0 : _c.url) || '', undefined, (_d = item.data) === null || _d === void 0 ? void 0 : _d.target)), item.title),
|
|
@@ -5,6 +5,8 @@ interface NavigationPopupProps {
|
|
|
5
5
|
headerRef?: RefObject<HTMLDivElement>;
|
|
6
6
|
children: React.ReactNode;
|
|
7
7
|
id?: string;
|
|
8
|
+
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
|
|
9
|
+
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
|
8
10
|
}
|
|
9
|
-
export declare const NHNavigationPopup: ({ headerRef, children, id }: NavigationPopupProps) => React.ReactPortal | null;
|
|
11
|
+
export declare const NHNavigationPopup: ({ headerRef, children, id, onMouseEnter, onMouseLeave, }: NavigationPopupProps) => React.ReactPortal | null;
|
|
10
12
|
export {};
|
|
@@ -12,7 +12,7 @@ const getNextIndex = (currentIndex, offset, elementsCount) => {
|
|
|
12
12
|
}
|
|
13
13
|
return (currentIndex + offset + elementsCount) % elementsCount;
|
|
14
14
|
};
|
|
15
|
-
export const NHNavigationPopup = ({ headerRef, children, id }) => {
|
|
15
|
+
export const NHNavigationPopup = ({ headerRef, children, id, onMouseEnter, onMouseLeave, }) => {
|
|
16
16
|
const popupRef = useRef(null);
|
|
17
17
|
const focusRelativeElement = useCallback((offset) => {
|
|
18
18
|
const popup = popupRef.current;
|
|
@@ -61,6 +61,6 @@ export const NHNavigationPopup = ({ headerRef, children, id }) => {
|
|
|
61
61
|
};
|
|
62
62
|
}, [focusRelativeElement]);
|
|
63
63
|
return (headerRef === null || headerRef === void 0 ? void 0 : headerRef.current)
|
|
64
|
-
? ReactDOM.createPortal(React.createElement("div", { className: b(), id: id, ref: popupRef }, children), headerRef.current)
|
|
64
|
+
? ReactDOM.createPortal(React.createElement("div", { className: b(), id: id, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, ref: popupRef }, children), headerRef.current)
|
|
65
65
|
: null;
|
|
66
66
|
};
|