vue-dialog-view 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,6 +65,7 @@ const showDialog = ref(false)
65
65
  | `modelValue` | `boolean` | **required** | Controls the visibility of the dialog |
66
66
  | `showTitleBar` | `boolean` | `true` | Whether to show the title bar |
67
67
  | `showCloseButton` | `boolean` | `true` | Whether to show the close button in title bar |
68
+ | `closable` | `boolean` | `true` | Control if the dialog can be closed **by the user** (programmatically close will always work) |
68
69
 
69
70
  ## Events
70
71
 
@@ -76,7 +77,8 @@ const showDialog = ref(false)
76
77
 
77
78
  | Slot | Description |
78
79
  |------|-------------|
79
- | `#title` | Content for the dialog title |
80
+ | `#title` | Content for the dialog title (optional) |
81
+ | `#footer` | Footer of the dialog (optional) |
80
82
  | `default` | Main content of the dialog |
81
83
 
82
84
  ## Methods
@@ -2,12 +2,14 @@ interface Props {
2
2
  modelValue: boolean;
3
3
  showTitleBar?: boolean;
4
4
  showCloseButton?: boolean;
5
+ closable?: boolean;
5
6
  }
6
7
  declare function __VLS_template(): {
7
8
  attrs: Partial<{}>;
8
9
  slots: {
9
10
  title?(_: {}): any;
10
11
  default?(_: {}): any;
12
+ footer?(_: {}): any;
11
13
  };
12
14
  refs: {
13
15
  dialogRef: HTMLDialogElement;
@@ -25,6 +27,7 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {
25
27
  }>, {
26
28
  showTitleBar: boolean;
27
29
  showCloseButton: boolean;
30
+ closable: boolean;
28
31
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
29
32
  dialogRef: HTMLDialogElement;
30
33
  }, HTMLDialogElement>;
@@ -1,59 +1,72 @@
1
- (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode("._b4102a3b79656a37{padding:20px;border-radius:5px;border:1px solid gray;outline:0!important;max-width:calc(100% - 2em);max-height:calc(100% - 2em);box-sizing:border-box;overflow:hidden}._b4102a3b79656a37[open]{display:flex;flex-direction:column}._b4102a3b79656a37::backdrop{background:#00000080}._4d394b1507fdc584{display:flex;flex-direction:row;align-items:center;margin-bottom:.5em;min-height:24px;white-space:pre;overflow:hidden}._088d860d2fd75292{flex:1;text-align:center;font-weight:700;font-size:large;overflow:hidden;text-overflow:ellipsis}._468ff1da37ead40a{margin-left:.5em;text-decoration:none;color:#666;font-size:1.5em;line-height:1;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;background:none}._468ff1da37ead40a:hover{color:#333;background-color:#f0f0f0;border-radius:3px}._da3b3b2a4aeed1ee{flex:1;overflow:auto;display:flex;flex-direction:column}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
- import { defineComponent as v, ref as h, watch as g, nextTick as w, createElementBlock as a, openBlock as t, mergeProps as V, createCommentVNode as i, createElementVNode as d, renderSlot as u, withModifiers as _ } from "vue";
3
- const B = {
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode("._b4102a3b79656a37{padding:20px;border-radius:5px;border:1px solid gray;outline:0!important;max-width:calc(100% - 2em);max-height:calc(100% - 2em);box-sizing:border-box;overflow:hidden}._b4102a3b79656a37[open]{display:flex;flex-direction:column}._b4102a3b79656a37::backdrop{background:#00000080}._4d394b1507fdc584{display:flex;flex-direction:row;align-items:center;margin-bottom:.5em;min-height:24px;white-space:pre;overflow:hidden}._088d860d2fd75292{flex:1;text-align:center;font-weight:700;font-size:large;overflow:hidden;text-overflow:ellipsis}._468ff1da37ead40a{margin-left:.5em;text-decoration:none;color:#666;font-size:1.5em;line-height:1;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;background:none}._468ff1da37ead40a:hover{color:#333;background-color:#f0f0f0;border-radius:3px}._da3b3b2a4aeed1ee{flex:1;overflow:auto;display:flex;flex-direction:column}._61879ba330d9a71c{margin-top:.5em}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
+ import { defineComponent as v, ref as V, watch as g, nextTick as r, createElementBlock as t, openBlock as s, mergeProps as w, createCommentVNode as n, createElementVNode as c, renderSlot as d, withModifiers as _ } from "vue";
3
+ const b = {
4
4
  key: 0,
5
5
  class: "_4d394b1507fdc584"
6
- }, b = { class: "_088d860d2fd75292" }, C = { class: "_da3b3b2a4aeed1ee" }, k = /* @__PURE__ */ v({
6
+ }, B = { class: "_088d860d2fd75292" }, y = { class: "_da3b3b2a4aeed1ee" }, k = {
7
+ key: 1,
8
+ class: "_61879ba330d9a71c"
9
+ }, C = /* @__PURE__ */ v({
7
10
  __name: "DialogView.obf",
8
11
  props: {
9
12
  modelValue: { type: Boolean },
10
13
  showTitleBar: { type: Boolean, default: !0 },
11
- showCloseButton: { type: Boolean, default: !0 }
14
+ showCloseButton: { type: Boolean, default: !0 },
15
+ closable: { type: Boolean, default: !0 }
12
16
  },
13
17
  emits: ["update:modelValue"],
14
- setup(o, { expose: c, emit: r }) {
15
- const s = o, f = r, e = h(null), p = () => {
16
- e.value && !e.value.open && e.value.showModal();
17
- }, n = () => {
18
- e.value && e.value.open && e.value.close();
19
- }, m = () => {
20
- s.modelValue && f("update:modelValue", !1);
18
+ setup(l, { expose: f, emit: p }) {
19
+ const a = l, i = p, e = V(null), m = () => {
20
+ i("update:modelValue", !0);
21
+ }, u = () => {
22
+ i("update:modelValue", !1);
23
+ }, h = () => {
24
+ if (!a.closable && a.modelValue) {
25
+ r(() => {
26
+ e.value && !e.value.open && e.value.showModal();
27
+ });
28
+ return;
29
+ }
30
+ a.modelValue && i("update:modelValue", !1);
21
31
  };
22
- return g(() => s.modelValue, async (l) => {
23
- await w(), l ? e.value && !e.value.open && e.value.showModal() : e.value && e.value.open && e.value.close();
24
- }), c({
25
- open: p,
26
- close: n
27
- }), (l, y) => (t(), a("dialog", V({
32
+ return g(() => a.modelValue, async (o) => {
33
+ await r(), o ? e.value && !e.value.open && e.value.showModal() : e.value && e.value.open && e.value.close();
34
+ }), f({
35
+ open: m,
36
+ close: u
37
+ }), (o, D) => (s(), t("dialog", w({
28
38
  ref_key: "dialogRef",
29
39
  ref: e,
30
40
  class: "_b4102a3b79656a37"
31
- }, l.$attrs, { onClose: m }), [
32
- o.showTitleBar ? (t(), a("div", B, [
33
- d("span", b, [
34
- u(l.$slots, "title")
41
+ }, o.$attrs, { onClose: h }), [
42
+ l.showTitleBar ? (s(), t("div", b, [
43
+ c("span", B, [
44
+ d(o.$slots, "title")
35
45
  ]),
36
- o.showCloseButton ? (t(), a("a", {
46
+ l.showCloseButton ? (s(), t("a", {
37
47
  key: 0,
38
48
  href: "javascript:void(0)",
39
49
  role: "button",
40
50
  "aria-label": "Close the dialog",
41
51
  class: "_468ff1da37ead40a",
42
- onClick: _(n, ["prevent"])
43
- }, "×")) : i("", !0)
44
- ])) : i("", !0),
45
- d("div", C, [
46
- u(l.$slots, "default")
47
- ])
52
+ onClick: _(u, ["prevent"])
53
+ }, "×")) : n("", !0)
54
+ ])) : n("", !0),
55
+ c("div", y, [
56
+ d(o.$slots, "default")
57
+ ]),
58
+ o.$slots.footer ? (s(), t("div", k, [
59
+ d(o.$slots, "footer")
60
+ ])) : n("", !0)
48
61
  ], 16));
49
62
  }
50
63
  }), M = {
51
- install: (o) => {
52
- o.component("DialogView", k);
64
+ install: (l) => {
65
+ l.component("DialogView", C);
53
66
  }
54
67
  };
55
68
  export {
56
- k as DialogView,
69
+ C as DialogView,
57
70
  M as DialogViewPlugin,
58
71
  M as default
59
72
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dialog-view.es.js","sources":["../src/DialogView.obf.vue","../src/index.ts"],"sourcesContent":["<template>\n <dialog\n ref=\"dialogRef\"\n class=\"_b4102a3b79656a37\"\n v-bind=\"$attrs\"\n @close=\"handleDialogClose\"\n >\n <div v-if=\"showTitleBar\" class=\"_4d394b1507fdc584\">\n <span class=\"_088d860d2fd75292\">\n <slot name=\"title\"></slot>\n </span>\n <a\n v-if=\"showCloseButton\"\n href=\"javascript:void(0)\"\n role=\"button\"\n aria-label=\"Close the dialog\"\n class=\"_468ff1da37ead40a\"\n @click.prevent=\"closeDialog\"\n >×</a>\n </div>\n <div class=\"_da3b3b2a4aeed1ee\">\n <slot></slot>\n </div>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, nextTick } from 'vue'\n\ninterface Props {\n modelValue: boolean\n showTitleBar?: boolean\n showCloseButton?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showTitleBar: true,\n showCloseButton: true\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n}>()\n\nconst dialogRef = ref<HTMLDialogElement | null>(null)\n\nconst openDialog = (): void => {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n}\n\nconst closeDialog = (): void => {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n}\n\nconst handleDialogClose = (): void => {\n if (props.modelValue) {\n emit('update:modelValue', false)\n }\n}\n\nwatch(() => props.modelValue, async (newValue) => {\n await nextTick()\n \n if (newValue) {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n } else {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n }\n})\n\ndefineExpose({\n open: openDialog,\n close: closeDialog,\n})\n</script>\n\n<style>\n._b4102a3b79656a37 {\n padding: 20px;\n border-radius: 5px;\n border: 1px solid gray;\n outline: 0 !important;\n max-width: calc(100% - 2em);\n max-height: calc(100% - 2em);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n._b4102a3b79656a37[open] {\n display: flex;\n flex-direction: column;\n}\n\n._b4102a3b79656a37::backdrop {\n background: rgba(0, 0, 0, 0.5);\n}\n\n._4d394b1507fdc584 {\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-bottom: 0.5em;\n min-height: 24px;\n white-space: pre;\n overflow: hidden;\n}\n\n._088d860d2fd75292 {\n flex: 1;\n text-align: center;\n font-weight: bold;\n font-size: large;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._468ff1da37ead40a {\n margin-left: 0.5em;\n text-decoration: none;\n color: #666;\n font-size: 1.5em;\n line-height: 1;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n background: none;\n}\n\n._468ff1da37ead40a:hover {\n color: #333;\n background-color: #f0f0f0;\n border-radius: 3px;\n}\n\n._da3b3b2a4aeed1ee {\n flex: 1;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n</style>","import { App, Plugin } from 'vue'\nimport DialogViewComponent from './DialogView.obf.vue'\n\nexport { default as DialogView } from './DialogView.obf.vue'\n\nexport const DialogViewPlugin: Plugin = {\n install: (app: App) => {\n app.component('DialogView', DialogViewComponent)\n }\n}\n\nexport default DialogViewPlugin\n"],"names":["props","__props","emit","__emit","dialogRef","ref","openDialog","closeDialog","handleDialogClose","watch","newValue","nextTick","__expose","_openBlock","_createElementBlock","_mergeProps","$attrs","_hoisted_1","_createElementVNode","_hoisted_2","_renderSlot","_ctx","_hoisted_3","DialogViewPlugin","app","DialogViewComponent"],"mappings":";;;;;;;;;;;;;AAmCA,UAAMA,IAAQC,GAKRC,IAAOC,GAIPC,IAAYC,EAA8B,IAAI,GAE9CC,IAAa,MAAY;AAC7B,MAAIF,EAAU,SAAS,CAACA,EAAU,MAAM,QACtCA,EAAU,MAAM,UAAA;AAAA,IAEpB,GAEMG,IAAc,MAAY;AAC9B,MAAIH,EAAU,SAASA,EAAU,MAAM,QACrCA,EAAU,MAAM,MAAA;AAAA,IAEpB,GAEMI,IAAoB,MAAY;AACpC,MAAIR,EAAM,cACRE,EAAK,qBAAqB,EAAK;AAAA,IAEnC;AAEA,WAAAO,EAAM,MAAMT,EAAM,YAAY,OAAOU,MAAa;AAChD,YAAMC,EAAA,GAEFD,IACEN,EAAU,SAAS,CAACA,EAAU,MAAM,QACtCA,EAAU,MAAM,UAAA,IAGdA,EAAU,SAASA,EAAU,MAAM,QACrCA,EAAU,MAAM,MAAA;AAAA,IAGtB,CAAC,GAEDQ,EAAa;AAAA,MACX,MAAMN;AAAA,MACN,OAAOC;AAAA,IAAA,CACR,cAhFCM,EAAA,GAAAC,EAsBS,UAtBTC,EAsBS;AAAA,eArBH;AAAA,MAAJ,KAAIX;AAAA,MACJ,OAAM;AAAA,IAAA,GACEY,EAAAA,QAAM,EACb,SAAOR,EAAA,CAAiB,GAAA;AAAA,MAEdP,EAAA,gBAAXY,EAAA,GAAAC,EAYM,OAZNG,GAYM;AAAA,QAXJC,EAEO,QAFPC,GAEO;AAAA,UADLC,EAA0BC,EAAA,QAAA,OAAA;AAAA,QAAA;QAGpBpB,EAAA,wBADRa,EAOM,KAAA;AAAA;UALJ,MAAK;AAAA,UACL,MAAK;AAAA,UACL,cAAW;AAAA,UACX,OAAM;AAAA,UACL,WAAeP,GAAW,CAAA,SAAA,CAAA;AAAA,QAAA,GAC5B,GAAC;;MAEJW,EAEM,OAFNI,GAEM;AAAA,QADJF,EAAaC,EAAA,QAAA,SAAA;AAAA,MAAA;;;IChBNE,IAA2B;AAAA,EACtC,SAAS,CAACC,MAAa;AACrB,IAAAA,EAAI,UAAU,cAAcC,CAAmB;AAAA,EACjD;AACF;"}
1
+ {"version":3,"file":"dialog-view.es.js","sources":["../src/DialogView.obf.vue","../src/index.ts"],"sourcesContent":["<template>\n <dialog\n ref=\"dialogRef\"\n class=\"_b4102a3b79656a37\"\n v-bind=\"$attrs\"\n @close=\"handleDialogClose\"\n >\n <div v-if=\"showTitleBar\" class=\"_4d394b1507fdc584\">\n <span class=\"_088d860d2fd75292\">\n <slot name=\"title\"></slot>\n </span>\n <a\n v-if=\"showCloseButton\"\n href=\"javascript:void(0)\"\n role=\"button\"\n aria-label=\"Close the dialog\"\n class=\"_468ff1da37ead40a\"\n @click.prevent=\"closeDialog\"\n >×</a>\n </div>\n <div class=\"_da3b3b2a4aeed1ee\">\n <slot></slot>\n </div>\n\n <div v-if=\"$slots.footer\" class=\"_61879ba330d9a71c\">\n <slot name=\"footer\"></slot>\n </div>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, nextTick } from 'vue'\n\ninterface Props {\n modelValue: boolean\n showTitleBar?: boolean\n showCloseButton?: boolean\n closable?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showTitleBar: true,\n showCloseButton: true,\n closable: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n}>()\n\nconst dialogRef = ref<HTMLDialogElement | null>(null)\n\nconst openDialog = (): void => {\n emit('update:modelValue', true)\n}\n\nconst closeDialog = (): void => {\n emit('update:modelValue', false)\n}\n\nconst handleDialogClose = (): void => {\n if (!props.closable) {\n if (props.modelValue) {\n // not programmatically close\n // re-open the dialog\n nextTick(() => {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n }) // Avoid using 'cancel' event because some browsers handle it incorrectly\n return;\n }\n }\n if (props.modelValue) {\n emit('update:modelValue', false)\n }\n}\n\nwatch(() => props.modelValue, async (newValue: boolean) => {\n await nextTick()\n \n if (newValue) {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n } else {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n }\n})\n\ndefineExpose({\n open: openDialog,\n close: closeDialog,\n})\n</script>\n\n<style>\n._b4102a3b79656a37 {\n padding: 20px;\n border-radius: 5px;\n border: 1px solid gray;\n outline: 0 !important;\n max-width: calc(100% - 2em);\n max-height: calc(100% - 2em);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n._b4102a3b79656a37[open] {\n display: flex;\n flex-direction: column;\n}\n\n._b4102a3b79656a37::backdrop {\n background: rgba(0, 0, 0, 0.5);\n}\n\n._4d394b1507fdc584 {\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-bottom: 0.5em;\n min-height: 24px;\n white-space: pre;\n overflow: hidden;\n}\n\n._088d860d2fd75292 {\n flex: 1;\n text-align: center;\n font-weight: bold;\n font-size: large;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._468ff1da37ead40a {\n margin-left: 0.5em;\n text-decoration: none;\n color: #666;\n font-size: 1.5em;\n line-height: 1;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n background: none;\n}\n\n._468ff1da37ead40a:hover {\n color: #333;\n background-color: #f0f0f0;\n border-radius: 3px;\n}\n\n._da3b3b2a4aeed1ee {\n flex: 1;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n\n._61879ba330d9a71c {\n margin-top: 0.5em;\n}\n</style>","import { App, Plugin } from 'vue'\nimport DialogViewComponent from './DialogView.obf.vue'\n\nexport { default as DialogView } from './DialogView.obf.vue'\n\nexport const DialogViewPlugin: Plugin = {\n install: (app: App) => {\n app.component('DialogView', DialogViewComponent)\n }\n}\n\nexport default DialogViewPlugin\n"],"names":["props","__props","emit","__emit","dialogRef","ref","openDialog","closeDialog","handleDialogClose","nextTick","watch","newValue","__expose","_openBlock","_createElementBlock","_mergeProps","$attrs","_hoisted_1","_createElementVNode","_hoisted_2","_renderSlot","_ctx","_hoisted_3","$slots","_hoisted_4","DialogViewPlugin","app","DialogViewComponent"],"mappings":";;;;;;;;;;;;;;;;;AAwCA,UAAMA,IAAQC,GAMRC,IAAOC,GAIPC,IAAYC,EAA8B,IAAI,GAE9CC,IAAa,MAAY;AAC7B,MAAAJ,EAAK,qBAAqB,EAAI;AAAA,IAChC,GAEMK,IAAc,MAAY;AAC9B,MAAAL,EAAK,qBAAqB,EAAK;AAAA,IACjC,GAEMM,IAAoB,MAAY;AACpC,UAAI,CAACR,EAAM,YACLA,EAAM,YAAY;AAGpB,QAAAS,EAAS,MAAM;AACb,UAAIL,EAAU,SAAS,CAACA,EAAU,MAAM,QACtCA,EAAU,MAAM,UAAA;AAAA,QAEpB,CAAC;AACD;AAAA,MACF;AAEF,MAAIJ,EAAM,cACRE,EAAK,qBAAqB,EAAK;AAAA,IAEnC;AAEA,WAAAQ,EAAM,MAAMV,EAAM,YAAY,OAAOW,MAAsB;AACzD,YAAMF,EAAA,GAEFE,IACEP,EAAU,SAAS,CAACA,EAAU,MAAM,QACtCA,EAAU,MAAM,UAAA,IAGdA,EAAU,SAASA,EAAU,MAAM,QACrCA,EAAU,MAAM,MAAA;AAAA,IAGtB,CAAC,GAEDQ,EAAa;AAAA,MACX,MAAMN;AAAA,MACN,OAAOC;AAAA,IAAA,CACR,cA9FCM,EAAA,GAAAC,EA0BS,UA1BTC,EA0BS;AAAA,eAzBH;AAAA,MAAJ,KAAIX;AAAA,MACJ,OAAM;AAAA,IAAA,GACEY,EAAAA,QAAM,EACb,SAAOR,EAAA,CAAiB,GAAA;AAAA,MAEdP,EAAA,gBAAXY,EAAA,GAAAC,EAYM,OAZNG,GAYM;AAAA,QAXJC,EAEO,QAFPC,GAEO;AAAA,UADLC,EAA0BC,EAAA,QAAA,OAAA;AAAA,QAAA;QAGpBpB,EAAA,wBADRa,EAOM,KAAA;AAAA;UALJ,MAAK;AAAA,UACL,MAAK;AAAA,UACL,cAAW;AAAA,UACX,OAAM;AAAA,UACL,WAAeP,GAAW,CAAA,SAAA,CAAA;AAAA,QAAA,GAC5B,GAAC;;MAEJW,EAEM,OAFNI,GAEM;AAAA,QADJF,EAAaC,EAAA,QAAA,SAAA;AAAA,MAAA;MAGJE,EAAAA,OAAO,UAAlBV,KAAAC,EAEM,OAFNU,GAEM;AAAA,QADJJ,EAA2BC,EAAA,QAAA,QAAA;AAAA,MAAA;;;ICpBpBI,IAA2B;AAAA,EACtC,SAAS,CAACC,MAAa;AACrB,IAAAA,EAAI,UAAU,cAAcC,CAAmB;AAAA,EACjD;AACF;"}
@@ -1,3 +1,3 @@
1
- (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode("._b4102a3b79656a37{padding:20px;border-radius:5px;border:1px solid gray;outline:0!important;max-width:calc(100% - 2em);max-height:calc(100% - 2em);box-sizing:border-box;overflow:hidden}._b4102a3b79656a37[open]{display:flex;flex-direction:column}._b4102a3b79656a37::backdrop{background:#00000080}._4d394b1507fdc584{display:flex;flex-direction:row;align-items:center;margin-bottom:.5em;min-height:24px;white-space:pre;overflow:hidden}._088d860d2fd75292{flex:1;text-align:center;font-weight:700;font-size:large;overflow:hidden;text-overflow:ellipsis}._468ff1da37ead40a{margin-left:.5em;text-decoration:none;color:#666;font-size:1.5em;line-height:1;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;background:none}._468ff1da37ead40a:hover{color:#333;background-color:#f0f0f0;border-radius:3px}._da3b3b2a4aeed1ee{flex:1;overflow:auto;display:flex;flex-direction:column}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
- (function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l.DialogView={},l.Vue))})(this,(function(l,e){"use strict";const c={key:0,class:"_4d394b1507fdc584"},r={class:"_088d860d2fd75292"},f={class:"_da3b3b2a4aeed1ee"},n=e.defineComponent({__name:"DialogView.obf",props:{modelValue:{type:Boolean},showTitleBar:{type:Boolean,default:!0},showCloseButton:{type:Boolean,default:!0}},emits:["update:modelValue"],setup(t,{expose:u,emit:p}){const s=t,m=p,o=e.ref(null),h=()=>{o.value&&!o.value.open&&o.value.showModal()},d=()=>{o.value&&o.value.open&&o.value.close()},g=()=>{s.modelValue&&m("update:modelValue",!1)};return e.watch(()=>s.modelValue,async a=>{await e.nextTick(),a?o.value&&!o.value.open&&o.value.showModal():o.value&&o.value.open&&o.value.close()}),u({open:h,close:d}),(a,V)=>(e.openBlock(),e.createElementBlock("dialog",e.mergeProps({ref_key:"dialogRef",ref:o,class:"_b4102a3b79656a37"},a.$attrs,{onClose:g}),[t.showTitleBar?(e.openBlock(),e.createElementBlock("div",c,[e.createElementVNode("span",r,[e.renderSlot(a.$slots,"title")]),t.showCloseButton?(e.openBlock(),e.createElementBlock("a",{key:0,href:"javascript:void(0)",role:"button","aria-label":"Close the dialog",class:"_468ff1da37ead40a",onClick:e.withModifiers(d,["prevent"])},"×")):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",f,[e.renderSlot(a.$slots,"default")])],16))}}),i={install:t=>{t.component("DialogView",n)}};l.DialogView=n,l.DialogViewPlugin=i,l.default=i,Object.defineProperties(l,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode("._b4102a3b79656a37{padding:20px;border-radius:5px;border:1px solid gray;outline:0!important;max-width:calc(100% - 2em);max-height:calc(100% - 2em);box-sizing:border-box;overflow:hidden}._b4102a3b79656a37[open]{display:flex;flex-direction:column}._b4102a3b79656a37::backdrop{background:#00000080}._4d394b1507fdc584{display:flex;flex-direction:row;align-items:center;margin-bottom:.5em;min-height:24px;white-space:pre;overflow:hidden}._088d860d2fd75292{flex:1;text-align:center;font-weight:700;font-size:large;overflow:hidden;text-overflow:ellipsis}._468ff1da37ead40a{margin-left:.5em;text-decoration:none;color:#666;font-size:1.5em;line-height:1;width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;background:none}._468ff1da37ead40a:hover{color:#333;background-color:#f0f0f0;border-radius:3px}._da3b3b2a4aeed1ee{flex:1;overflow:auto;display:flex;flex-direction:column}._61879ba330d9a71c{margin-top:.5em}")),document.head.appendChild(e)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
2
+ (function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l.DialogView={},l.Vue))})(this,(function(l,e){"use strict";const r={key:0,class:"_4d394b1507fdc584"},f={class:"_088d860d2fd75292"},u={class:"_da3b3b2a4aeed1ee"},m={key:1,class:"_61879ba330d9a71c"},i=e.defineComponent({__name:"DialogView.obf",props:{modelValue:{type:Boolean},showTitleBar:{type:Boolean,default:!0},showCloseButton:{type:Boolean,default:!0},closable:{type:Boolean,default:!0}},emits:["update:modelValue"],setup(a,{expose:p,emit:V}){const n=a,s=V,o=e.ref(null),h=()=>{s("update:modelValue",!0)},c=()=>{s("update:modelValue",!1)},g=()=>{if(!n.closable&&n.modelValue){e.nextTick(()=>{o.value&&!o.value.open&&o.value.showModal()});return}n.modelValue&&s("update:modelValue",!1)};return e.watch(()=>n.modelValue,async t=>{await e.nextTick(),t?o.value&&!o.value.open&&o.value.showModal():o.value&&o.value.open&&o.value.close()}),p({open:h,close:c}),(t,B)=>(e.openBlock(),e.createElementBlock("dialog",e.mergeProps({ref_key:"dialogRef",ref:o,class:"_b4102a3b79656a37"},t.$attrs,{onClose:g}),[a.showTitleBar?(e.openBlock(),e.createElementBlock("div",r,[e.createElementVNode("span",f,[e.renderSlot(t.$slots,"title")]),a.showCloseButton?(e.openBlock(),e.createElementBlock("a",{key:0,href:"javascript:void(0)",role:"button","aria-label":"Close the dialog",class:"_468ff1da37ead40a",onClick:e.withModifiers(c,["prevent"])},"×")):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",u,[e.renderSlot(t.$slots,"default")]),t.$slots.footer?(e.openBlock(),e.createElementBlock("div",m,[e.renderSlot(t.$slots,"footer")])):e.createCommentVNode("",!0)],16))}}),d={install:a=>{a.component("DialogView",i)}};l.DialogView=i,l.DialogViewPlugin=d,l.default=d,Object.defineProperties(l,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
3
3
  //# sourceMappingURL=dialog-view.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog-view.umd.js","sources":["../src/DialogView.obf.vue","../src/index.ts"],"sourcesContent":["<template>\n <dialog\n ref=\"dialogRef\"\n class=\"_b4102a3b79656a37\"\n v-bind=\"$attrs\"\n @close=\"handleDialogClose\"\n >\n <div v-if=\"showTitleBar\" class=\"_4d394b1507fdc584\">\n <span class=\"_088d860d2fd75292\">\n <slot name=\"title\"></slot>\n </span>\n <a\n v-if=\"showCloseButton\"\n href=\"javascript:void(0)\"\n role=\"button\"\n aria-label=\"Close the dialog\"\n class=\"_468ff1da37ead40a\"\n @click.prevent=\"closeDialog\"\n >×</a>\n </div>\n <div class=\"_da3b3b2a4aeed1ee\">\n <slot></slot>\n </div>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, nextTick } from 'vue'\n\ninterface Props {\n modelValue: boolean\n showTitleBar?: boolean\n showCloseButton?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showTitleBar: true,\n showCloseButton: true\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n}>()\n\nconst dialogRef = ref<HTMLDialogElement | null>(null)\n\nconst openDialog = (): void => {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n}\n\nconst closeDialog = (): void => {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n}\n\nconst handleDialogClose = (): void => {\n if (props.modelValue) {\n emit('update:modelValue', false)\n }\n}\n\nwatch(() => props.modelValue, async (newValue) => {\n await nextTick()\n \n if (newValue) {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n } else {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n }\n})\n\ndefineExpose({\n open: openDialog,\n close: closeDialog,\n})\n</script>\n\n<style>\n._b4102a3b79656a37 {\n padding: 20px;\n border-radius: 5px;\n border: 1px solid gray;\n outline: 0 !important;\n max-width: calc(100% - 2em);\n max-height: calc(100% - 2em);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n._b4102a3b79656a37[open] {\n display: flex;\n flex-direction: column;\n}\n\n._b4102a3b79656a37::backdrop {\n background: rgba(0, 0, 0, 0.5);\n}\n\n._4d394b1507fdc584 {\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-bottom: 0.5em;\n min-height: 24px;\n white-space: pre;\n overflow: hidden;\n}\n\n._088d860d2fd75292 {\n flex: 1;\n text-align: center;\n font-weight: bold;\n font-size: large;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._468ff1da37ead40a {\n margin-left: 0.5em;\n text-decoration: none;\n color: #666;\n font-size: 1.5em;\n line-height: 1;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n background: none;\n}\n\n._468ff1da37ead40a:hover {\n color: #333;\n background-color: #f0f0f0;\n border-radius: 3px;\n}\n\n._da3b3b2a4aeed1ee {\n flex: 1;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n</style>","import { App, Plugin } from 'vue'\nimport DialogViewComponent from './DialogView.obf.vue'\n\nexport { default as DialogView } from './DialogView.obf.vue'\n\nexport const DialogViewPlugin: Plugin = {\n install: (app: App) => {\n app.component('DialogView', DialogViewComponent)\n }\n}\n\nexport default DialogViewPlugin\n"],"names":["props","__props","emit","__emit","dialogRef","ref","openDialog","closeDialog","handleDialogClose","watch","newValue","nextTick","__expose","_openBlock","_createElementBlock","_mergeProps","$attrs","_hoisted_1","_createElementVNode","_hoisted_2","_renderSlot","_ctx","_hoisted_3","DialogViewPlugin","app","DialogViewComponent"],"mappings":"6jBAmCA,MAAMA,EAAQC,EAKRC,EAAOC,EAIPC,EAAYC,EAAAA,IAA8B,IAAI,EAE9CC,EAAa,IAAY,CACzBF,EAAU,OAAS,CAACA,EAAU,MAAM,MACtCA,EAAU,MAAM,UAAA,CAEpB,EAEMG,EAAc,IAAY,CAC1BH,EAAU,OAASA,EAAU,MAAM,MACrCA,EAAU,MAAM,MAAA,CAEpB,EAEMI,EAAoB,IAAY,CAChCR,EAAM,YACRE,EAAK,oBAAqB,EAAK,CAEnC,EAEAO,OAAAA,EAAAA,MAAM,IAAMT,EAAM,WAAY,MAAOU,GAAa,CAChD,MAAMC,WAAA,EAEFD,EACEN,EAAU,OAAS,CAACA,EAAU,MAAM,MACtCA,EAAU,MAAM,UAAA,EAGdA,EAAU,OAASA,EAAU,MAAM,MACrCA,EAAU,MAAM,MAAA,CAGtB,CAAC,EAEDQ,EAAa,CACX,KAAMN,EACN,MAAOC,CAAA,CACR,UAhFCM,YAAA,EAAAC,qBAsBS,SAtBTC,EAAAA,WAsBS,SArBH,YAAJ,IAAIX,EACJ,MAAM,mBAAA,EACEY,EAAAA,OAAM,CACb,QAAOR,CAAA,CAAiB,EAAA,CAEdP,EAAA,cAAXY,EAAAA,UAAA,EAAAC,EAAAA,mBAYM,MAZNG,EAYM,CAXJC,EAAAA,mBAEO,OAFPC,EAEO,CADLC,aAA0BC,EAAA,OAAA,OAAA,CAAA,GAGpBpB,EAAA,+BADRa,EAAAA,mBAOM,IAAA,OALJ,KAAK,qBACL,KAAK,SACL,aAAW,mBACX,MAAM,oBACL,wBAAeP,EAAW,CAAA,SAAA,CAAA,CAAA,EAC5B,GAAC,8DAEJW,EAAAA,mBAEM,MAFNI,EAEM,CADJF,aAAaC,EAAA,OAAA,SAAA,CAAA,YChBNE,EAA2B,CACtC,QAAUC,GAAa,CACrBA,EAAI,UAAU,aAAcC,CAAmB,CACjD,CACF"}
1
+ {"version":3,"file":"dialog-view.umd.js","sources":["../src/DialogView.obf.vue","../src/index.ts"],"sourcesContent":["<template>\n <dialog\n ref=\"dialogRef\"\n class=\"_b4102a3b79656a37\"\n v-bind=\"$attrs\"\n @close=\"handleDialogClose\"\n >\n <div v-if=\"showTitleBar\" class=\"_4d394b1507fdc584\">\n <span class=\"_088d860d2fd75292\">\n <slot name=\"title\"></slot>\n </span>\n <a\n v-if=\"showCloseButton\"\n href=\"javascript:void(0)\"\n role=\"button\"\n aria-label=\"Close the dialog\"\n class=\"_468ff1da37ead40a\"\n @click.prevent=\"closeDialog\"\n >×</a>\n </div>\n <div class=\"_da3b3b2a4aeed1ee\">\n <slot></slot>\n </div>\n\n <div v-if=\"$slots.footer\" class=\"_61879ba330d9a71c\">\n <slot name=\"footer\"></slot>\n </div>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, nextTick } from 'vue'\n\ninterface Props {\n modelValue: boolean\n showTitleBar?: boolean\n showCloseButton?: boolean\n closable?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n showTitleBar: true,\n showCloseButton: true,\n closable: true,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n}>()\n\nconst dialogRef = ref<HTMLDialogElement | null>(null)\n\nconst openDialog = (): void => {\n emit('update:modelValue', true)\n}\n\nconst closeDialog = (): void => {\n emit('update:modelValue', false)\n}\n\nconst handleDialogClose = (): void => {\n if (!props.closable) {\n if (props.modelValue) {\n // not programmatically close\n // re-open the dialog\n nextTick(() => {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n }) // Avoid using 'cancel' event because some browsers handle it incorrectly\n return;\n }\n }\n if (props.modelValue) {\n emit('update:modelValue', false)\n }\n}\n\nwatch(() => props.modelValue, async (newValue: boolean) => {\n await nextTick()\n \n if (newValue) {\n if (dialogRef.value && !dialogRef.value.open) {\n dialogRef.value.showModal()\n }\n } else {\n if (dialogRef.value && dialogRef.value.open) {\n dialogRef.value.close()\n }\n }\n})\n\ndefineExpose({\n open: openDialog,\n close: closeDialog,\n})\n</script>\n\n<style>\n._b4102a3b79656a37 {\n padding: 20px;\n border-radius: 5px;\n border: 1px solid gray;\n outline: 0 !important;\n max-width: calc(100% - 2em);\n max-height: calc(100% - 2em);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n._b4102a3b79656a37[open] {\n display: flex;\n flex-direction: column;\n}\n\n._b4102a3b79656a37::backdrop {\n background: rgba(0, 0, 0, 0.5);\n}\n\n._4d394b1507fdc584 {\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-bottom: 0.5em;\n min-height: 24px;\n white-space: pre;\n overflow: hidden;\n}\n\n._088d860d2fd75292 {\n flex: 1;\n text-align: center;\n font-weight: bold;\n font-size: large;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._468ff1da37ead40a {\n margin-left: 0.5em;\n text-decoration: none;\n color: #666;\n font-size: 1.5em;\n line-height: 1;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: none;\n background: none;\n}\n\n._468ff1da37ead40a:hover {\n color: #333;\n background-color: #f0f0f0;\n border-radius: 3px;\n}\n\n._da3b3b2a4aeed1ee {\n flex: 1;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n\n._61879ba330d9a71c {\n margin-top: 0.5em;\n}\n</style>","import { App, Plugin } from 'vue'\nimport DialogViewComponent from './DialogView.obf.vue'\n\nexport { default as DialogView } from './DialogView.obf.vue'\n\nexport const DialogViewPlugin: Plugin = {\n install: (app: App) => {\n app.component('DialogView', DialogViewComponent)\n }\n}\n\nexport default DialogViewPlugin\n"],"names":["props","__props","emit","__emit","dialogRef","ref","openDialog","closeDialog","handleDialogClose","nextTick","watch","newValue","__expose","_openBlock","_createElementBlock","_mergeProps","$attrs","_hoisted_1","_createElementVNode","_hoisted_2","_renderSlot","_ctx","_hoisted_3","$slots","_hoisted_4","DialogViewPlugin","app","DialogViewComponent"],"mappings":"ooBAwCA,MAAMA,EAAQC,EAMRC,EAAOC,EAIPC,EAAYC,EAAAA,IAA8B,IAAI,EAE9CC,EAAa,IAAY,CAC7BJ,EAAK,oBAAqB,EAAI,CAChC,EAEMK,EAAc,IAAY,CAC9BL,EAAK,oBAAqB,EAAK,CACjC,EAEMM,EAAoB,IAAY,CACpC,GAAI,CAACR,EAAM,UACLA,EAAM,WAAY,CAGpBS,EAAAA,SAAS,IAAM,CACTL,EAAU,OAAS,CAACA,EAAU,MAAM,MACtCA,EAAU,MAAM,UAAA,CAEpB,CAAC,EACD,MACF,CAEEJ,EAAM,YACRE,EAAK,oBAAqB,EAAK,CAEnC,EAEAQ,OAAAA,EAAAA,MAAM,IAAMV,EAAM,WAAY,MAAOW,GAAsB,CACzD,MAAMF,WAAA,EAEFE,EACEP,EAAU,OAAS,CAACA,EAAU,MAAM,MACtCA,EAAU,MAAM,UAAA,EAGdA,EAAU,OAASA,EAAU,MAAM,MACrCA,EAAU,MAAM,MAAA,CAGtB,CAAC,EAEDQ,EAAa,CACX,KAAMN,EACN,MAAOC,CAAA,CACR,UA9FCM,YAAA,EAAAC,qBA0BS,SA1BTC,EAAAA,WA0BS,SAzBH,YAAJ,IAAIX,EACJ,MAAM,mBAAA,EACEY,EAAAA,OAAM,CACb,QAAOR,CAAA,CAAiB,EAAA,CAEdP,EAAA,cAAXY,EAAAA,UAAA,EAAAC,EAAAA,mBAYM,MAZNG,EAYM,CAXJC,EAAAA,mBAEO,OAFPC,EAEO,CADLC,aAA0BC,EAAA,OAAA,OAAA,CAAA,GAGpBpB,EAAA,+BADRa,EAAAA,mBAOM,IAAA,OALJ,KAAK,qBACL,KAAK,SACL,aAAW,mBACX,MAAM,oBACL,wBAAeP,EAAW,CAAA,SAAA,CAAA,CAAA,EAC5B,GAAC,8DAEJW,EAAAA,mBAEM,MAFNI,EAEM,CADJF,aAAaC,EAAA,OAAA,SAAA,CAAA,GAGJE,EAAAA,OAAO,QAAlBV,EAAAA,YAAAC,EAAAA,mBAEM,MAFNU,EAEM,CADJJ,aAA2BC,EAAA,OAAA,QAAA,CAAA,yCCpBpBI,EAA2B,CACtC,QAAUC,GAAa,CACrBA,EAAI,UAAU,aAAcC,CAAmB,CACjD,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-dialog-view",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "A modern Vue 3 dialog component using native dialog element",
5
5
  "type": "module",
6
6
  "main": "./dist/dialog-view.umd.js",
@@ -21,6 +21,10 @@
21
21
  <div class="_da3b3b2a4aeed1ee">
22
22
  <slot></slot>
23
23
  </div>
24
+
25
+ <div v-if="$slots.footer" class="_61879ba330d9a71c">
26
+ <slot name="footer"></slot>
27
+ </div>
24
28
  </dialog>
25
29
  </template>
26
30
 
@@ -31,11 +35,13 @@ interface Props {
31
35
  modelValue: boolean
32
36
  showTitleBar?: boolean
33
37
  showCloseButton?: boolean
38
+ closable?: boolean
34
39
  }
35
40
 
36
41
  const props = withDefaults(defineProps<Props>(), {
37
42
  showTitleBar: true,
38
- showCloseButton: true
43
+ showCloseButton: true,
44
+ closable: true,
39
45
  })
40
46
 
41
47
  const emit = defineEmits<{
@@ -45,24 +51,32 @@ const emit = defineEmits<{
45
51
  const dialogRef = ref<HTMLDialogElement | null>(null)
46
52
 
47
53
  const openDialog = (): void => {
48
- if (dialogRef.value && !dialogRef.value.open) {
49
- dialogRef.value.showModal()
50
- }
54
+ emit('update:modelValue', true)
51
55
  }
52
56
 
53
57
  const closeDialog = (): void => {
54
- if (dialogRef.value && dialogRef.value.open) {
55
- dialogRef.value.close()
56
- }
58
+ emit('update:modelValue', false)
57
59
  }
58
60
 
59
61
  const handleDialogClose = (): void => {
62
+ if (!props.closable) {
63
+ if (props.modelValue) {
64
+ // not programmatically close
65
+ // re-open the dialog
66
+ nextTick(() => {
67
+ if (dialogRef.value && !dialogRef.value.open) {
68
+ dialogRef.value.showModal()
69
+ }
70
+ }) // Avoid using 'cancel' event because some browsers handle it incorrectly
71
+ return;
72
+ }
73
+ }
60
74
  if (props.modelValue) {
61
75
  emit('update:modelValue', false)
62
76
  }
63
77
  }
64
78
 
65
- watch(() => props.modelValue, async (newValue) => {
79
+ watch(() => props.modelValue, async (newValue: boolean) => {
66
80
  await nextTick()
67
81
 
68
82
  if (newValue) {
@@ -150,4 +164,8 @@ defineExpose({
150
164
  display: flex;
151
165
  flex-direction: column;
152
166
  }
167
+
168
+ ._61879ba330d9a71c {
169
+ margin-top: 0.5em;
170
+ }
153
171
  </style>
@@ -21,6 +21,10 @@
21
21
  <div class="dialog-content">
22
22
  <slot></slot>
23
23
  </div>
24
+
25
+ <div v-if="$slots.footer" class="dialog-footer">
26
+ <slot name="footer"></slot>
27
+ </div>
24
28
  </dialog>
25
29
  </template>
26
30
 
@@ -31,11 +35,13 @@ interface Props {
31
35
  modelValue: boolean
32
36
  showTitleBar?: boolean
33
37
  showCloseButton?: boolean
38
+ closable?: boolean
34
39
  }
35
40
 
36
41
  const props = withDefaults(defineProps<Props>(), {
37
42
  showTitleBar: true,
38
- showCloseButton: true
43
+ showCloseButton: true,
44
+ closable: true,
39
45
  })
40
46
 
41
47
  const emit = defineEmits<{
@@ -45,24 +51,32 @@ const emit = defineEmits<{
45
51
  const dialogRef = ref<HTMLDialogElement | null>(null)
46
52
 
47
53
  const openDialog = (): void => {
48
- if (dialogRef.value && !dialogRef.value.open) {
49
- dialogRef.value.showModal()
50
- }
54
+ emit('update:modelValue', true)
51
55
  }
52
56
 
53
57
  const closeDialog = (): void => {
54
- if (dialogRef.value && dialogRef.value.open) {
55
- dialogRef.value.close()
56
- }
58
+ emit('update:modelValue', false)
57
59
  }
58
60
 
59
61
  const handleDialogClose = (): void => {
62
+ if (!props.closable) {
63
+ if (props.modelValue) {
64
+ // not programmatically close
65
+ // re-open the dialog
66
+ nextTick(() => {
67
+ if (dialogRef.value && !dialogRef.value.open) {
68
+ dialogRef.value.showModal()
69
+ }
70
+ }) // Avoid using 'cancel' event because some browsers handle it incorrectly
71
+ return;
72
+ }
73
+ }
60
74
  if (props.modelValue) {
61
75
  emit('update:modelValue', false)
62
76
  }
63
77
  }
64
78
 
65
- watch(() => props.modelValue, async (newValue) => {
79
+ watch(() => props.modelValue, async (newValue: boolean) => {
66
80
  await nextTick()
67
81
 
68
82
  if (newValue) {
@@ -150,4 +164,8 @@ defineExpose({
150
164
  display: flex;
151
165
  flex-direction: column;
152
166
  }
167
+
168
+ .dialog-footer {
169
+ margin-top: 0.5em;
170
+ }
153
171
  </style>