UNPKG

@atlaskit/side-navigation

Version:

A highly composable side navigation component that supports nested views.

186 lines (180 loc) • 7.8 kB
/* index.tsx generated by @compiled/babel-plugin v3.0.2 */ import _extends from "@babel/runtime/helpers/extends"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import "./index.compiled.css"; import { ax, ix } from "@compiled/react/runtime"; import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import ExitingPersistence from '@atlaskit/motion/exiting-persistence'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import useChildIds from '../../common/use-child-ids'; import { GoBackItem as GoBackButton } from '../Item/go-back-item'; import { NestingItem } from '../NestingItem'; import { NestedContext } from './nested-context'; import { NestingMotion } from './nesting-motion'; // Named so ERT doesn't pick up the override name as a type. export var ROOT_ID = 'ATLASKIT_NESTED_ROOT'; /** * @deprecated `@atlaskit/side-navigation` is deprecated. Use `@atlaskit/navigation-system` instead. */ var nestableNavigationContentStyles = null; var nestingRootStyles = null; /** * __Nestable navigation content__ * * The container for navigation items with nested views * * - [Examples](https://atlassian.design/components/side-navigation/examples#nested-navigation) * - [Code](https://atlassian.design/components/side-navigation/code) * * @deprecated `@atlaskit/side-navigation` is deprecated. Use `@atlaskit/navigation-system` instead. */ export var NestableNavigationContent = function NestableNavigationContent(props) { var containerRef = useRef(null); var children = props.children, testId = props.testId, overrides = props.overrides, initialStack = props.initialStack, onChange = props.onChange, onUnknownNest = props.onUnknownNest, stack = props.stack, showTopScrollIndicator = props.showTopScrollIndicator, _props$isDefaultFocus = props.isDefaultFocusControl, isDefaultFocusControl = _props$isDefaultFocus === void 0 ? true : _props$isDefaultFocus; var goBackButtonRef = useRef(null); var _useState = useState(stack || initialStack || []), _useState2 = _slicedToArray(_useState, 2), committedStack = _useState2[0], setCommittedStack = _useState2[1]; var controlledStack = stack || undefined; var currentStackId = committedStack[committedStack.length - 1] || ROOT_ID; var _useState3 = useState('nesting'), _useState4 = _slicedToArray(_useState3, 2), transition = _useState4[0], setTransition = _useState4[1]; var backTestId = testId && "".concat(testId, "--go-back-item"); var _useState5 = useState(''), _useState6 = _slicedToArray(_useState5, 2), activeParentId = _useState6[0], setActiveParentId = _useState6[1]; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), focusGoBackButton = _useState8[0], setFocusGoBackButton = _useState8[1]; var shouldFocus = isDefaultFocusControl && fg('platform-side-navigation-keyboard-focus'); var renderGoBackItem = overrides && overrides.GoBackItem && overrides.GoBackItem.render ? overrides.GoBackItem.render : function (props) { return /*#__PURE__*/React.createElement(GoBackButton, props, "Go back"); }; var _useChildIds = useChildIds(currentStackId, committedStack, onUnknownNest), childIdsRef = _useChildIds.childIdsRef; var onNestHandler = useCallback(function (layerId) { onChange && onChange(committedStack.concat(layerId)); setFocusGoBackButton(true); if (controlledStack) { // We are in controlled mode - ignore the steps. return; } // We need to split the state update into to parts. // First: Updating the direction of the motions. // Second: Actually updating the stack (which will cause elements to enter & leave). setTransition('nesting'); requestAnimationFrame(function () { setCommittedStack(function (prev) { var newStack = prev.concat(layerId); return newStack; }); }); }, [controlledStack, onChange, committedStack]); var onUnNestHandler = useCallback(function () { onChange && onChange(committedStack.slice(0, committedStack.length - 1)); setActiveParentId(currentStackId); setFocusGoBackButton(false); if (controlledStack) { // We are in controlled mode - ignore the steps. return; } // We need to split the state update into to parts. // First: Updating the direction of the motions. // Second: Actually updating the stack (which will cause elements to enter & leave). setTransition('unnesting'); requestAnimationFrame(function () { setCommittedStack(function (prev) { var newStack = prev.slice(0, prev.length - 1); return newStack; }); }); }, [controlledStack, onChange, committedStack, setActiveParentId, currentStackId]); useEffect(function () { if (!controlledStack) { // We aren't in controlled mode - bail out. return; } if (JSON.stringify(committedStack) === JSON.stringify(controlledStack)) { // stacks are equal - do nothing! return; } // Controlled prop updated, let's figure out if we're nesting or unnesting. if (controlledStack.length < committedStack.length) { // We are unnesting (removing from the stack) setTransition('unnesting'); } else { // We are nesting (adding to the stack) setTransition('nesting'); } requestAnimationFrame(function () { setCommittedStack(controlledStack); }); }, [committedStack, controlledStack]); var backButton = renderGoBackItem({ onClick: onUnNestHandler, testId: backTestId, ref: shouldFocus ? goBackButtonRef : null }); var context = useMemo(function () { return { currentStackId: currentStackId, backButton: backButton, stack: committedStack, onNest: onNestHandler, onUnNest: onUnNestHandler, parentId: ROOT_ID, childIds: childIdsRef, forceShowTopScrollIndicator: showTopScrollIndicator, activeParentId: activeParentId, goBackButtonRef: goBackButtonRef, isDefaultFocusControl: isDefaultFocusControl, focusGoBackButton: focusGoBackButton }; }, [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]); var manageFocus = function manageFocus(event) { var triggeredByKeyboard = event.nativeEvent.detail === 0; if (triggeredByKeyboard) { containerRef.current && containerRef.current.focus(); } }; return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", { "data-testid": testId, ref: containerRef, tabIndex: -1, onClick: manageFocus, className: ax(["_12ji1r31 _1qu2glyw _12y31o36 _4t3i1osq _kqswh2mm"]) }, /*#__PURE__*/React.createElement(ExitingPersistence, null, /*#__PURE__*/React.createElement(NestingMotion // Key is needed to have a unique react instance per stack name. // This enables us to easily animate it in & out with exiting persistence. , { key: currentStackId, enterFrom: transition === 'nesting' ? 'right' : 'left', exitTo: transition === 'nesting' ? 'left' : 'right', testId: testId && "".concat(testId, "-anim") }, function (motion) { return /*#__PURE__*/React.createElement("div", _extends({}, motion, { className: ax(["_1e0c1txw _1bsb1osq _4t3i1osq _kqswstnw _2lx21bp4", motion.className]) }), /*#__PURE__*/React.createElement(NestedContext.Provider, { // This provider is inside the NestingMotion to ensure it keeps a stale // reference to the previous value. value: context }, /*#__PURE__*/React.createElement(NestingItem, { title: "", id: ROOT_ID }, children))); })))); };