Files
laravel-gost-template/resources/js/composables/useAppDialog.ts
2026-06-24 17:20:43 +09:00

99 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { nextTick, ref } from 'vue';
/**
* Очередь подтверждающих диалогов с поддержкой async-onConfirm и анимаций.
* Перенесено из проекта onboard (Composables/useAppDialog.js).
*
* Использование:
* const ok = await useAppDialog({ title: 'Удалить?', content: '...' })
*/
export interface AppDialogButtonProps {
type?: 'default' | 'primary' | 'info' | 'success' | 'warning' | 'error';
secondary?: boolean;
[key: string]: unknown;
}
export interface AppDialogItem {
id: number;
show: boolean;
title?: string;
content?: string;
loading: boolean;
onConfirm?: () => unknown | Promise<unknown>;
positiveText?: string;
negativeText?: string;
positiveProps?: AppDialogButtonProps;
negativeProps?: AppDialogButtonProps;
maskClosable?: boolean;
resolve: (confirmed: boolean) => void;
}
export interface AppDialogOptions {
title?: string;
content?: string;
positiveText?: string;
negativeText?: string;
positiveProps?: AppDialogButtonProps;
negativeProps?: AppDialogButtonProps;
maskClosable?: boolean;
onConfirm?: () => unknown | Promise<unknown>;
}
export const dialogQueue = ref<AppDialogItem[]>([]);
let idCounter = 0;
/** Закрытие диалога (кнопка / Esc / клик по маске). */
export function closeDialog(id: number, confirmed = false): void {
const dialog = dialogQueue.value.find((d) => d.id === id);
if (dialog && dialog.show) {
dialog.show = false;
dialog.resolve(confirmed);
}
}
/** Удаление из очереди после завершения leave-анимации. */
export function cleanupDialog(id: number): void {
dialogQueue.value = dialogQueue.value.filter((d) => d.id !== id);
}
export function useAppDialog(options: AppDialogOptions = {}): Promise<boolean> {
const {
title,
content,
positiveProps,
negativeProps,
positiveText = 'Подтвердить',
negativeText = 'Отмена',
maskClosable = false,
onConfirm,
} = options;
return new Promise<boolean>((resolve) => {
const id = idCounter++;
dialogQueue.value.push({
id,
show: false,
title,
content,
loading: false,
onConfirm,
positiveText,
negativeText,
positiveProps,
negativeProps,
maskClosable,
resolve,
});
nextTick(() => {
const dialog = dialogQueue.value.find((d) => d.id === id);
if (dialog) {
dialog.show = true;
}
});
});
}