Browse Source

feat(gui-v2): add `useDialog` composable

pull/3211/head
braks 2 years ago
parent
commit
a0bcf49b24
  1. 1
      packages/nc-gui-v2/composables/index.ts
  2. 67
      packages/nc-gui-v2/composables/useDialog/index.ts

1
packages/nc-gui-v2/composables/index.ts

@ -1,4 +1,5 @@
export * from './useApi'
export * from './useDialog'
export * from './useGlobal'
export * from './useInjectionState'
export * from './useSidebar'

67
packages/nc-gui-v2/composables/useDialog/index.ts

@ -0,0 +1,67 @@
import { render } from '@vue/runtime-dom'
import type { ComponentPublicInstance } from '@vue/runtime-core'
import { createEventHook, h, toReactive, tryOnScopeDispose, useNuxtApp, watch } from '#imports'
/**
* Programmatically create a component and attach it to the body (or a specific mount target), like a dialog or modal.
*/
export function useDialog(
component: any,
props: NonNullable<Parameters<typeof h>[1]> = {},
mountTarget?: Element | ComponentPublicInstance,
) {
const closeHook = createEventHook<void>()
const mountedHook = createEventHook<void>()
const isMounted = $ref(false)
const domNode = document.createElement('div')
/** if specified, append vnode to mount target instead of document.body */
if (mountTarget) {
if ('$el' in mountTarget) {
mountTarget.$el.appendChild(domNode)
} else {
mountTarget.appendChild(domNode)
}
} else {
document.body.appendChild(domNode)
}
/** When props change, we want to re-render the element with the new prop values */
watch(
toReactive(props),
(reactiveProps) => {
const vNode = h(component, reactiveProps)
vNode.appContext = useNuxtApp().vueApp._context
render(vNode, domNode)
if (!isMounted) mountedHook.trigger()
},
{ deep: true, immediate: true },
)
/** When calling scope is disposed, destroy component */
tryOnScopeDispose(close)
/** destroy component, can be debounced */
function close(debounce = 0) {
setTimeout(() => {
render(null, domNode)
setTimeout(() => {
document.body.removeChild(domNode)
}, 100)
closeHook.trigger()
}, debounce)
}
return {
close,
onClose: closeHook.on,
onMounted: mountedHook.on,
}
}
Loading…
Cancel
Save