UNPKG

kui-vue

Version:

A lightweight desktop UI component library suitable for Vue.js 2.

226 lines (212 loc) 6.33 kB
import { Button } from "../button"; import Icon from "../icon"; import transfer from "../directives/transfer"; import { Close } from "kui-icons"; import { defineComponent, inject, nextTick, ref, /*Transition,*/ watch, onMounted, onBeforeUnmount, computed, } from "vue"; import zhCN from "../locale/zh-CN"; import { withInstall } from "../utils/vue"; const Drawer = defineComponent({ name: "Drawer", directives: { transfer }, props: { // show: Boolean, //for 3 value: Boolean, title: { default: "Title", type: String }, width: { default: 520, type: [Number, String] }, height: { default: 256, type: [Number, String] }, okText: String, cancelText: String, placement: { type: String, default: "right" }, closable: { type: Boolean, default: true }, footer: { type: Boolean, default: true }, maskClosable: { type: Boolean, default: true }, target: { type: Function, default: () => document.body }, mask: { type: Boolean, default: true }, loading: { type: Boolean, default: false }, escKey: { type: Boolean, default: true }, }, setup(ps, { slots, emit }) { const injectedLocale = inject("locale", zhCN); const locale = computed(() => { return injectedLocale instanceof Object && "value" in injectedLocale ? injectedLocale.value : injectedLocale; }); const rendered = ref(ps.value); // for 2 // const rendered = ref(ps.show); // for 3 const visible = ref(ps.value); // const visible = ref(ps.show); // for 3 const opened = ref(ps.show); watch( // () => ps.show, // for 3 () => ps.value, (nv, ov) => { if (nv) { toggle(nv); } } ); onMounted(() => { if (!window.__kui_body_style) { window.__kui_body_style = { overflowY: document.body.style.overflowY, paddingRight: document.body.style.paddingRight, }; } ps.escKey && document.addEventListener("keydown", escToClose); }); onBeforeUnmount(() => { ps.escKey && document.removeEventListener("keydown", escToClose); }); const lockScroll = (lock) => { if (lock) { const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; const hasScrollbar = scrollbarWidth > 0; if (hasScrollbar) { document.body.style.overflowY = "hidden"; document.body.style.paddingRight = `${scrollbarWidth}px`; // 防止布局跳动 } } else { let { overflowY, paddingRight } = window.__kui_body_style; document.body.style.overflowY = overflowY || ""; document.body.style.paddingRight = paddingRight || ""; } }; const toggle = (v) => { if (v && !rendered.value) { rendered.value = true; nextTick(() => { visible.value = true; openHandle(); }); } else { visible.value = v; openHandle(); } }; const escToClose = (event) => { if (event.key === "Escape") { close(); } }; const maskToClose = () => { if (ps.maskClosable) { close(); } }; const cancel = () => { emit("cancel"); visible.value = false; openHandle(); }; const openHandle = () => { if (visible.value) { opened.value = true; } else { setTimeout(() => { opened.value = false; }, 300); } lockScroll(visible.value); emit("update:show", visible.value); // for 3 emit("input", visible.value); }; const close = () => { visible.value = false; emit("close"); openHandle(); }; const ok = () => { emit("ok"); }; return () => { const { title, cancelText, okText, placement, width, height, closable, loading, } = ps; const hasFooter = ps.footer || slots.footer; const cancelBtn = ( <Button onClick={cancel}> {cancelText || locale?.value.k.common.cancel} </Button> ); const okBtn = ( <Button type="primary" onClick={ok} loading={loading}> {okText || locale?.value.k.common.ok} </Button> ); const footNode = hasFooter ? ( <div class="k-drawer-footer"> {slots.footer ? slots.footer() : [cancelBtn, okBtn]} </div> ) : null; const closeNode = closable ? ( <span class="k-drawer-close" onClick={close}> <Icon type={Close} /> </span> ) : null; const transitionName = `k-drawer-${placement}`; const target = ps.target(); const isBody = target == document.body; const classes = [ "k-drawer", `k-drawer-${placement}`, { "k-drawer-opened": opened.value }, { "k-drawer-has-footer": hasFooter }, { "k-drawer-nobody": !isBody }, { "k-drawer-nomask": !ps.mask }, ]; let styles = {}; if (placement == "left" || placement == "right") styles.width = typeof width === "number" ? `${width}px` : width; if (placement == "top" || placement == "bottom") styles.height = typeof height === "number" ? `${height}px` : height; let maskNode = null; if (ps.mask) { maskNode = ( <transition name="k-drawer-fade"> <div class={["k-drawer-mask", { "k-drawer-mask-nobody": !isBody }]} v-show={visible.value} onClick={maskToClose} ></div> </transition> ); } return rendered.value ? ( <div class={classes} v-transfer={target}> {maskNode} <transition name={transitionName}> <div class="k-drawer-box" v-show={visible.value} style={styles}> <div class="k-drawer-content"> <div class="k-drawer-header"> {closeNode} <div class="k-drawer-header-inner">{title}</div> </div> <div class="k-drawer-body">{slots.default?.()}</div> {footNode} </div> </div> </transition> </div> ) : null; }; }, }); export default withInstall(Drawer);