11<template >
2- <div
3- v-if =" $slots.trigger"
4- @click =" modal?.show()" class =" inline-flex items-center cursor-pointer"
2+ <Modal
3+ ref =" modalRef"
4+ v-bind =" $attrs"
5+ :closeByClickOutside =" clickToCloseOutside || closeByClickOutside"
6+ :closeByEsc =" closeByEsc || closable"
7+ :beforeCloseFunction =" beforeCloseFunction"
8+ :beforeOpenFunction =" beforeOpenFunction"
9+ :askForCloseConfirmation =" askForCloseConfirmation"
10+ :closeConfirmationText =" closeConfirmationText"
11+ :removeFromDomOnClose =" removeFromDomOnClose"
512 >
6- <slot name =" trigger" ></slot >
7- </div >
8- <Teleport to =" body" >
9- <div ref =" modalEl" tabindex =" -1" aria-hidden =" true" class =" [scrollbar-gutter:stable] hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-full max-h-full" >
10- <div v-bind =" $attrs" class =" relative p-4 max-w-2xl max-h-full" :class =" ($attrs.class as string)?.includes('w-') ? '' : 'w-full'" >
11- <!-- Modal content -->
12- <div class =" relative bg-lightDialogBackgorund rounded-lg shadow-sm dark:bg-darkDialogBackgorund" >
13- <!-- Modal header -->
14- <div
15- v-if =" header"
16- class =" flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-darkDialogBreakLine border-lightDialogBreakLine"
17- >
18- <h3 class =" text-xl font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText" >
19- {{ header }}
20- </h3 >
21- <button
22- v-if =" headerCloseButton"
23- type =" button"
24- class =" text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
25- @click =" tryToHideModal"
26- >
27- <svg class =" w-3 h-3" aria-hidden =" true" xmlns =" http://www.w3.org/2000/svg" fill =" none" viewBox =" 0 0 14 14" >
28- <path stroke =" currentColor" stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" d =" m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
29- </svg >
30- <span class =" sr-only" >Close modal</span >
31- </button >
32- </div >
33- <!-- Modal body -->
34- <div class =" p-4 md:p-5 space-y-4 text-lightDialogBodyText dark:text-darkDialogBodyText" >
35- <slot ></slot >
36- </div >
37- <!-- Modal footer -->
38- <div
39- v-if =" buttons.length"
40- class =" flex items-center p-4 md:p-5 border-t border-lightDialogBreakLine rounded-b dark:border-darkDialogBreakLine"
41- >
42- <Button
43- v-for =" (button, buttonIndex) in buttons"
44- :key =" buttonIndex"
45- v-bind =" button.options"
46- :class =" { 'ms-3': buttonIndex > 0 }"
47- @click =" button.onclick(modal)"
48- >
49- {{ button.label }}
50- </Button >
51- </div >
52- </div >
53- </div >
54- <div >
55- <!-- Confirmation Modal -->
56- <div
57- v-if =" showConfirmationOnClose"
58- class =" fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-[60]"
59- >
60- <div class =" bg-white dark:bg-gray-800 p-6 rounded-lg shadow-lg max-w-sm w-full" >
61- <h2 class =" text-lg font-semibold mb-4 text-lightDialogHeaderText dark:text-darkDialogHeaderText" >Confirm Close</h2 >
62- <p class =" mb-6 text-lightDialogBodyText dark:text-darkDialogBodyText" >{{ props.closeConfirmationText }}</p >
63- <div class =" flex justify-end" >
64- <Button
65- class =" me-3 !bg-gray-50 dark:!bg-gray-700 !text-lightDialogBodyText dark:!text-darkDialogBodyText hover:!bg-gray-100 dark:hover:!bg-gray-600 !border-gray-200 dark:!border-gray-600"
66- @click =" showConfirmationOnClose = false"
67- >
68- Cancel
69- </Button >
70- <Button
71- @click ="
72- showConfirmationOnClose = false;
73- modal?.hide();
74- "
75- >
76- Confirm
77- </Button >
78- </div >
79- </div >
80- </div >
81- </div >
13+ <template v-if =" $slots .trigger " #trigger >
14+ <slot name =" trigger" ></slot >
15+ </template >
16+
17+ <!-- Modal header -->
18+ <div
19+ v-if =" header"
20+ class =" flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-darkDialogBreakLine border-lightDialogBreakLine"
21+ >
22+ <h3 class =" text-xl font-semibold text-lightDialogHeaderText dark:text-darkDialogHeaderText" >
23+ {{ header }}
24+ </h3 >
25+ <button
26+ v-if =" headerCloseButton"
27+ type =" button"
28+ class =" text-lightDialogCloseButton bg-transparent hover:bg-lightDialogCloseButtonHoverBackground hover:text-lightDialogCloseButtonHover rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:text-darkDialogCloseButton dark:hover:bg-darkDialogCloseButtonHoverBackground dark:hover:text-darkDialogCloseButtonHover"
29+ @click =" tryToHideModal"
30+ >
31+ <svg class =" w-3 h-3" aria-hidden =" true" xmlns =" http://www.w3.org/2000/svg" fill =" none" viewBox =" 0 0 14 14" >
32+ <path stroke =" currentColor" stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" d =" m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
33+ </svg >
34+ <span class =" sr-only" >{{ t('Close Modal') }}</span >
35+ </button >
36+ </div >
37+ <!-- Modal body -->
38+ <div class =" p-4 md:p-5 text-lightDialogBodyText dark:text-darkDialogBodyText" >
39+ <slot ></slot >
40+ </div >
41+ <!-- Modal footer -->
42+ <div
43+ v-if =" buttons.length"
44+ class =" flex items-center p-4 md:p-5 border-t border-lightDialogBreakLine rounded-b dark:border-darkDialogBreakLine"
45+ >
46+ <Button
47+ v-for =" (button, buttonIndex) in buttons"
48+ :key =" buttonIndex"
49+ v-bind =" button.options"
50+ :class =" { 'ms-3': buttonIndex > 0 }"
51+ @click =" button.onclick(dialog)"
52+ >
53+ {{ button.label }}
54+ </Button >
8255 </div >
83- </Teleport >
56+ </Modal >
8457</template >
8558
8659<script setup lang="ts">
8760import Button from " ./Button.vue" ;
88- import { ref , onMounted , nextTick , onUnmounted , computed , type Ref } from ' vue' ;
89- import { Modal } from ' flowbite' ;
61+ import { ref , computed , type Ref } from ' vue' ;
62+ import { Modal } from ' @/afcl'
63+ import { useI18n } from " vue-i18n" ;
64+
65+ const { t } = useI18n ();
66+
67+
68+ interface IDialogInsideButtonClickHandler {
69+ hide: () => void
70+ }
9071
91- const modalEl = ref (null );
92- const modal: Ref <Modal | null > = ref (null );
9372
9473interface DialogButton {
9574 label: string
96- onclick: (dialog : any ) => void
75+ onclick: (dialog : IDialogInsideButtonClickHandler ) => void
9776 options? : Record <string , any >
9877}
9978
79+
10080interface DialogProps {
81+ /**
82+ * The header text to display in the dialog. If not provided, no header will be displayed.
83+ */
10184 header? : string
85+
86+ /**
87+ * If true, a close button will be displayed in the dialog header. Default is true.
88+ */
10289 headerCloseButton? : boolean
90+
91+ /**
92+ * An array of buttons to display in the dialog footer.
93+ */
10394 buttons? : DialogButton []
95+
96+ /**
97+ * If true, clicking outside the dialog will close it. Default is true.
98+ *
99+ * @deprecated Use `closeByClickOutside` instead
100+ */
104101 clickToCloseOutside? : boolean
102+
103+ /**
104+ * If true, pressing the Esc key will close the dialog. Default is true.
105+ */
106+ closeByEsc? : boolean
107+
108+ /**
109+ * If true, clicking outside the dialog will close it. Default is true.
110+ */
111+ closeByClickOutside? : boolean
112+
113+ /**
114+ * Function that will be called before the dialog is closed.
115+ */
105116 beforeCloseFunction? : (() => void | Promise <void >) | null
117+
118+ /**
119+ * Function that will be called before the dialog is opened.
120+ */
106121 beforeOpenFunction? : (() => void | Promise <void >) | null
122+
123+ /**
124+ * Disables close on Ecs button
125+ *
126+ * @deprecated Use `closeByEsc` or instead
127+ */
107128 closable? : boolean
129+
130+ /**
131+ * If true, the dialog will ask for confirmation before closing. Default is false.
132+ */
108133 askForCloseConfirmation? : boolean
134+
135+ /**
136+ * The text to display in the close confirmation dialog. Default is "Are you sure you want to close this dialog?".
137+ */
109138 closeConfirmationText? : string
139+
140+ /**
141+ * If true, the dialog will be removed from the DOM when closed. Default is false.
142+ */
143+ removeFromDomOnClose? : boolean
110144}
111145
146+
147+
148+
149+
150+
151+ /** ******** for the backward compatibility ***************/
152+ class Dialog implements IDialogInsideButtonClickHandler {
153+ hide: () => void
154+ constructor ( hide : () => void ) {
155+ this .hide = hide ;
156+ }
157+ }
158+ const dialog: Ref <Dialog > = ref (
159+ new Dialog (
160+ () => {
161+ if (dialog .value ) {
162+ tryToHideModal ();
163+ }
164+ }
165+ )
166+ );
167+ /** ***********************************************************/
168+
169+
170+
171+ const modalRef = ref ();
172+
112173const props = withDefaults (defineProps <DialogProps >(), {
113174 header: ' ' ,
114175 headerCloseButton: true ,
115176 buttons : () => [],
116- clickToCloseOutside: true ,
177+ clickToCloseOutside: false ,
178+ closeByEsc: true ,
179+ closeByClickOutside: true ,
117180 beforeCloseFunction: null ,
118181 beforeOpenFunction: null ,
119- closable: true ,
182+ closable: false ,
120183 askForCloseConfirmation: false ,
121184 closeConfirmationText: ' Are you sure you want to close this dialog?' ,
185+ removeFromDomOnClose: false ,
122186})
123187
124188const buttons = computed <DialogButton []>(() => {
@@ -129,51 +193,20 @@ const buttons = computed<DialogButton[]>(() => {
129193 {
130194 label: ' Close' ,
131195 onclick : (dialog : any ) => {
132- if (! props .askForCloseConfirmation ) {
133- dialog .hide ();
134- } else {
135- showConfirmationOnClose .value = true ;
136- }
196+ tryToHideModal ();
137197 },
138198 options: {}
139199 }
140200 ];
141201});
142202
143- const showConfirmationOnClose = ref (false );
144- onMounted (async () => {
145- // await one tick when all is mounted
146- await nextTick ();
147- modal .value = new Modal (
148- modalEl .value ,
149- {
150- closable: props .closable ,
151- backdrop: props .clickToCloseOutside ? ' dynamic' : ' static' ,
152- onHide : async () => {
153- if (props .beforeCloseFunction ) {
154- await props .beforeCloseFunction ();
155- }
156- },
157- onShow : async () => {
158- if (props .beforeOpenFunction ) {
159- await props .beforeOpenFunction ();
160- }
161- },
162- }
163- );
164- })
165-
166- onUnmounted (() => {
167- // destroy tooltip
168- modal .value ?.destroy ();
169- })
170203
171204function open() {
172- modal .value ?. show ();
205+ modalRef .value . open ();
173206}
174207
175208function close() {
176- modal .value ? .hide ();
209+ modalRef .value .hide ();
177210}
178211
179212defineExpose ({
@@ -183,11 +216,7 @@ defineExpose({
183216})
184217
185218function tryToHideModal() {
186- if (! props .askForCloseConfirmation ) {
187- modal .value ?.hide ();
188- } else {
189- showConfirmationOnClose .value = true ;
190- }
219+ modalRef .value ?.tryToHideModal ();
191220}
192221
193222
0 commit comments