@elastic/eui
Version:
Elastic UI Component Library
189 lines (180 loc) • 8.23 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
var _excluded = ["id", "children", "className", "initialIsCollapsed", "isCollapsed", "onCollapseToggle", "width", "side", "focusTrapProps"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useRef, useMemo, useState, useEffect, useCallback } from 'react';
import classNames from 'classnames';
import { useEuiMemoizedStyles, useEuiThemeCSSVariables, useGeneratedHtmlId, throttle } from '../../services';
import { EuiFlyout } from '../flyout';
import { useEuiI18n } from '../i18n';
import { euiHeaderVariables } from '../header/header.styles';
import { EuiCollapsibleNavContext } from './context';
import { EuiCollapsibleNavButton } from './collapsible_nav_button';
import { euiCollapsibleNavBetaStyles } from './collapsible_nav_beta.styles';
var _EuiCollapsibleNavBeta = function _EuiCollapsibleNavBeta(_ref) {
var id = _ref.id,
children = _ref.children,
className = _ref.className,
_ref$initialIsCollaps = _ref.initialIsCollapsed,
initialIsCollapsed = _ref$initialIsCollaps === void 0 ? false : _ref$initialIsCollaps,
propsIsCollapsed = _ref.isCollapsed,
onCollapseToggle = _ref.onCollapseToggle,
_ref$width = _ref.width,
_width = _ref$width === void 0 ? 248 : _ref$width,
_ref$side = _ref.side,
side = _ref$side === void 0 ? 'left' : _ref$side,
_focusTrapProps = _ref.focusTrapProps,
rest = _objectWithoutProperties(_ref, _excluded);
var _useEuiThemeCSSVariab = useEuiThemeCSSVariables(),
setGlobalCSSVariables = _useEuiThemeCSSVariab.setGlobalCSSVariables;
var _useEuiMemoizedStyles = useEuiMemoizedStyles(euiHeaderVariables),
headerHeight = _useEuiMemoizedStyles.height;
/**
* Collapsed state
*/
var _useState = useState(initialIsCollapsed),
_useState2 = _slicedToArray(_useState, 2),
isCollapsed = _useState2[0],
setIsCollapsed = _useState2[1];
var toggleCollapsed = useCallback(function () {
return setIsCollapsed(function (isCollapsed) {
onCollapseToggle === null || onCollapseToggle === void 0 || onCollapseToggle(!isCollapsed);
return !isCollapsed;
});
}, [onCollapseToggle]);
var onClose = useCallback(function () {
setIsCollapsed(true);
onCollapseToggle === null || onCollapseToggle === void 0 || onCollapseToggle(true);
}, [onCollapseToggle]);
// Controlled state
useEffect(function () {
if (propsIsCollapsed !== undefined) {
setIsCollapsed(propsIsCollapsed);
}
}, [propsIsCollapsed]);
/**
* Responsive behavior
* By default on large enough screens, the nav is always a push flyout,
* but on smaller/mobile screens, the nav overlays the page instead
*/
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
isOverlay = _useState4[0],
setIsOverlay = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
isOverlayFullWidth = _useState6[0],
setIsOverlayFullWidth = _useState6[1];
var _useState7 = useState(false),
_useState8 = _slicedToArray(_useState7, 2),
isOverlayOpen = _useState8[0],
setIsOverlayOpen = _useState8[1];
var toggleOverlayFlyout = useCallback(function () {
setIsOverlayOpen(function (isOpen) {
return !isOpen;
});
}, []);
var closeOverlayFlyout = useCallback(function () {
return setIsOverlayOpen(false);
}, []);
var flyoutType = isOverlay ? 'overlay' : 'push';
var isPush = !isOverlay;
// Set up a window resize listener that determines breakpoint behavior
useEffect(function () {
var getBreakpoints = function getBreakpoints() {
setIsOverlay(window.innerWidth < _width * 3);
setIsOverlayFullWidth(window.innerWidth < _width * 1.5);
};
getBreakpoints();
var onWindowResize = throttle(getBreakpoints, 50);
window.addEventListener('resize', onWindowResize);
return function () {
return window.removeEventListener('resize', onWindowResize);
};
}, [_width]);
var width = useMemo(function () {
if (isOverlayFullWidth) return '100%';
if (isPush && isCollapsed) return headerHeight;
return "".concat(_width, "px");
}, [_width, isOverlayFullWidth, isPush, isCollapsed, headerHeight]);
// Other UI elements may need to account for the nav width -
// set a global CSS variable that they can use
useEffect(function () {
setGlobalCSSVariables({
'--euiCollapsibleNavOffset': isOverlay ? '0' : width
});
}, [width, isOverlay, setGlobalCSSVariables]);
/**
* Prop setup
*/
var flyoutID = useGeneratedHtmlId({
conditionalId: id,
suffix: 'euiCollapsibleNav'
});
var defaultAriaLabel = useEuiI18n('euiCollapsibleNavBeta.ariaLabel', 'Site menu');
var buttonRef = useRef(null);
var focusTrapProps = useMemo(function () {
return _objectSpread(_objectSpread({}, _focusTrapProps), {}, {
shards: [buttonRef].concat(_toConsumableArray((_focusTrapProps === null || _focusTrapProps === void 0 ? void 0 : _focusTrapProps.shards) || []))
});
}, [_focusTrapProps]);
var classes = classNames('euiCollapsibleNav', 'euiCollapsibleNavBeta', className);
var styles = useEuiMemoizedStyles(euiCollapsibleNavBetaStyles);
var cssStyles = [styles.euiCollapsibleNavBeta, isPush && styles.isPush, styles[side], isPush && isCollapsed && styles.isPushCollapsed, isOverlayFullWidth && styles.isOverlayFullWidth];
var flyout = ___EmotionJSX(EuiFlyout, _extends({
"aria-label": defaultAriaLabel
}, rest, {
// EuiCollapsibleNav is significantly less permissive than EuiFlyout
id: flyoutID,
session: "never",
css: cssStyles,
className: classes,
size: width,
side: side,
focusTrapProps: focusTrapProps,
as: "nav",
type: flyoutType,
paddingSize: "none",
pushMinBreakpoint: "xs",
onClose: isPush ? onClose : closeOverlayFlyout,
hideCloseButton: true
}), children);
var hideFlyout = isOverlay && !isOverlayOpen;
return ___EmotionJSX(EuiCollapsibleNavContext.Provider, {
value: {
isPush: isPush,
isCollapsed: isCollapsed,
isOverlayOpen: isOverlayOpen,
side: side,
closePortals: closeOverlayFlyout
}
}, ___EmotionJSX(EuiCollapsibleNavButton, {
ref: buttonRef,
onClick: isPush ? toggleCollapsed : toggleOverlayFlyout,
"aria-controls": flyoutID
}), !hideFlyout && flyout);
};
/**
* Combined export with subcomponents
*/
import { EuiCollapsibleNavBody, EuiCollapsibleNavFooter } from './collapsible_nav_body_footer';
import { EuiCollapsibleNavItem } from './collapsible_nav_item';
import { KibanaCollapsibleNavSolution } from './_kibana_solution';
import { jsx as ___EmotionJSX } from "@emotion/react";
export var EuiCollapsibleNavBeta = Object.assign(_EuiCollapsibleNavBeta, {
Body: EuiCollapsibleNavBody,
Footer: EuiCollapsibleNavFooter,
Item: EuiCollapsibleNavItem,
KibanaSolution: KibanaCollapsibleNavSolution
});