UNPKG

6.48 kBJavaScriptView Raw
1import { __rest } from "tslib";
2import * as React from 'react';
3import styles from '@patternfly/react-styles/css/components/Nav/nav';
4import { css } from '@patternfly/react-styles';
5import { NavContext } from './Nav';
6import { PageSidebarContext } from '../Page/PageSidebar';
7import { useOUIAProps } from '../../helpers';
8import { Popper } from '../../helpers/Popper/Popper';
9import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
10export const NavItem = (_a) => {
11 var { children, styleChildren = true, className, to, isActive = false, groupId = null, itemId = null, preventDefault = false, onClick = null, component = 'a', flyout, onShowFlyout, ouiaId, ouiaSafe } = _a, props = __rest(_a, ["children", "styleChildren", "className", "to", "isActive", "groupId", "itemId", "preventDefault", "onClick", "component", "flyout", "onShowFlyout", "ouiaId", "ouiaSafe"]);
12 const { flyoutRef, setFlyoutRef } = React.useContext(NavContext);
13 const { isNavOpen } = React.useContext(PageSidebarContext);
14 const [flyoutTarget, setFlyoutTarget] = React.useState(null);
15 const [isHovered, setIsHovered] = React.useState(false);
16 const ref = React.useRef();
17 const flyoutVisible = ref === flyoutRef;
18 const popperRef = React.useRef();
19 const Component = component;
20 const hasFlyout = flyout !== undefined;
21 const showFlyout = (show, override) => {
22 if ((!flyoutVisible || override) && show) {
23 setFlyoutRef(ref);
24 }
25 else if ((flyoutVisible || override) && !show) {
26 setFlyoutRef(null);
27 }
28 onShowFlyout && show && onShowFlyout();
29 };
30 const onMouseOver = (event) => {
31 const evtContainedInFlyout = event.target.closest('.pf-c-nav__item.pf-m-flyout');
32 if (hasFlyout && !flyoutVisible) {
33 showFlyout(true);
34 }
35 else if (flyoutRef !== null && !evtContainedInFlyout) {
36 setFlyoutRef(null);
37 }
38 };
39 const onFlyoutClick = (event) => {
40 const target = event.target;
41 const closestItem = target.closest('.pf-m-flyout');
42 if (!closestItem) {
43 if (hasFlyout) {
44 showFlyout(false, true);
45 }
46 else if (flyoutRef !== null) {
47 setFlyoutRef(null);
48 }
49 }
50 };
51 const handleFlyout = (event) => {
52 var _a, _b;
53 const key = event.key;
54 const target = event.target;
55 if (!(((_a = popperRef === null || popperRef === void 0 ? void 0 : popperRef.current) === null || _a === void 0 ? void 0 : _a.contains(target)) || (hasFlyout && ((_b = ref === null || ref === void 0 ? void 0 : ref.current) === null || _b === void 0 ? void 0 : _b.contains(target))))) {
56 return;
57 }
58 if (key === ' ' || key === 'ArrowRight') {
59 event.stopPropagation();
60 event.preventDefault();
61 if (!flyoutVisible) {
62 showFlyout(true);
63 setFlyoutTarget(target);
64 }
65 }
66 if (key === 'Escape' || key === 'ArrowLeft') {
67 if (flyoutVisible) {
68 event.stopPropagation();
69 event.preventDefault();
70 showFlyout(false);
71 }
72 }
73 };
74 React.useEffect(() => {
75 if (hasFlyout) {
76 window.addEventListener('click', onFlyoutClick);
77 }
78 return () => {
79 if (hasFlyout) {
80 window.removeEventListener('click', onFlyoutClick);
81 }
82 };
83 }, []);
84 React.useEffect(() => {
85 if (flyoutTarget) {
86 if (flyoutVisible) {
87 const flyoutItems = Array.from(popperRef.current.getElementsByTagName('UL')[0].children).filter(el => !(el.classList.contains('pf-m-disabled') || el.classList.contains('pf-c-divider')));
88 flyoutItems[0].firstChild.focus();
89 }
90 else {
91 flyoutTarget.focus();
92 }
93 }
94 }, [flyoutVisible, flyoutTarget]);
95 const flyoutButton = (React.createElement("span", { className: css(styles.navToggle) },
96 React.createElement("span", { className: css(styles.navToggleIcon) },
97 React.createElement(AngleRightIcon, { "aria-hidden": true }))));
98 const renderDefaultLink = (context) => {
99 const preventLinkDefault = preventDefault || !to;
100 return (React.createElement(Component, Object.assign({ href: to, onClick: (e) => context.onSelect(e, groupId, itemId, to, preventLinkDefault, onClick), className: css(styles.navLink, isActive && styles.modifiers.current, isHovered && styles.modifiers.hover, className), "aria-current": isActive ? 'page' : null, tabIndex: isNavOpen ? null : '-1' }, props),
101 children,
102 flyout && flyoutButton));
103 };
104 const renderClonedChild = (context, child) => React.cloneElement(child, Object.assign(Object.assign({ onClick: (e) => context.onSelect(e, groupId, itemId, to, preventDefault, onClick), 'aria-current': isActive ? 'page' : null }, (styleChildren && {
105 className: css(styles.navLink, isActive && styles.modifiers.current, child.props && child.props.className)
106 })), { tabIndex: child.props.tabIndex || isNavOpen ? null : -1, children: hasFlyout ? (React.createElement(React.Fragment, null,
107 child.props.children,
108 flyoutButton)) : (child.props.children) }));
109 const ouiaProps = useOUIAProps(NavItem.displayName, ouiaId, ouiaSafe);
110 const handleMouseEnter = () => {
111 setIsHovered(true);
112 };
113 const handleMouseLeave = () => {
114 setIsHovered(false);
115 };
116 const flyoutPopper = (React.createElement(Popper, { reference: ref, popper: React.createElement("div", { ref: popperRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }, flyout), placement: "right-start", isVisible: flyoutVisible, onDocumentKeyDown: handleFlyout }));
117 const navItem = (React.createElement(React.Fragment, null,
118 React.createElement("li", Object.assign({ onMouseOver: onMouseOver, className: css(styles.navItem, hasFlyout && styles.modifiers.flyout, className), ref: ref }, ouiaProps),
119 React.createElement(NavContext.Consumer, null, context => React.isValidElement(children)
120 ? renderClonedChild(context, children)
121 : renderDefaultLink(context))),
122 flyout && flyoutPopper));
123 return navItem;
124};
125NavItem.displayName = 'NavItem';
126//# sourceMappingURL=NavItem.js.map
\No newline at end of file