45 lines
2.2 KiB
TypeScript
45 lines
2.2 KiB
TypeScript
// Императивный вызов модалки подтверждения из любого места (в т.ч. из обычных
|
|
// модулей вроде shared/unsavedChanges.ts, где нет React-контекста).
|
|
//
|
|
// Модалка живёт в React-дереве (ConfirmHost, монтируется один раз в
|
|
// RequestPortal). Здесь — только «мостик»: confirmModal(...) отдаёт промис,
|
|
// который резолвится, когда пользователь нажмёт «Продолжить»/«Отмена».
|
|
|
|
export interface IConfirmOptions {
|
|
/** Заголовок окна. */
|
|
title?: string;
|
|
/** Основной текст-вопрос. */
|
|
message: string;
|
|
/** Подпись подтверждающей кнопки. По умолчанию — «Продолжить». */
|
|
confirmText?: string;
|
|
/** Подпись кнопки отмены. По умолчанию — «Отмена». */
|
|
cancelText?: string;
|
|
/** Опасное действие (потеря данных) — подтверждающая кнопка красная. */
|
|
danger?: boolean;
|
|
}
|
|
|
|
type ConfirmHandler = (opts: IConfirmOptions, resolve: (ok: boolean) => void) => void;
|
|
|
|
// Единственный подписчик — смонтированный ConfirmHost. Больше одного окна
|
|
// подтверждения одновременно нам не нужно.
|
|
let handler: ConfirmHandler | undefined;
|
|
|
|
export function registerConfirmHost(fn: ConfirmHandler): () => void {
|
|
handler = fn;
|
|
return () => {
|
|
if (handler === fn) handler = undefined;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Показать модальное подтверждение. Промис резолвится в true («Продолжить») или
|
|
* false («Отмена»/Esc/клик по фону). Если хост почему-то не смонтирован —
|
|
* падаем на нативный confirm, чтобы не потерять защиту от потери данных.
|
|
*/
|
|
export function confirmModal(opts: IConfirmOptions): Promise<boolean> {
|
|
if (!handler) {
|
|
return Promise.resolve(window.confirm(opts.message));
|
|
}
|
|
return new Promise<boolean>((resolve) => handler!(opts, resolve));
|
|
}
|