diff --git a/package-lock.json b/package-lock.json index 1d9759a..4ddd072 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,7 @@ "vue-loader": "^17.0.1", "vue-recaptcha-v3": "^2.0.1", "vue-router": "^4.1.6", - "vue3-easy-data-table": "^1.5.24", - "vue3-promise-dialog": "^0.3.4" + "vue3-easy-data-table": "^1.5.24" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.48.1", @@ -4220,14 +4219,6 @@ "vue": "^3.2.45" } }, - "node_modules/vue3-promise-dialog": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/vue3-promise-dialog/-/vue3-promise-dialog-0.3.4.tgz", - "integrity": "sha512-JquYYE+1lxuGgncD8Q+8KTFAWUJsNWnhuYPSsOFRKzz3kz66Rjz5pdlEW6GLfUlV3cKak9T8b3mV49B4ouEgVg==", - "peerDependencies": { - "vue": "^3.x" - } - }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index 81ff680..20e525e 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "vue-loader": "^17.0.1", "vue-recaptcha-v3": "^2.0.1", "vue-router": "^4.1.6", - "vue3-easy-data-table": "^1.5.24", - "vue3-promise-dialog": "^0.3.4" + "vue3-easy-data-table": "^1.5.24" } } diff --git a/resources/css/app.scss b/resources/css/app.scss index c52b998..9242313 100644 --- a/resources/css/app.scss +++ b/resources/css/app.scss @@ -95,3 +95,24 @@ code { } } } + +/* SM Dialog */ +.sm-dialog-outer { + position: fixed; + display: flex; + top: 0; + left: 0; + bottom: 0; + right: 0; + flex-direction: column; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 1rem; +} + +.sm-dialog-outer:last-of-type { + background-color: rgba(0, 0, 0, 0.4); + backdrop-filter: blur(2px); + -webkit-backdrop-filter: blur(2px); +} diff --git a/resources/js/components/SMDialog.ts b/resources/js/components/SMDialog.ts new file mode 100644 index 0000000..d1ba1ff --- /dev/null +++ b/resources/js/components/SMDialog.ts @@ -0,0 +1,114 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + AllowedComponentProps, + Component, + defineComponent, + shallowReactive, + VNodeProps, +} from "vue"; + +export interface DialogInstance { + comp?: any; + dialog: Component; + wrapper: string; + props: unknown; + resolve: (data: unknown) => void; +} +const dialogRefs = shallowReactive([]); + +export default defineComponent({ + name: "SMDialogList", + template: ` +
+
+ +
+
+ `, + data() { + const dialogRefList = dialogRefs; + + return { + name: "default", + transitionAttrs: {}, + dialogRefList, + }; + }, +}); + +/** + * Closes last opened dialog, resolving the promise with the return value of the dialog, or with the given + * data if any. + * + * @param {unknown} data The dialog return value. + */ +export function closeDialog(data?: unknown) { + if (dialogRefs.length <= 1) { + document.getElementsByTagName("html")[0].style.overflow = ""; + document.getElementsByTagName("body")[0].style.overflow = ""; + } + + const lastDialog = dialogRefs.pop(); + if (data === undefined) { + data = lastDialog.comp.returnValue(); + } + lastDialog.resolve(data); +} + +/** + * Extracts the type of props from a component definition. + */ +type PropsType = C extends new (...args: any) => any + ? Omit< + InstanceType["$props"], + keyof VNodeProps | keyof AllowedComponentProps + > + : never; + +/** + * Extracts the return type of the dialog from the setup function. + */ +type BindingReturnType = C extends new ( + ...args: any +) => any + ? InstanceType extends { returnValue: () => infer Y } + ? Y + : never + : never; + +/** + * Extracts the return type of the dialog either from the setup method or from the methods. + */ +type ReturnType = BindingReturnType; + +/** + * Opens a dialog. + * + * @param {Component} dialog The dialog you want to open. + * @param {PropsType} props The props to be passed to the dialog. + * @param {string} wrapper The dialog wrapper you want the dialog to open into. + * @returns {Promise} A promise that resolves when the dialog is closed + */ +export function openDialog( + dialog: C, + props?: PropsType, + wrapper: string = "default" +): Promise> { + if (dialogRefs.length === 0) { + document.getElementsByTagName("html")[0].style.overflow = "hidden"; + document.getElementsByTagName("body")[0].style.overflow = "hidden"; + } + + return new Promise((resolve) => { + dialogRefs.push({ + dialog, + props, + wrapper, + resolve, + }); + }); +} diff --git a/resources/js/components/SMInput.vue b/resources/js/components/SMInput.vue index ba64435..330d68c 100644 --- a/resources/js/components/SMInput.vue +++ b/resources/js/components/SMInput.vue @@ -88,7 +88,7 @@ - - diff --git a/resources/js/components/dialogs/SMDialogChangePassword.vue b/resources/js/components/dialogs/SMDialogChangePassword.vue index 0a4769d..9b54b26 100644 --- a/resources/js/components/dialogs/SMDialogChangePassword.vue +++ b/resources/js/components/dialogs/SMDialogChangePassword.vue @@ -1,32 +1,27 @@