preact-arco-design
Version:
Arco Design React UI Library.
295 lines (270 loc) • 10.5 kB
JavaScript
var __assign = this && this.__assign || function () {
__assign = Object.assign || function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) {
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = this && this.__read || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o),
r,
ar = [],
e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) {
ar.push(r.value);
}
} catch (error) {
e = {
error: error
};
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
};
import React, { useContext, useRef, useEffect, useCallback, useMemo, useState, useImperativeHandle } from "preact/compat";
import { CSSTransition } from "preact-transition-group-4";
import { findDOMNode } from "preact/compat";
import IconClose from "../../icon/react-icon/IconClose";
import cs from "../_util/classNames";
import Button from "../Button";
import Portal from "../Portal";
import ConfigProvider, { ConfigContext } from "../ConfigProvider";
import { isServerRendering, off, on } from "../_util/dom";
import IconHover from "../_class/icon-hover";
import { Esc } from "../_util/keycode";
import { isObject } from "../_util/is";
import useOverflowHidden from "../_util/hooks/useOverflowHidden";
import useMergeProps from "../_util/hooks/useMergeProps";
var defaultProps = {
placement: 'right',
width: 250,
height: 250,
escToExit: true,
mask: true,
closable: true,
maskClosable: true,
mountOnEnter: true,
getPopupContainer: function getPopupContainer() {
return document.body;
}
};
function Drawer(baseProps, ref) {
var _a, _b, _c, _d;
var context = useContext(ConfigContext);
var locale = context.locale,
getPrefixCls = context.getPrefixCls,
componentConfig = context.componentConfig,
rtl = context.rtl;
var props = useMergeProps(baseProps, defaultProps, componentConfig === null || componentConfig === void 0 ? void 0 : componentConfig.Drawer);
var style = props.style,
className = props.className,
children = props.children,
wrapClassName = props.wrapClassName,
maskStyle = props.maskStyle,
headerStyle = props.headerStyle,
bodyStyle = props.bodyStyle,
title = props.title,
footer = props.footer,
okText = props.okText,
cancelText = props.cancelText,
width = props.width,
height = props.height,
placement = props.placement,
mask = props.mask,
visible = props.visible,
closable = props.closable,
maskClosable = props.maskClosable,
confirmLoading = props.confirmLoading,
mountOnEnter = props.mountOnEnter,
unmountOnExit = props.unmountOnExit,
afterOpen = props.afterOpen,
afterClose = props.afterClose,
getPopupContainer = props.getPopupContainer,
escToExit = props.escToExit,
propGetChildrenPopupContainer = props.getChildrenPopupContainer,
focusLock = props.focusLock,
autoFocus = props.autoFocus,
okButtonProps = props.okButtonProps,
cancelButtonProps = props.cancelButtonProps;
var drawerWrapperRef = useRef(null);
var contentWrapperRef = useRef(null);
var _e = __read(useState(false), 2),
shouldReComputeFixed = _e[0],
setShouldReComputeFixed = _e[1];
var _f = __read(useState(), 2),
popupZIndex = _f[0],
setPopupZIndex = _f[1];
var prefixCls = getPrefixCls('drawer'); // Record whether is exiting, to prevent `onCancel` being unnecessarily triggered when mask is clicked during the period.
var inExit = useRef(false); // Record whether it's opened to avoid element shaking during animation caused by focus lock.
var _g = __read(useState(false), 2),
isOpened = _g[0],
setIsOpened = _g[1]; // eslint-disable-next-line no-console
console.log(isOpened);
var getContainer = useCallback(function () {
var container = getPopupContainer && getPopupContainer();
return findDOMNode(container) || document.body;
}, [getPopupContainer]);
var isFixed = useMemo(function () {
return !isServerRendering && getContainer() === document.body; // eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldReComputeFixed, getContainer]);
useOverflowHidden(getContainer, {
hidden: visible && mask
});
useImperativeHandle(ref, function () {
return drawerWrapperRef.current;
});
useEffect(function () {
// 初始就是展示,且设置了 getPopupContainer 时,组件挂载后重新执行下 isFixed 的计算逻辑,避免 getPopupContainer 返回的节点还未挂载,导致 isFixed 为true,样式表现错误的问题。
if (visible && props.getPopupContainer) {
// Recompute `isFixed` to avoid style error resulting from truthy `isFixed` value due to the custom container dom is not mounted yet.
setShouldReComputeFixed(true);
}
}, []);
useEffect(function () {
var _a;
if (visible && popupZIndex === undefined) {
if (drawerWrapperRef.current) {
// Set zIndex for nested drawer components based on zIndex of wrapper
var zIndex = +((_a = window.getComputedStyle(drawerWrapperRef.current, null)) === null || _a === void 0 ? void 0 : _a.zIndex);
if (!isNaN(zIndex)) {
setPopupZIndex(zIndex + 1);
}
}
}
}, [visible, popupZIndex]);
useEffect(function () {
var onKeyDown = function onKeyDown(e) {
if (escToExit && e && e.key === Esc.key && props.onCancel) {
props.onCancel(e);
}
};
if (visible) {
on(document, 'keydown', onKeyDown);
}
return function () {
off(document, 'keydown', onKeyDown);
};
}, [visible, escToExit]);
var element = React.createElement("div", {
className: "".concat(prefixCls, "-scroll")
}, title !== null && React.createElement("div", {
className: "".concat(prefixCls, "-header"),
style: headerStyle
}, React.createElement("div", {
className: "".concat(prefixCls, "-header-title")
}, title)), closable && React.createElement(IconHover, {
onClick: props.onCancel,
className: "".concat(prefixCls, "-close-icon")
}, React.createElement(IconClose, null)), React.createElement("div", {
ref: contentWrapperRef,
style: bodyStyle,
className: cs("".concat(prefixCls, "-content"), (_a = {}, _a["".concat(prefixCls, "-content-nofooter")] = footer === null, _a["".concat(prefixCls, "-content-noheader")] = title === null, _a))
}, React.createElement(ConfigProvider, __assign({}, context, {
zIndex: popupZIndex || 1050,
getPopupContainer: function getPopupContainer(node) {
return typeof propGetChildrenPopupContainer === 'function' ? propGetChildrenPopupContainer(node) : contentWrapperRef.current;
}
}), children)), footer !== null && (footer ? React.createElement("div", {
className: "".concat(prefixCls, "-footer")
}, footer) : React.createElement("div", {
className: "".concat(prefixCls, "-footer")
}, React.createElement(Button, __assign({
onClick: props.onCancel
}, cancelButtonProps), cancelText || locale.Drawer.cancelText), React.createElement(Button, __assign({
type: "primary",
loading: confirmLoading,
onClick: props.onOk
}, okButtonProps), okText || locale.Drawer.okText))));
var globalFocusLockConfig = context.focusLock.drawer;
var globalFocusLock = !!globalFocusLockConfig;
var globalAutoFocus = isObject(globalFocusLockConfig) && globalFocusLockConfig.autoFocus;
var innerFocusLock = focusLock !== undefined ? focusLock : globalFocusLock; // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
var innerAutoFocus = autoFocus !== undefined ? autoFocus : globalAutoFocus; // eslint-disable-next-line no-console
console.log(innerAutoFocus); // Only enable FocusLock when drawer is fully opened, to avoid element shaking.
var dom = innerFocusLock ? element : element;
return React.createElement(Portal, {
forceRender: !mountOnEnter,
visible: visible,
getContainer: getPopupContainer
}, React.createElement("div", {
ref: drawerWrapperRef,
className: cs("".concat(prefixCls, "-wrapper"), (_b = {}, _b["".concat(prefixCls, "-no-mask")] = !mask, _b["".concat(prefixCls, "-wrapper-hide")] = !visible, _b), wrapClassName),
style: isFixed ? {
position: 'fixed'
} : {
zIndex: 'inherit',
position: 'absolute'
}
}, mask ? React.createElement(CSSTransition, {
in: visible,
appear: true,
timeout: 300,
classNames: "fadeInStandard",
mountOnEnter: mountOnEnter,
unmountOnExit: unmountOnExit
}, React.createElement("div", {
className: "".concat(prefixCls, "-mask"),
style: maskStyle,
onClick: function onClick(e) {
if (!inExit.current && maskClosable) {
props.onCancel && props.onCancel(e);
}
}
})) : null, React.createElement(CSSTransition, {
in: visible,
appear: true,
timeout: 300,
classNames: {
top: 'slideTop',
bottom: 'slideBottom',
left: 'slideLeft',
right: 'slideRight'
}[placement],
mountOnEnter: mountOnEnter,
unmountOnExit: unmountOnExit,
onEnter: function onEnter(e) {
e.parentNode.style.display = 'block';
inExit.current = false;
},
onEntered: function onEntered() {
setIsOpened(true);
afterOpen && afterOpen();
},
onExit: function onExit() {
setIsOpened(false);
inExit.current = true;
},
onExited: function onExited(e) {
inExit.current = false;
e.parentNode.style.display = ''; // don't set display='none'
afterClose && afterClose();
}
}, React.createElement("div", {
className: cs(prefixCls, className, (_c = {}, _c["".concat(prefixCls, "-rtl")] = rtl, _c)),
style: Object.assign(placement === 'left' || placement === 'right' ? {
width: width
} : {
height: height
}, (_d = {}, _d[placement] = 0, _d), style)
}, React.createElement("div", {
className: "".concat(prefixCls, "-inner")
}, React.createElement(ConfigProvider, __assign({}, context, {
zIndex: popupZIndex || 1050
}), dom))))));
}
var DrawerComponent = React.forwardRef(Drawer);
DrawerComponent.displayName = 'Drawer';
export default DrawerComponent;