diff --git a/src/assets/css/tailwind.css b/src/assets/css/tailwind.css index 0465b94..893cf9d 100644 --- a/src/assets/css/tailwind.css +++ b/src/assets/css/tailwind.css @@ -34,3 +34,5 @@ --radius-default: var(--radius); } + +@source inline('{bg,text,border}-{red,blue,green,yellow}-{50,{100..900..100},950}'); diff --git a/src/stores/App/overlay.store.ts b/src/stores/App/overlay.store.ts new file mode 100644 index 0000000..c92801a --- /dev/null +++ b/src/stores/App/overlay.store.ts @@ -0,0 +1,122 @@ +import { defineStore } from "pinia"; +import { ref, type Ref, onUnmounted } from "vue"; +import { CreateShortCutKey } from "dolphin-components"; + +class EscapeKeyManager { + private static instance: EscapeKeyManager; + private modalStack: Array<() => void> = []; + private shortcutHandler: { destroy: () => void } | null = null; + + static getInstance(): EscapeKeyManager { + if (!EscapeKeyManager.instance) { + EscapeKeyManager.instance = new EscapeKeyManager(); + } + return EscapeKeyManager.instance; + } + + addModal(closeCallback: () => void) { + this.modalStack.push(closeCallback); + + if (this.modalStack.length === 1) { + this.setupEscapeKey(); + } + } + + removeModal(closeCallback: () => void) { + const index = this.modalStack.indexOf(closeCallback); + if (index > -1) { + this.modalStack.splice(index, 1); + } + + if (this.modalStack.length === 0) { + this.cleanupEscapeKey(); + } + } + + private setupEscapeKey() { + if (!this.shortcutHandler) { + this.shortcutHandler = CreateShortCutKey("escape", () => { + if (this.modalStack.length > 0) { + const topModalClose = this.modalStack[this.modalStack.length - 1]; + if (typeof topModalClose == "function") { + topModalClose(); + } + } + }); + } + } + + private cleanupEscapeKey() { + if (this.shortcutHandler) { + this.shortcutHandler.destroy(); + this.shortcutHandler = null; + } + } +} + +export const createOverlayStore = (storeId: string) => { + return defineStore(storeId, () => { + const show = ref(false); + const editId = ref(null); + const context = ref>({}); + const escapeManager = EscapeKeyManager.getInstance(); + let onCloseCallback: (() => void) | null = null; + + function open(options: { id?: number | string; context?: Record } = {}) { + editId.value = options.id ?? null; + context.value = { + ...context.value, + ...(options.context || {}), + }; + show.value = true; + + escapeManager.addModal(close); + } + + function close() { + if (onCloseCallback) { + onCloseCallback(); + } + + show.value = false; + editId.value = null; + escapeManager.removeModal(close); + } + + async function onSave( + genericStore: any, + genericAPI: any, + fetchList: boolean = true, + loadingRef: Ref | null = null + ) { + let response: any = false; + if (editId.value !== null) { + response = await genericStore.updateItem(genericAPI, editId.value, fetchList, loadingRef); + } else { + response = await genericStore.createItem(genericAPI, fetchList, loadingRef); + } + if (response) close(); + return response; + } + + onUnmounted(() => { + if (show.value) { + escapeManager.removeModal(close); + } + }); + + function setOnCloseCallback(callback: () => void) { + onCloseCallback = callback; + } + + return { + show, + editId, + context, + open, + close, + onSave, + setOnCloseCallback, + }; + }); +};