12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- import { Teleport, h, onUnmounted, ref } from 'vue'
- import { NOOP } from '@vue/shared'
- import { isClient } from '@vueuse/core'
- import { createGlobalNode, removeGlobalNode } from '@element-plus/utils'
- import type { Ref, VNode } from 'vue'
- export const useTeleport = (
- contentRenderer: () => VNode,
- appendToBody: Ref<boolean>
- ) => {
- const isTeleportVisible = ref(false)
- if (!isClient) {
- return {
- isTeleportVisible,
- showTeleport: NOOP,
- hideTeleport: NOOP,
- renderTeleport: NOOP,
- }
- }
- let $el: HTMLElement | null = null
- const showTeleport = () => {
- isTeleportVisible.value = true
- // this allows the delayed showing strategy since the the content itself could be enterable
- // e.g. el-popper
- if ($el !== null) return
- $el = createGlobalNode()
- }
- const hideTeleport = () => {
- isTeleportVisible.value = false
- if ($el !== null) {
- removeGlobalNode($el)
- $el = null
- }
- }
- const renderTeleport = () => {
- return appendToBody.value !== true
- ? contentRenderer()
- : isTeleportVisible.value
- ? [h(Teleport, { to: $el }, contentRenderer())]
- : undefined
- }
- onUnmounted(hideTeleport)
- return {
- isTeleportVisible,
- showTeleport,
- hideTeleport,
- renderTeleport,
- }
- }
|