11<script setup lang="ts">
2- import type { HTMLAttributes } from ' vue '
2+ import type { DrawerEmits , DrawerProps } from ' . '
33import { cn } from ' @/utils'
44import {
55 Sheet ,
@@ -15,33 +15,9 @@ defineOptions({
1515})
1616
1717const props = withDefaults (
18- defineProps <{
19- modelValue? : boolean
20- side? : ' top' | ' bottom' | ' left' | ' right'
21- title: string
22- description? : string
23- loading? : boolean
24- closable? : boolean
25- centered? : boolean
26- bordered? : boolean
27- overlay? : boolean
28- overlayBlur? : boolean
29- showConfirmButton? : boolean
30- showCancelButton? : boolean
31- confirmButtonText? : string
32- cancelButtonText? : string
33- confirmButtonDisabled? : boolean
34- confirmButtonLoading? : boolean
35- header? : boolean
36- footer? : boolean
37- closeOnClickOverlay? : boolean
38- closeOnPressEscape? : boolean
39- destroyOnClose? : boolean
40- contentClass? : HTMLAttributes [' class' ]
41- headerClass? : HTMLAttributes [' class' ]
42- footerClass? : HTMLAttributes [' class' ]
43- }>(),
18+ defineProps <DrawerProps >(),
4419 {
20+ id: useId (),
4521 modelValue: false ,
4622 side: ' right' ,
4723 loading: false ,
@@ -64,18 +40,7 @@ const props = withDefaults(
6440 },
6541)
6642
67- const emits = defineEmits <{
68- ' update:modelValue' : [value : boolean ]
69- ' open' : []
70- ' opened' : []
71- ' close' : []
72- ' closed' : []
73- ' confirm' : []
74- ' cancel' : []
75- }>()
76-
77- const id = useId ()
78- provide (' DrawerId' , id )
43+ const emits = defineEmits <DrawerEmits >()
7944
8045const isOpen = ref (props .modelValue )
8146
@@ -86,9 +51,16 @@ watch(() => props.modelValue, (newValue) => {
8651const hasOpened = ref (false )
8752const isClosed = ref (true )
8853
89- watch (() => isOpen .value , (value ) => {
54+ watch (isOpen , (val ) => {
55+ emits (' update:modelValue' , val )
56+ if (val ) {
57+ emits (' open' )
58+ }
59+ else {
60+ emits (' close' )
61+ }
9062 isClosed .value = false
91- if (value && ! hasOpened .value ) {
63+ if (val && ! hasOpened .value ) {
9264 hasOpened .value = true
9365 }
9466}, {
@@ -97,25 +69,62 @@ watch(() => isOpen.value, (value) => {
9769
9870const forceMount = computed (() => ! props .destroyOnClose && hasOpened .value )
9971
100- function updateOpen(value : boolean ) {
101- isOpen .value = value
102- emits (' update:modelValue' , value )
72+ async function updateOpen(value : boolean ) {
10373 if (value ) {
74+ isOpen .value = value
10475 emits (' open' )
10576 }
10677 else {
107- emits (' close' )
78+ if (props .beforeClose ) {
79+ await props .beforeClose (
80+ ' close' ,
81+ () => {
82+ isOpen .value = value
83+ emits (' close' )
84+ },
85+ )
86+ }
87+ else {
88+ isOpen .value = value
89+ emits (' close' )
90+ }
10891 }
10992}
11093
111- function onConfirm() {
112- updateOpen (false )
113- emits (' confirm' )
94+ const isConfirmButtonLoading = ref (false )
95+
96+ async function onConfirm() {
97+ if (props .beforeClose ) {
98+ isConfirmButtonLoading .value = true
99+ await props .beforeClose (
100+ ' confirm' ,
101+ () => {
102+ isOpen .value = false
103+ emits (' confirm' )
104+ },
105+ )
106+ isConfirmButtonLoading .value = false
107+ }
108+ else {
109+ isOpen .value = false
110+ emits (' confirm' )
111+ }
114112}
115113
116- function onCancel() {
117- updateOpen (false )
118- emits (' cancel' )
114+ async function onCancel() {
115+ if (props .beforeClose ) {
116+ await props .beforeClose (
117+ ' cancel' ,
118+ () => {
119+ isOpen .value = false
120+ emits (' cancel' )
121+ },
122+ )
123+ }
124+ else {
125+ isOpen .value = false
126+ emits (' cancel' )
127+ }
119128}
120129
121130function handleFocusOutside(e : Event ) {
@@ -124,7 +133,7 @@ function handleFocusOutside(e: Event) {
124133}
125134
126135function handleClickOutside(e : Event ) {
127- if (! props .closeOnClickOverlay || (e .target as HTMLElement ).dataset .drawerId !== id ) {
136+ if (! props .closeOnClickOverlay || (e .target as HTMLElement ).dataset .drawerId !== props . id ) {
128137 e .preventDefault ()
129138 e .stopPropagation ()
130139 }
@@ -151,8 +160,9 @@ function handleAnimationEnd() {
151160<template >
152161 <Sheet :modal =" false" :open =" isOpen" @update:open =" updateOpen" >
153162 <SheetContent
154- :closable =" props.closable "
163+ :drawer-id =" props.id "
155164 :open =" isOpen"
165+ :closable =" props.closable"
156166 :overlay =" props.overlay"
157167 :overlay-blur =" props.overlayBlur"
158168 :class =" cn('w-full flex flex-col gap-0 p-0', props.contentClass, {
@@ -187,10 +197,10 @@ function handleAnimationEnd() {
187197 <div class =" p-4" >
188198 <slot />
189199 </div >
200+ <div v-show =" props.loading" class =" absolute inset-0 z-1000 size-full flex-center bg-popover/75" >
201+ <FaIcon name =" i-line-md:loading-twotone-loop" class =" size-10" />
202+ </div >
190203 </FaScrollArea >
191- <div v-show =" props.loading" class =" absolute inset-0 z-1000 size-full flex-center bg-popover/75" >
192- <FaIcon name =" i-line-md:loading-twotone-loop" class =" size-10" />
193- </div >
194204 </div >
195205 <SheetFooter
196206 v-if =" footer" :class =" cn('p-2 gap-y-2', props.footerClass, {
0 commit comments