ant-design-vue
Version:
An enterprise-class UI design language and Vue-based implementation
439 lines • 18.1 kB
JavaScript
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
var _excluded = ["width", "height", "open", "prefixCls", "placement", "level", "levelMove", "ease", "duration", "getContainer", "onChange", "afterVisibleChange", "showMask", "maskClosable", "maskStyle", "keyboard", "getOpenCount", "scrollLocker", "contentWrapperStyle", "style", "class"];
import { createVNode as _createVNode } from "vue";
import { defineComponent, reactive, onMounted, computed, onUnmounted, nextTick, watch, ref } from 'vue';
import classnames from '../../_util/classNames';
import getScrollBarSize from '../../_util/getScrollBarSize';
import KeyCode from '../../_util/KeyCode';
import omit from '../../_util/omit';
import supportsPassive from '../../_util/supportsPassive';
import { drawerChildProps } from './IDrawerPropTypes';
import { addEventListener, dataToArray, getTouchParentScroll, isNumeric, removeEventListener, transformArguments, transitionEndFun, windowIsUndefined } from './utils';
var currentDrawer = {};
var DrawerChild = defineComponent({
compatConfig: {
MODE: 3
},
inheritAttrs: false,
props: drawerChildProps(),
emits: ['close', 'handleClick', 'change'],
setup: function setup(props, _ref) {
var emit = _ref.emit,
slots = _ref.slots;
var state = reactive({
startPos: {
x: null,
y: null
}
});
var timeout;
var contentWrapper = ref();
var dom = ref();
var maskDom = ref();
var handlerDom = ref();
var contentDom = ref();
var levelDom = [];
var drawerId = "drawer_id_".concat(Number((Date.now() + Math.random()).toString().replace('.', Math.round(Math.random() * 9).toString())).toString(16));
var passive = !windowIsUndefined && supportsPassive ? {
passive: false
} : false;
onMounted(function () {
nextTick(function () {
var open = props.open,
getContainer = props.getContainer,
showMask = props.showMask,
autofocus = props.autofocus;
var container = getContainer === null || getContainer === void 0 ? void 0 : getContainer();
getLevelDom(props);
if (open) {
if (container && container.parentNode === document.body) {
currentDrawer[drawerId] = open;
}
// 默认打开状态时推出 level;
openLevelTransition();
nextTick(function () {
if (autofocus) {
domFocus();
}
});
if (showMask) {
var _props$scrollLocker;
(_props$scrollLocker = props.scrollLocker) === null || _props$scrollLocker === void 0 ? void 0 : _props$scrollLocker.lock();
}
}
});
});
watch(function () {
return props.level;
}, function () {
getLevelDom(props);
}, {
flush: 'post'
});
watch(function () {
return props.open;
}, function () {
var open = props.open,
getContainer = props.getContainer,
scrollLocker = props.scrollLocker,
showMask = props.showMask,
autofocus = props.autofocus;
var container = getContainer === null || getContainer === void 0 ? void 0 : getContainer();
if (container && container.parentNode === document.body) {
currentDrawer[drawerId] = !!open;
}
openLevelTransition();
if (open) {
if (autofocus) {
domFocus();
}
if (showMask) {
scrollLocker === null || scrollLocker === void 0 ? void 0 : scrollLocker.lock();
}
} else {
scrollLocker === null || scrollLocker === void 0 ? void 0 : scrollLocker.unLock();
}
}, {
flush: 'post'
});
onUnmounted(function () {
var _props$scrollLocker2;
var open = props.open;
delete currentDrawer[drawerId];
if (open) {
setLevelTransform(false);
document.body.style.touchAction = '';
}
(_props$scrollLocker2 = props.scrollLocker) === null || _props$scrollLocker2 === void 0 ? void 0 : _props$scrollLocker2.unLock();
});
watch(function () {
return props.placement;
}, function (val) {
if (val) {
// test 的 bug, 有动画过场,删除 dom
contentDom.value = null;
}
});
var domFocus = function domFocus() {
var _dom$value, _dom$value$focus;
(_dom$value = dom.value) === null || _dom$value === void 0 ? void 0 : (_dom$value$focus = _dom$value.focus) === null || _dom$value$focus === void 0 ? void 0 : _dom$value$focus.call(_dom$value);
};
var removeStartHandler = function removeStartHandler(e) {
if (e.touches.length > 1) {
return;
}
state.startPos = {
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
};
var removeMoveHandler = function removeMoveHandler(e) {
if (e.changedTouches.length > 1) {
return;
}
var currentTarget = e.currentTarget;
var differX = e.changedTouches[0].clientX - state.startPos.x;
var differY = e.changedTouches[0].clientY - state.startPos.y;
if ((currentTarget === maskDom.value || currentTarget === handlerDom.value || currentTarget === contentDom.value && getTouchParentScroll(currentTarget, e.target, differX, differY)) && e.cancelable) {
e.preventDefault();
}
};
var transitionEnd = function transitionEnd(e) {
var dom = e.target;
removeEventListener(dom, transitionEndFun, transitionEnd);
dom.style.transition = '';
};
var onClose = function onClose(e) {
emit('close', e);
};
var onKeyDown = function onKeyDown(e) {
if (e.keyCode === KeyCode.ESC) {
e.stopPropagation();
onClose(e);
}
};
var onWrapperTransitionEnd = function onWrapperTransitionEnd(e) {
var open = props.open,
afterVisibleChange = props.afterVisibleChange;
if (e.target === contentWrapper.value && e.propertyName.match(/transform$/)) {
dom.value.style.transition = '';
if (!open && getCurrentDrawerSome()) {
document.body.style.overflowX = '';
if (maskDom.value) {
maskDom.value.style.left = '';
maskDom.value.style.width = '';
}
}
if (afterVisibleChange) {
afterVisibleChange(!!open);
}
}
};
var horizontalBoolAndPlacementName = computed(function () {
var placement = props.placement;
var isHorizontal = placement === 'left' || placement === 'right';
var placementName = "translate".concat(isHorizontal ? 'X' : 'Y');
return {
isHorizontal: isHorizontal,
placementName: placementName
};
});
var openLevelTransition = function openLevelTransition() {
var open = props.open,
width = props.width,
height = props.height;
var _horizontalBoolAndPla = horizontalBoolAndPlacementName.value,
isHorizontal = _horizontalBoolAndPla.isHorizontal,
placementName = _horizontalBoolAndPla.placementName;
var contentValue = contentDom.value ? contentDom.value.getBoundingClientRect()[isHorizontal ? 'width' : 'height'] : 0;
var value = (isHorizontal ? width : height) || contentValue;
setLevelAndScrolling(open, placementName, value);
};
var setLevelTransform = function setLevelTransform(open, placementName, value, right) {
var placement = props.placement,
levelMove = props.levelMove,
duration = props.duration,
ease = props.ease,
showMask = props.showMask;
// router 切换时可能会导至页面失去滚动条,所以需要时时获取。
levelDom.forEach(function (dom) {
dom.style.transition = "transform ".concat(duration, " ").concat(ease);
addEventListener(dom, transitionEndFun, transitionEnd);
var levelValue = open ? value : 0;
if (levelMove) {
var $levelMove = transformArguments(levelMove, {
target: dom,
open: open
});
levelValue = open ? $levelMove[0] : $levelMove[1] || 0;
}
var $value = typeof levelValue === 'number' ? "".concat(levelValue, "px") : levelValue;
var placementPos = placement === 'left' || placement === 'top' ? $value : "-".concat($value);
placementPos = showMask && placement === 'right' && right ? "calc(".concat(placementPos, " + ").concat(right, "px)") : placementPos;
dom.style.transform = levelValue ? "".concat(placementName, "(").concat(placementPos, ")") : '';
});
};
var setLevelAndScrolling = function setLevelAndScrolling(open, placementName, value) {
if (!windowIsUndefined) {
var right = document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) && window.innerWidth > document.body.offsetWidth ? getScrollBarSize(true) : 0;
setLevelTransform(open, placementName, value, right);
toggleScrollingToDrawerAndBody(right);
}
emit('change', open);
};
var toggleScrollingToDrawerAndBody = function toggleScrollingToDrawerAndBody(right) {
var getContainer = props.getContainer,
showMask = props.showMask,
open = props.open;
var container = getContainer === null || getContainer === void 0 ? void 0 : getContainer();
// 处理 body 滚动
if (container && container.parentNode === document.body && showMask) {
var eventArray = ['touchstart'];
var domArray = [document.body, maskDom.value, handlerDom.value, contentDom.value];
if (open && document.body.style.overflow !== 'hidden') {
if (right) {
addScrollingEffect(right);
}
document.body.style.touchAction = 'none';
// 手机禁滚
domArray.forEach(function (item, i) {
if (!item) {
return;
}
addEventListener(item, eventArray[i] || 'touchmove', i ? removeMoveHandler : removeStartHandler, passive);
});
} else if (getCurrentDrawerSome()) {
document.body.style.touchAction = '';
if (right) {
remScrollingEffect(right);
}
// 恢复事件
domArray.forEach(function (item, i) {
if (!item) {
return;
}
removeEventListener(item, eventArray[i] || 'touchmove', i ? removeMoveHandler : removeStartHandler, passive);
});
}
}
};
var addScrollingEffect = function addScrollingEffect(right) {
var placement = props.placement,
duration = props.duration,
ease = props.ease;
var widthTransition = "width ".concat(duration, " ").concat(ease);
var transformTransition = "transform ".concat(duration, " ").concat(ease);
dom.value.style.transition = 'none';
switch (placement) {
case 'right':
dom.value.style.transform = "translateX(-".concat(right, "px)");
break;
case 'top':
case 'bottom':
dom.value.style.width = "calc(100% - ".concat(right, "px)");
dom.value.style.transform = 'translateZ(0)';
break;
default:
break;
}
clearTimeout(timeout);
timeout = setTimeout(function () {
if (dom.value) {
dom.value.style.transition = "".concat(transformTransition, ",").concat(widthTransition);
dom.value.style.width = '';
dom.value.style.transform = '';
}
});
};
var remScrollingEffect = function remScrollingEffect(right) {
var placement = props.placement,
duration = props.duration,
ease = props.ease;
dom.value.style.transition = 'none';
var heightTransition;
var widthTransition = "width ".concat(duration, " ").concat(ease);
var transformTransition = "transform ".concat(duration, " ").concat(ease);
switch (placement) {
case 'left':
{
dom.value.style.width = '100%';
widthTransition = "width 0s ".concat(ease, " ").concat(duration);
break;
}
case 'right':
{
dom.value.style.transform = "translateX(".concat(right, "px)");
dom.value.style.width = '100%';
widthTransition = "width 0s ".concat(ease, " ").concat(duration);
if (maskDom.value) {
maskDom.value.style.left = "-".concat(right, "px");
maskDom.value.style.width = "calc(100% + ".concat(right, "px)");
}
break;
}
case 'top':
case 'bottom':
{
dom.value.style.width = "calc(100% + ".concat(right, "px)");
dom.value.style.height = '100%';
dom.value.style.transform = 'translateZ(0)';
heightTransition = "height 0s ".concat(ease, " ").concat(duration);
break;
}
default:
break;
}
clearTimeout(timeout);
timeout = setTimeout(function () {
if (dom.value) {
dom.value.style.transition = "".concat(transformTransition, ",").concat(heightTransition ? "".concat(heightTransition, ",") : '').concat(widthTransition);
dom.value.style.transform = '';
dom.value.style.width = '';
dom.value.style.height = '';
}
});
};
var getCurrentDrawerSome = function getCurrentDrawerSome() {
return !Object.keys(currentDrawer).some(function (key) {
return currentDrawer[key];
});
};
var getLevelDom = function getLevelDom(_ref2) {
var level = _ref2.level,
getContainer = _ref2.getContainer;
if (windowIsUndefined) {
return;
}
var container = getContainer === null || getContainer === void 0 ? void 0 : getContainer();
var parent = container ? container.parentNode : null;
levelDom = [];
if (level === 'all') {
var children = parent ? Array.prototype.slice.call(parent.children) : [];
children.forEach(function (child) {
if (child.nodeName !== 'SCRIPT' && child.nodeName !== 'STYLE' && child.nodeName !== 'LINK' && child !== container) {
levelDom.push(child);
}
});
} else if (level) {
dataToArray(level).forEach(function (key) {
document.querySelectorAll(key).forEach(function (item) {
levelDom.push(item);
});
});
}
};
var onHandleClick = function onHandleClick(e) {
emit('handleClick', e);
};
var canOpen = ref(false);
watch(dom, function () {
nextTick(function () {
canOpen.value = true;
});
});
return function () {
var _classnames, _slots$default, _slots$handler;
var width = props.width,
height = props.height,
$open = props.open,
prefixCls = props.prefixCls,
placement = props.placement,
level = props.level,
levelMove = props.levelMove,
ease = props.ease,
duration = props.duration,
getContainer = props.getContainer,
onChange = props.onChange,
afterVisibleChange = props.afterVisibleChange,
showMask = props.showMask,
maskClosable = props.maskClosable,
maskStyle = props.maskStyle,
keyboard = props.keyboard,
getOpenCount = props.getOpenCount,
scrollLocker = props.scrollLocker,
contentWrapperStyle = props.contentWrapperStyle,
style = props.style,
className = props.class,
otherProps = _objectWithoutProperties(props, _excluded);
// 首次渲染都将是关闭状态。
var open = $open && canOpen.value;
var wrapperClassName = classnames(prefixCls, (_classnames = {}, _defineProperty(_classnames, "".concat(prefixCls, "-").concat(placement), true), _defineProperty(_classnames, "".concat(prefixCls, "-open"), open), _defineProperty(_classnames, className, !!className), _defineProperty(_classnames, 'no-mask', !showMask), _classnames));
var placementName = horizontalBoolAndPlacementName.value.placementName;
// 百分比与像素动画不同步,第一次打用后全用像素动画。
// const defaultValue = !this.contentDom || !level ? '100%' : `${value}px`;
var placementPos = placement === 'left' || placement === 'top' ? '-100%' : '100%';
var transform = open ? '' : "".concat(placementName, "(").concat(placementPos, ")");
return _createVNode("div", _objectSpread(_objectSpread({}, omit(otherProps, ['switchScrollingEffect', 'autofocus'])), {}, {
"tabindex": -1,
"class": wrapperClassName,
"style": style,
"ref": dom,
"onKeydown": open && keyboard ? onKeyDown : undefined,
"onTransitionend": onWrapperTransitionEnd
}), [showMask && _createVNode("div", {
"class": "".concat(prefixCls, "-mask"),
"onClick": maskClosable ? onClose : undefined,
"style": maskStyle,
"ref": maskDom
}, null), _createVNode("div", {
"class": "".concat(prefixCls, "-content-wrapper"),
"style": _objectSpread({
transform: transform,
msTransform: transform,
width: isNumeric(width) ? "".concat(width, "px") : width,
height: isNumeric(height) ? "".concat(height, "px") : height
}, contentWrapperStyle),
"ref": contentWrapper
}, [_createVNode("div", {
"class": "".concat(prefixCls, "-content"),
"ref": contentDom
}, [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)]), slots.handler ? _createVNode("div", {
"onClick": onHandleClick,
"ref": handlerDom
}, [(_slots$handler = slots.handler) === null || _slots$handler === void 0 ? void 0 : _slots$handler.call(slots)]) : null])]);
};
}
});
export default DrawerChild;