UNPKG

@extclp/vexip-ui

Version:

A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good

1 lines 11.9 kB
{"version":3,"file":"masker.vue2.mjs","sources":["../../../components/masker/masker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { Portal } from '@/components/portal'\nimport { ResizeObserver } from '@/components/resize-observer'\n\nimport { computed, nextTick, ref, watch } from 'vue'\n\nimport { emitEvent, useNameHelper, useProps, useZIndex } from '@vexip-ui/config'\nimport { getLast, isPromise, queryTabables } from '@vexip-ui/utils'\nimport { maskerProps } from './props'\n\ndefineOptions({ name: 'Masker' })\n\nconst nh = useNameHelper('masker')\nconst _props = defineProps(maskerProps)\nconst props = useProps('masker', _props, {\n active: {\n default: false,\n static: true\n },\n closable: false,\n inner: false,\n maskTransition: () => nh.ns('fade'),\n transitionName: () => nh.ns('fade'),\n disabled: false,\n onBeforeClose: {\n default: null,\n isFunc: true\n },\n transfer: false,\n autoRemove: false,\n permeable: false,\n disableEsc: false\n})\n\nconst emit = defineEmits(['update:active'])\n\nconst slots = defineSlots<{\n mask?: () => any,\n default?: (params: { show: boolean }) => any\n}>()\n\nconst getIndex = useZIndex()\n\nconst currentActive = ref(props.active)\n// If initial active, we should set a valid index as initial value\nconst zIndex = ref(props.active ? getIndex() : 0)\nconst wrapperShow = ref(props.active)\n\nconst wrapper = ref<HTMLElement>()\nconst topTrap = ref<HTMLElement>()\nconst bottomTrap = ref<HTMLElement>()\n\nlet maskShow = false\nlet contentShow = false\nlet stable = false\nlet prevFocusedEl: HTMLElement | null = null\n\nconst transferTo = computed(() => {\n return props.inner\n ? ''\n : typeof props.transfer === 'boolean'\n ? props.transfer\n ? 'body'\n : ''\n : props.transfer\n})\nconst className = computed(() => {\n return [\n nh.b(),\n nh.bs('vars'),\n {\n [nh.bm('inherit')]: transferTo.value !== 'body' && props.inherit,\n [nh.bm('inner')]: props.inner,\n [nh.bm('disabled')]: props.disabled\n }\n ]\n})\n\nwatch(\n () => props.active,\n value => {\n currentActive.value = value\n\n if (value) {\n wrapperShow.value = value\n }\n }\n)\nwatch(currentActive, value => {\n if (!value) {\n stable = false\n\n if (prevFocusedEl) {\n prevFocusedEl.focus()\n prevFocusedEl = null\n }\n } else {\n prevFocusedEl = document.activeElement as HTMLElement\n zIndex.value = getIndex()\n }\n\n if ((!props.maskTransition || props.disabled) && !props.transitionName) {\n value ? afterOpen() : afterClose()\n }\n})\nwatch(\n [() => props.permeable, wrapper],\n () => {\n if (wrapper.value) {\n wrapper.value.removeEventListener('wheel', disableWheel)\n\n if (!props.permeable) {\n wrapper.value.addEventListener('wheel', disableWheel)\n }\n }\n },\n { immediate: true, flush: 'post' }\n)\n\ndefineExpose({\n currentActive,\n zIndex,\n wrapperShow,\n wrapper,\n topTrap,\n bottomTrap\n})\n\nfunction disableWheel(event: WheelEvent) {\n event.preventDefault()\n event.stopPropagation()\n}\n\nfunction toggleActive(active: boolean) {\n if (currentActive.value === active) return\n\n currentActive.value = active\n\n emit('update:active', active)\n emitEvent(props.onToggle, active)\n}\n\nasync function handleClose() {\n if (!props.closable) return\n\n let result: unknown = true\n\n if (typeof props.onBeforeClose === 'function') {\n result = props.onBeforeClose()\n\n if (isPromise(result)) {\n result = await result\n }\n }\n\n if (result !== false) {\n nextTick(() => {\n toggleActive(false)\n emitEvent(props.onClose)\n })\n }\n}\n\nfunction afterOpen() {\n if (!currentActive.value) return\n\n const activeEl = document && document.activeElement\n\n if (!activeEl || !wrapper.value || !wrapper.value.contains(activeEl)) {\n topTrap.value?.focus()\n }\n\n nextTick(() => {\n stable = true\n emitEvent(props.onShow)\n })\n}\n\nfunction afterClose() {\n if (currentActive.value) return\n\n nextTick(() => {\n wrapperShow.value = false\n emitEvent(props.onHide)\n })\n}\n\nfunction afterMaskOpen() {\n if (!currentActive.value) return\n\n maskShow = true\n ;(!props.transitionName || !slots.default || contentShow) && afterOpen()\n}\n\nfunction afterMaskClose() {\n if (currentActive.value) return\n\n maskShow = false\n ;(!props.transitionName || !slots.default || !contentShow) && afterClose()\n}\n\nfunction afterContentOpen() {\n if (!currentActive.value) return\n\n contentShow = true\n ;(!props.maskTransition || props.disabled || maskShow) && afterOpen()\n}\n\nfunction afterContentClose() {\n if (currentActive.value) return\n\n contentShow = false\n ;(!props.maskTransition || props.disabled || !maskShow) && afterClose()\n}\n\nfunction handleMaskClick(event: MouseEvent) {\n emitEvent(props.onMaskClick, event)\n handleClose()\n}\n\nfunction handleFocusIn(event: FocusEvent) {\n const target = event.target as HTMLElement\n\n if (!stable || !wrapper.value || !target || !topTrap.value || !bottomTrap.value) {\n return\n }\n\n const tabables = queryTabables(wrapper.value)\n\n if (!tabables.length) {\n return\n }\n\n if (topTrap.value === target) {\n getLast(tabables)!.focus()\n } else if (bottomTrap.value === target) {\n tabables[0].focus()\n }\n}\n\nfunction handleResize(entry: ResizeObserverEntry) {\n emitEvent(props.onResize, entry)\n}\n\nfunction handleEscape(event: KeyboardEvent) {\n if (!props.disableEsc) {\n event.preventDefault()\n handleClose()\n }\n}\n</script>\n\n<template>\n <Portal v-if=\"!props.autoRemove || wrapperShow\" :to=\"transferTo\">\n <div\n v-bind=\"$attrs\"\n ref=\"wrapper\"\n :class=\"[className, $attrs.class]\"\n tabindex=\"-1\"\n :style=\"{\n zIndex,\n ...($attrs.style || {}),\n pointerEvents: wrapperShow ? undefined : 'none',\n visibility: wrapperShow ? undefined : 'hidden'\n }\"\n @focusin=\"handleFocusIn\"\n @keydown.escape=\"handleEscape\"\n >\n <ResizeObserver @resize=\"handleResize\">\n <Transition\n v-if=\"!props.disabled\"\n appear\n :name=\"props.maskTransition\"\n @after-enter=\"afterMaskOpen\"\n @after-leave=\"afterMaskClose\"\n >\n <div v-show=\"currentActive\" :class=\"nh.be('mask')\" @click=\"handleMaskClick\">\n <slot name=\"mask\">\n <div :class=\"nh.be('mask-inner')\"></div>\n </slot>\n </div>\n </Transition>\n <div\n v-else\n :class=\"nh.be('placeholder')\"\n role=\"none\"\n aria-hidden\n ></div>\n </ResizeObserver>\n <div\n ref=\"topTrap\"\n tabindex=\"0\"\n role=\"none\"\n style=\"width: 0; height: 0; overflow: hidden; outline: none\"\n ></div>\n <div :class=\"nh.be('content')\" @wheel.stop.prevent>\n <Transition\n v-if=\"props.transitionName\"\n appear\n :name=\"props.transitionName\"\n @after-enter=\"afterContentOpen\"\n @after-leave=\"afterContentClose\"\n >\n <slot :show=\"currentActive\"></slot>\n </Transition>\n <slot v-else :show=\"currentActive\"></slot>\n </div>\n <div\n ref=\"bottomTrap\"\n tabindex=\"0\"\n role=\"none\"\n style=\"width: 0; height: 0; overflow: hidden; outline: none\"\n ></div>\n </div>\n </Portal>\n</template>\n"],"names":["nh","useNameHelper","props","useProps","__props","emit","__emit","slots","_useSlots","getIndex","useZIndex","currentActive","ref","zIndex","wrapperShow","wrapper","topTrap","bottomTrap","maskShow","contentShow","stable","prevFocusedEl","transferTo","computed","className","watch","value","afterOpen","afterClose","disableWheel","__expose","event","toggleActive","active","emitEvent","handleClose","result","isPromise","nextTick","activeEl","_a","afterMaskOpen","afterMaskClose","afterContentOpen","afterContentClose","handleMaskClick","handleFocusIn","target","tabables","queryTabables","getLast","handleResize","entry","handleEscape"],"mappings":"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"}