@atlaskit/drawer
Version:
A drawer is a panel that slides in from the left side of the screen.
134 lines (131 loc) • 4.55 kB
JavaScript
/// <reference types="node" />
/* eslint-disable @repo/internal/dom-events/no-unsafe-event-listeners */
import React, { useCallback, useEffect } from 'react';
import { canUseDOM } from 'exenv';
import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next/usePlatformLeafEventHandler';
import { Layering } from '@atlaskit/layering/layering';
import { useCloseOnEscapePress } from '@atlaskit/layering/use-close-on-escape-press';
import { fg } from '@atlaskit/platform-feature-flags/fg';
import Portal from '@atlaskit/portal/portal';
import Blanket from './blanket';
import { DrawerPanel } from './drawer-panel/drawer-panel';
import { DrawerTopLayer } from './drawer-panel/drawer-top-layer';
// escape close manager for layering
const EscapeCloseManager = ({
onClose
}) => {
// wrap so that we can cast the event to a React.KeyboardEvent
const handleClose = useCallback(evt => {
onClose && onClose(evt);
}, [onClose]);
useCloseOnEscapePress({
onClose: handleClose
});
return /*#__PURE__*/React.createElement("span", null);
};
const DrawerBase = ({
width = 'narrow',
isOpen,
isFocusLockEnabled = true,
shouldReturnFocus = true,
autoFocusFirstElem = true,
onKeyDown,
testId,
children,
onClose,
onCloseComplete,
onOpenComplete,
zIndex = 'unset',
label,
titleId,
enterFrom
}) => {
const handleClose = usePlatformLeafEventHandler({
fn: (evt, analyticsEvent) => onClose === null || onClose === void 0 ? void 0 : onClose(evt, analyticsEvent),
action: 'dismissed',
componentName: 'drawer',
packageName: "@atlaskit/drawer",
packageVersion: "14.3.5",
analyticsData: {
trigger: 'escKey'
}
});
const handleKeyDown = useCallback(evt => {
onKeyDown && onKeyDown(evt);
}, [onKeyDown]);
useEffect(() => {
if (isOpen) {
window.addEventListener('keydown', handleKeyDown);
}
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown, isOpen]);
const handleBlanketClick = usePlatformLeafEventHandler({
fn: (evt, analyticsEvent) => onClose === null || onClose === void 0 ? void 0 : onClose(evt, analyticsEvent),
action: 'dismissed',
componentName: 'drawer',
packageName: "@atlaskit/drawer",
packageVersion: "14.3.5",
analyticsData: {
trigger: 'blanket'
}
});
const handleBackButtonClick = usePlatformLeafEventHandler({
fn: (evt, analyticsEvent) => onClose === null || onClose === void 0 ? void 0 : onClose(evt, analyticsEvent),
action: 'dismissed',
componentName: 'drawer',
packageName: "@atlaskit/drawer",
packageVersion: "14.3.5",
analyticsData: {
trigger: 'backButton'
}
});
const body = canUseDOM ? document.querySelector('body') : undefined;
if (!body) {
return null;
}
return /*#__PURE__*/React.createElement(Portal, {
zIndex: zIndex
}, /*#__PURE__*/React.createElement(Blanket, {
isOpen: isOpen,
onBlanketClicked: handleBlanketClick,
testId: testId && `${testId}--blanket`
}), /*#__PURE__*/React.createElement(DrawerPanel, {
testId: testId,
isOpen: isOpen,
onClose: handleBackButtonClick,
onCloseComplete: onCloseComplete,
onOpenComplete: onOpenComplete,
width: width,
enterFrom: enterFrom,
label: label,
titleId: titleId,
autoFocusFirstElem: autoFocusFirstElem,
isFocusLockEnabled: isFocusLockEnabled,
shouldReturnFocus: shouldReturnFocus
}, isOpen ? /*#__PURE__*/React.createElement(Layering, {
isDisabled: false
}, children, /*#__PURE__*/React.createElement(EscapeCloseManager, {
onClose: handleClose
})) : children));
};
/**
* __Drawer__
*
* A drawer is a panel that slides in from the left side of the screen.
*
* - [Examples](https://atlassian.design/components/drawer/examples)
* - [Code](https://atlassian.design/components/drawer/code)
* - [Usage](https://atlassian.design/components/drawer/usage)
*/
export const Drawer = props => {
if (fg('platform-dst-top-layer')) {
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props -- internal implementation component takes the same DrawerProps
return /*#__PURE__*/React.createElement(DrawerTopLayer, props);
}
// eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props -- internal implementation component takes the same DrawerProps
return /*#__PURE__*/React.createElement(DrawerBase, props);
};
// Public API aliases preserved from an eliminated entry-point (volt-migrate-package).
export { Drawer as default };