first commit
This commit is contained in:
98
resources/js/composables/useAppDialog.ts
Normal file
98
resources/js/composables/useAppDialog.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
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;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user