UNPKG

@atlaskit/navigation-system

Version:

The latest navigation system for Atlassian apps.

167 lines (161 loc) • 8.3 kB
/* toggle-button.tsx generated by @compiled/babel-plugin v3.0.2 */ import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import "./toggle-button.compiled.css"; import { ax, ix } from "@compiled/react/runtime"; 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; } import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { bind } from 'bind-event-listener'; import { useAnalyticsEvents } from '@atlaskit/analytics-next/useAnalyticsEvents'; import SidebarCollapseIcon from '@atlaskit/icon/core/sidebar-collapse'; import SidebarExpandIcon from '@atlaskit/icon/core/sidebar-expand'; import { useOpenLayerObserver } from '@atlaskit/layering/use-open-layer-observer'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import { requestClosePopovers } from '@atlaskit/top-layer/page-surface/request-close-popovers'; import { IconButton } from '../../top-nav-items/themed/icon-button'; import { SideNavToggleButtonAttachRef } from './side-nav-toggle-button-attach-ref'; import { sideNavToggleTooltipKeyboardShortcut } from './side-nav-toggle-tooltip-keyboard-shortcut'; import { SideNavVisibilityState } from './side-nav-visibility-state'; import { useIsSideNavShortcutEnabled } from './use-is-side-nav-shortcut-enabled'; import { useSideNavVisibility } from './use-side-nav-visibility'; import { useToggleSideNav } from './use-toggle-side-nav'; var toggleButtonTooltipOptions = { // We're disabling pointer events on the tooltip to prevent it from blocking mouse events, so that the side nav flyout stays open // when moving the mouse from the top bar to the side nav. ignoreTooltipPointerEvents: true, // A press swaps the label between `collapseLabel` and `expandLabel`, so keep the // tooltip open to show the new label. hasNewContentOnTriggerClick: true }; // For duplicate "mouseenter" issue when changing icons (see below) var silentIconStyles = null; /** * __SideNavToggleButton__ * * Button for toggling the side nav. It should be used in the top bar. */ export var SideNavToggleButton = function SideNavToggleButton(_ref) { var _ref$defaultCollapsed = _ref.defaultCollapsed, defaultCollapsed = _ref$defaultCollapsed === void 0 ? false : _ref$defaultCollapsed, expandLabel = _ref.expandLabel, collapseLabel = _ref.collapseLabel, testId = _ref.testId, interactionName = _ref.interactionName, onClick = _ref.onClick; var _useSideNavVisibility = useSideNavVisibility({ defaultCollapsed: defaultCollapsed }), isSideNavExpandedOnDesktop = _useSideNavVisibility.isExpandedOnDesktop, isSideNavExpandedOnMobile = _useSideNavVisibility.isExpandedOnMobile; var sideNavState = useContext(SideNavVisibilityState); // When default state is provided to `Root` the state in context will already be // initialized in SSR var _useState = useState(sideNavState === null ? !defaultCollapsed : isSideNavExpandedOnDesktop), _useState2 = _slicedToArray(_useState, 2), isSideNavExpanded = _useState2[0], setIsSideNavExpanded = _useState2[1]; var ref = useContext(SideNavToggleButtonAttachRef); /** * Addresses HOT-121458 by ensuring that the toggle button element in context is always up to date. * * My theory is that something to do with SSR, hydration and suspense was causing the * underlying HTML element to change but without causing the toggle button to remount. * * This meant the effect calling `ref()` did not re-run, and the value in context became stale. */ var _useState3 = useState(null), _useState4 = _slicedToArray(_useState3, 2), element = _useState4[0], setElement = _useState4[1]; useEffect(function () { ref(element); }, [element, ref]); useEffect(function () { var _window$matchMedia = window.matchMedia('(min-width: 64rem)'), matches = _window$matchMedia.matches; setIsSideNavExpanded(matches ? isSideNavExpandedOnDesktop : isSideNavExpandedOnMobile); }, [isSideNavExpandedOnDesktop, isSideNavExpandedOnMobile]); useEffect(function () { // When screen size changes, ensure we use the correct visibility state var mediaQueryList = window.matchMedia('(min-width: 64rem)'); return bind(mediaQueryList, { type: 'change', listener: function listener() { setIsSideNavExpanded(mediaQueryList.matches ? isSideNavExpandedOnDesktop : isSideNavExpandedOnMobile); } }); }, [isSideNavExpandedOnDesktop, isSideNavExpandedOnMobile]); var toggleVisibility = useToggleSideNav({ trigger: 'toggle-button' }); var _useAnalyticsEvents = useAnalyticsEvents(), createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent; var openLayerObserver = useOpenLayerObserver({ isEnabled: !fg('platform-dst-top-layer') }); var handleClick = useCallback(function (event, analyticsEvent) { onClick === null || onClick === void 0 || onClick(event, analyticsEvent, { isSideNavVisible: isSideNavExpanded }); toggleVisibility(); // Not gated. Top-layer tooltips (`platform-dst-top-layer-tooltip`) are not known to the observer. requestClosePopovers(); openLayerObserver === null || openLayerObserver === void 0 || openLayerObserver.closeLayers(); }, [isSideNavExpanded, onClick, openLayerObserver, toggleVisibility]); var handlePointerEnter = useCallback(function () { // Hovers don't do anything on mobile, so not capturing var isDesktop = window.matchMedia('(min-width: 64rem)').matches; if (!isDesktop) { return; } var navigationAnalyticsEvent = createAnalyticsEvent({ source: 'topNav', actionSubject: 'sideNav', action: 'hovered', actionSubjectId: 'sideNavButton', attributes: { itemState: isSideNavExpanded ? 'expanded' : 'collapsed', screen: 'desktop' } }); navigationAnalyticsEvent.fire('navigation'); }, [createAnalyticsEvent, isSideNavExpanded]); /** * ## Behaviour * It is intentional that collapse icon will be used while the flyout is open. * The icon is tied to the expanded / collapse state, and not the flyout state. * * ## Why a function? * Unfortunately, changing the icon inside an <IconButton> when the user is over * the button will cause the svg element to be replaced, which can trigger a * "mouseenter" event. This is problematic when the user is already over the button, * as it can result in a "mouseenter" event after the user manually entered the button. * * `icon` accepts a function for the `icon` prop (ie a render prop), so we don't need to * memoize it, or pull it out into a new function */ var icon = function icon(props) { return /*#__PURE__*/React.createElement("span", { className: ax(["_1e0c1bgi _lcxvglyw"]) }, isSideNavExpanded ? /*#__PURE__*/React.createElement(SidebarCollapseIcon, props) : /*#__PURE__*/React.createElement(SidebarExpandIcon, props)); }; var isShortcutEnabled = useIsSideNavShortcutEnabled(); var tooltipProps = useMemo(function () { return _objectSpread(_objectSpread({}, toggleButtonTooltipOptions), {}, { shortcut: isShortcutEnabled ? sideNavToggleTooltipKeyboardShortcut : undefined }); }, [isShortcutEnabled]); return /*#__PURE__*/React.createElement(IconButton, { appearance: "subtle", label: isSideNavExpanded ? collapseLabel : expandLabel, icon: icon, onClick: handleClick, onPointerEnter: handlePointerEnter, testId: testId, isTooltipDisabled: false, interactionName: interactionName, ref: setElement, tooltip: tooltipProps }); };