Skip to content

Instantly share code, notes, and snippets.

@CasperEngl
Created September 28, 2023 09:57
Show Gist options
  • Select an option

  • Save CasperEngl/7fdd6c24f690a14b636757d434d87280 to your computer and use it in GitHub Desktop.

Select an option

Save CasperEngl/7fdd6c24f690a14b636757d434d87280 to your computer and use it in GitHub Desktop.

Revisions

  1. CasperEngl created this gist Sep 28, 2023.
    70 changes: 70 additions & 0 deletions use-dialog.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,70 @@
    import type { MaybeRef } from 'vue'
    import { ref, watchEffect } from 'vue'

    type UseDialogOptions = {
    isOpen: MaybeRef<boolean>
    persistent: MaybeRef<boolean>
    onClosing?: () => void
    onClose?: () => void
    animationOptions: MaybeRef<KeyframeAnimationOptions>
    dialogKeyframes: MaybeRef<Keyframe[]>
    contentKeyframes: MaybeRef<Keyframe[]>
    }

    export function useDialog(options: UseDialogOptions) {
    const dialogRef = ref<HTMLDialogElement | null>(null)
    const contentRef = ref<HTMLDivElement | null>(null)

    const persistent = ref(options.persistent)
    const isOpen = ref(options.isOpen)
    const animationOptions = ref(options.animationOptions)
    const dialogKeyframes = ref(options.dialogKeyframes)

    function handleClose(event: Event) {
    event.preventDefault()

    if (persistent.value === true) return

    if (options.onClosing) {
    options.onClosing()
    }

    const dialogFadeOut = dialogRef.value?.animate(dialogKeyframes.value, animationOptions.value)

    dialogFadeOut?.addEventListener('finish', () => {
    dialogRef.value?.close()

    if (options.onClose) {
    options.onClose()
    }
    })
    }

    watchEffect((onCleanup) => {
    if (isOpen.value) {
    dialogRef.value?.addEventListener('close', handleClose)
    dialogRef.value?.showModal()

    dialogRef.value?.animate(dialogKeyframes.value, animationOptions.value)
    contentRef.value?.animate(dialogKeyframes.value, animationOptions.value)
    } else {
    handleClose(new Event('close'))

    dialogRef.value?.removeEventListener('close', handleClose)
    }

    onCleanup(() => {
    dialogRef.value?.removeEventListener('close', handleClose)
    })
    })

    return [
    {
    dialog: dialogRef,
    content: contentRef,
    },
    {
    handleClose,
    },
    ] as const
    }