winbox-ui-next
Version:
We Design Vue 2.0: A Vue.js 3 UI Library
414 lines (413 loc) • 11.1 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var vue = require("vue");
var globalConfig = require("../_utils/global-config.js");
var clientOnly = require("../_components/client-only.js");
var iconHover = require("../_components/icon-hover.js");
var index = require("../button/index.js");
var index$1 = require("../icon/icon-close/index.js");
var index$2 = require("../icon/icon-info-circle-fill/index.js");
var index$3 = require("../icon/icon-check-circle-fill/index.js");
var index$4 = require("../icon/icon-exclamation-circle-fill/index.js");
var index$5 = require("../icon/icon-close-circle-fill/index.js");
var index$6 = require("../locale/index.js");
var useOverflow = require("../_hooks/use-overflow.js");
var dom = require("../_utils/dom.js");
var usePopupManager = require("../_hooks/use-popup-manager.js");
var is = require("../_utils/is.js");
var keyboard = require("../_utils/keyboard.js");
var useDraggable = require("./hooks/use-draggable.js");
var useTeleportContainer = require("../_hooks/use-teleport-container.js");
var _sfc_main = vue.defineComponent({
name: "Modal",
components: {
ClientOnly: clientOnly,
WButton: index["default"],
IconHover: iconHover,
IconClose: index$1,
IconInfoCircleFill: index$2,
IconCheckCircleFill: index$3,
IconExclamationCircleFill: index$4,
IconCloseCircleFill: index$5
},
inheritAttrs: false,
props: {
visible: {
type: Boolean,
default: void 0
},
defaultVisible: {
type: Boolean,
default: false
},
width: {
type: [Number, String]
},
top: {
type: [Number, String]
},
mask: {
type: Boolean,
default: true
},
title: {
type: String
},
titleAlign: {
type: String,
default: "center"
},
alignCenter: {
type: Boolean,
default: true
},
unmountOnClose: Boolean,
maskClosable: {
type: Boolean,
default: true
},
hideCancel: {
type: Boolean,
default: false
},
simple: {
type: Boolean,
default: (props) => {
return props.notice;
}
},
closable: {
type: Boolean,
default: true
},
okText: String,
cancelText: String,
okLoading: {
type: Boolean,
default: false
},
okButtonProps: {
type: Object
},
cancelButtonProps: {
type: Object
},
footer: {
type: Boolean,
default: true
},
renderToBody: {
type: Boolean,
default: true
},
popupContainer: {
type: [String, Object],
default: "body"
},
maskStyle: {
type: Object
},
modalClass: {
type: [String, Array]
},
modalStyle: {
type: Object
},
onBeforeOk: {
type: Function
},
onBeforeCancel: {
type: Function
},
escToClose: {
type: Boolean,
default: true
},
draggable: {
type: Boolean,
default: false
},
fullscreen: {
type: Boolean,
default: false
},
maskAnimationName: {
type: String,
default: (props) => {
if (props.fullscreen) {
return "fade-in-standard";
}
return "fade-modal";
}
},
modalAnimationName: {
type: String,
default: (props) => {
if (props.fullscreen) {
return "zoom-in";
}
return "zoom-modal";
}
},
bodyClass: {
type: [String, Array]
},
bodyStyle: {
type: [String, Object, Array]
},
messageType: {
type: String
}
},
emits: [
"update:visible",
"ok",
"cancel",
"open",
"close",
"beforeOpen",
"beforeClose"
],
setup(props, {
emit
}) {
const {
fullscreen,
popupContainer
} = vue.toRefs(props);
const prefixCls = globalConfig.getPrefixCls("modal");
const {
t
} = index$6.useI18n();
const wrapperRef = vue.ref();
const modalRef = vue.ref();
const _visible = vue.ref(props.defaultVisible);
const computedVisible = vue.computed(() => {
var _a;
return (_a = props.visible) != null ? _a : _visible.value;
});
const _okLoading = vue.ref(false);
const mergedOkLoading = vue.computed(() => props.okLoading || _okLoading.value);
const mergedDraggable = vue.computed(() => props.draggable && !props.fullscreen);
const {
teleportContainer,
containerRef
} = useTeleportContainer.useTeleportContainer({
popupContainer,
visible: computedVisible
});
const mounted = vue.ref(computedVisible.value);
const okDisplayText = vue.computed(() => props.okText || t("modal.okText"));
const cancelDisplayText = vue.computed(() => props.cancelText || t("modal.cancelText"));
const {
zIndex,
isLastDialog
} = usePopupManager("dialog", {
visible: computedVisible
});
let globalKeyDownListener = false;
const handleGlobalKeyDown = (ev) => {
if (props.escToClose && ev.key === keyboard.KEYBOARD_KEY.ESC && isLastDialog()) {
handleCancel();
}
};
const addGlobalKeyDownListener = () => {
if (props.escToClose && !globalKeyDownListener) {
globalKeyDownListener = true;
dom.on(document.documentElement, "keydown", handleGlobalKeyDown);
}
};
const removeGlobalKeyDownListener = () => {
globalKeyDownListener = false;
dom.off(document.documentElement, "keydown", handleGlobalKeyDown);
};
let promiseNumber = 0;
const {
position,
handleMoveDown
} = useDraggable.useDraggable({
wrapperRef,
modalRef,
draggable: mergedDraggable
});
const close = () => {
promiseNumber++;
if (_okLoading.value) {
_okLoading.value = false;
}
_visible.value = false;
emit("update:visible", false);
};
const handleOk = async () => {
const currentPromiseNumber = promiseNumber;
const closed = await new Promise(async (resolve) => {
var _a;
if (is.isFunction(props.onBeforeOk)) {
let result = props.onBeforeOk((closed2 = true) => resolve(closed2));
if (is.isPromise(result) || !is.isBoolean(result)) {
_okLoading.value = true;
}
if (is.isPromise(result)) {
try {
result = (_a = await result) != null ? _a : true;
} catch (error) {
result = false;
}
}
if (is.isBoolean(result)) {
resolve(result);
}
} else {
resolve(true);
}
});
if (currentPromiseNumber === promiseNumber) {
if (closed) {
emit("ok");
close();
} else if (_okLoading.value) {
_okLoading.value = false;
}
}
};
const handleCancel = () => {
var _a;
let result = true;
if (is.isFunction(props.onBeforeCancel)) {
result = (_a = props.onBeforeCancel()) != null ? _a : false;
}
if (result) {
emit("cancel");
close();
}
};
const currentIsMask = vue.ref(false);
const handleMaskMouseDown = (ev) => {
if (ev.target === wrapperRef.value) {
currentIsMask.value = true;
}
};
const handleMaskClick = () => {
if (props.mask && props.maskClosable && currentIsMask.value) {
handleCancel();
}
};
const handleOpen = () => {
if (computedVisible.value) {
if (!dom.contains(wrapperRef.value, document.activeElement) && document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
emit("open");
}
};
const handleClose = () => {
if (!computedVisible.value) {
if (mergedDraggable.value) {
position.value = void 0;
}
mounted.value = false;
resetOverflow();
emit("close");
}
};
const {
setOverflowHidden,
resetOverflow
} = useOverflow.useOverflow(containerRef);
vue.onMounted(() => {
containerRef.value = dom.getElement(props.popupContainer);
if (computedVisible.value) {
setOverflowHidden();
if (props.escToClose) {
addGlobalKeyDownListener();
}
}
});
vue.onBeforeUnmount(() => {
resetOverflow();
removeGlobalKeyDownListener();
});
vue.watch(computedVisible, (value) => {
if (_visible.value !== value) {
_visible.value = value;
}
if (value) {
emit("beforeOpen");
mounted.value = true;
currentIsMask.value = false;
setOverflowHidden();
addGlobalKeyDownListener();
} else {
emit("beforeClose");
removeGlobalKeyDownListener();
}
});
vue.watch(fullscreen, () => {
if (position.value) {
position.value = void 0;
}
});
const wrapperCls = vue.computed(() => [`${prefixCls}-wrapper`, {
[`${prefixCls}-wrapper-align-center`]: props.alignCenter && !props.fullscreen,
[`${prefixCls}-wrapper-moved`]: Boolean(position.value)
}]);
const modalCls = vue.computed(() => [`${prefixCls}`, props.modalClass, {
[`${prefixCls}-simple`]: props.simple,
[`${prefixCls}-draggable`]: mergedDraggable.value,
[`${prefixCls}-fullscreen`]: props.fullscreen
}]);
const mergedModalStyle = vue.computed(() => {
var _a;
const style = __spreadValues({}, (_a = props.modalStyle) != null ? _a : {});
if (props.width) {
style.width = is.isNumber(props.width) ? `${props.width}px` : props.width;
}
if (!props.alignCenter && props.top) {
style.top = is.isNumber(props.top) ? `${props.top}px` : props.top;
}
if (position.value) {
style.transform = `translate(${position.value[0]}px, ${position.value[1]}px)`;
}
return style;
});
return {
prefixCls,
mounted,
computedVisible,
containerRef,
wrapperRef,
mergedModalStyle,
okDisplayText,
cancelDisplayText,
zIndex,
handleOk,
handleCancel,
handleMaskClick,
handleMaskMouseDown,
handleOpen,
handleClose,
mergedOkLoading,
modalRef,
wrapperCls,
modalCls,
teleportContainer,
handleMoveDown
};
}
});
module.exports = _sfc_main;