@opensig/opendesign
Version:
140 lines (139 loc) • 4.2 kB
JavaScript
import { render, h, nextTick } from "vue";
import { isString } from "../_utils/is.mjs";
import _sfc_main from "./OMessageList.vue.mjs";
import { resolveHtmlElement } from "../_utils/vue-utils.mjs";
const DEFAULT_OPTIONS = {
status: "info",
position: "top",
duration: 3e3
};
const instanceMap = /* @__PURE__ */ new Map();
const targetOffset = 8;
const normalizeOptions = (params) => {
const options = !params || isString(params) ? { content: params } : params;
const normalized = {
...DEFAULT_OPTIONS,
...options
};
return normalized;
};
const getMessageStyle = (targetEl, position = "top", align = "center") => {
if (!targetEl) {
return;
}
const rect = targetEl.getBoundingClientRect();
let pos = "bottom";
let top = window.innerHeight - rect.top + targetOffset;
let left = rect.left;
let transform = "translateX(-50%)";
if (position === "bottom") {
pos = "top";
top = rect.top + rect.height + targetOffset;
}
if (align === "right") {
left = rect.left + rect.width;
transform = "translateX(-100%)";
} else if (align === "left") {
left = rect.left;
transform = "translateX(0%)";
} else {
left = rect.left + rect.width / 2;
transform = "translateX(-50%)";
}
return {
position: pos,
"--message-list-offset": `${top}px`,
[`--message-list-${pos}-offset`]: `${top}px`,
left: `${left}px`,
transform
};
};
const createMessageListVnode = ({
position,
wrap,
style,
targetEl
}) => {
return h(_sfc_main, {
position: (style == null ? void 0 : style.position) ?? position,
onDestroy: async () => {
if (wrap) {
render(null, wrap);
await nextTick();
document.body.removeChild(wrap);
}
instanceMap.delete(targetEl ?? position);
},
style
});
};
const showMessage = (target, closeHandlers, params) => {
const options = normalizeOptions(params);
const { position, targetAlign } = options;
let id = -1;
let instance;
let isClosed = false;
resolveHtmlElement(target).then((targetEl) => {
var _a, _b;
if (isClosed) {
return;
}
const msgStyle = getMessageStyle(targetEl, position, targetAlign);
instance = instanceMap.get(targetEl ?? position);
if (!instance) {
const wrap = document.createElement("div");
const vnode = createMessageListVnode({
position,
wrap,
style: msgStyle,
targetEl
});
render(vnode, wrap);
const vm = vnode.component;
id = (_a = vm.exposed) == null ? void 0 : _a.add(options);
instance = vm;
instanceMap.set(targetEl ?? position, instance);
document.body.appendChild(wrap);
} else {
id = (_b = instance.exposed) == null ? void 0 : _b.add(options);
}
});
const closeHandler = () => {
var _a;
isClosed = true;
(_a = instance == null ? void 0 : instance.exposed) == null ? void 0 : _a.close(id);
closeHandlers.delete(closeHandler);
};
closeHandlers.add(closeHandler);
return closeHandler;
};
const showMessageWithStatus = (status, target, closeHandlers, params) => {
return showMessage(target, closeHandlers, { ...normalizeOptions(params), status });
};
const closeAll = () => {
var _a;
for (const ins of instanceMap.values()) {
(_a = ins == null ? void 0 : ins.exposed) == null ? void 0 : _a.removeAll();
}
};
const close = (closeHandlers) => {
closeHandlers.forEach((handler) => handler());
};
function useMessage(target) {
const closeHandlers = /* @__PURE__ */ new Set();
return {
show: showMessage.bind(null, target, closeHandlers),
info: showMessageWithStatus.bind(null, "info", target, closeHandlers),
success: showMessageWithStatus.bind(null, "success", target, closeHandlers),
warning: showMessageWithStatus.bind(null, "warning", target, closeHandlers),
danger: showMessageWithStatus.bind(null, "danger", target, closeHandlers),
loading: showMessageWithStatus.bind(null, "loading", target, closeHandlers),
/** 关闭本 useMessage 实例渲染的所有消息 */
close: close.bind(null, closeHandlers),
/** 关闭所有实例渲染的所有消息 */
closeAll
};
}
export {
useMessage
};