UNPKG

@atlaskit/drawer

Version:

A drawer is a panel that slides in from the left side of the screen.

88 lines (86 loc) • 3.78 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useDrawerStack; var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = require("react"); var _useLazyCallback = _interopRequireDefault(require("@atlaskit/ds-lib/use-lazy-callback")); var _usePreviousValue = _interopRequireDefault(require("@atlaskit/ds-lib/use-previous-value")); var _useStateRef3 = _interopRequireDefault(require("@atlaskit/ds-lib/use-state-ref")); /** * **Major versions will not know about each other** * * An array holding references to all currently open drawers. This only works * for drawers of the same major version, because the reference differs between * majors (for example V13 will not know about any from V14). * * Adapted from `useModalStack` in `@atlaskit/modal-dialog`. The top-layer drawer * path uses this to know its position in the stack so that only the foreground * drawer renders a visible `::backdrop` (this avoids cumulative darkening for * nested or stacked drawers). Unlike the modal version, the register is timed * off `isOpen` rather than `@atlaskit/motion`'s `useExitingPersistence`: the * `Dialog` primitive owns its own exit lifecycle, so the top-layer drawer needs * no `ExitingPersistence` wrapper. */ var drawerStackRegister = []; /** * Returns the position of the calling drawer in the drawer stack. A stack index * of `0` is the foreground (top of the stack); higher numbers are further back. */ function useDrawerStack(_ref) { var isOpen = _ref.isOpen, onStackChange = _ref.onStackChange; var _useStateRef = (0, _useStateRef3.default)(0), _useStateRef2 = (0, _slicedToArray2.default)(_useStateRef, 2), stackIndexRef = _useStateRef2[0], setStackIndex = _useStateRef2[1]; var currentStackIndex = stackIndexRef.current; var previousStackIndex = (0, _usePreviousValue.default)(stackIndexRef.current); // Kept stable for the lifetime of the component so it can be the identity in // the shared register. This is why it is a lazy callback and not a // useMemo/useCallback value. var updateStack = (0, _useLazyCallback.default)(function () { var newStackIndex = drawerStackRegister.indexOf(updateStack); // Read from the ref rather than state: this closure only ever sees the // initial state value. if (stackIndexRef.current !== newStackIndex) { setStackIndex(newStackIndex); stackIndexRef.current = newStackIndex; } }); (0, _react.useEffect)(function () { if (!isOpen) { return; } // Opening: join the front of the register (the newest open drawer is the // foreground at index 0), then notify every open drawer to recompute. if (drawerStackRegister.indexOf(updateStack) === -1) { drawerStackRegister.unshift(updateStack); } drawerStackRegister.forEach(function (callback) { return callback(); }); return function () { // Closing or unmounting: leave the register and notify the rest. var index = drawerStackRegister.indexOf(updateStack); if (index !== -1) { drawerStackRegister.splice(index, 1); } drawerStackRegister.forEach(function (callback) { return callback(); }); }; }, [isOpen, updateStack]); (0, _react.useEffect)(function () { if (previousStackIndex === undefined) { // Initial render: nothing to notify about. return; } if (previousStackIndex !== currentStackIndex) { onStackChange === null || onStackChange === void 0 || onStackChange(currentStackIndex); } }, [onStackChange, previousStackIndex, currentStackIndex]); return currentStackIndex; }