feat(centralui): DialogHost ShowAsync<T> custom-content + focus trap/restore + backdrop hook (T33a)
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Centralised dialog/modal service. Pages inject this service and call
|
||||
/// <see cref="ConfirmAsync"/> or <see cref="PromptAsync"/> programmatically
|
||||
/// instead of embedding per-page modal components. A single <c>DialogHost</c>
|
||||
/// rendered in <c>MainLayout</c> displays the resulting dialog state.
|
||||
/// <see cref="ConfirmAsync"/>, <see cref="PromptAsync"/>, or
|
||||
/// <see cref="ShowAsync{TResult}"/> programmatically instead of embedding
|
||||
/// per-page modal components. A single <c>DialogHost</c> rendered in
|
||||
/// <c>MainLayout</c> displays the resulting dialog state.
|
||||
/// </summary>
|
||||
public interface IDialogService
|
||||
{
|
||||
@@ -31,4 +34,60 @@ public interface IDialogService
|
||||
/// <param name="placeholder">Optional placeholder shown when the input is empty.</param>
|
||||
/// <returns>A task that resolves to the entered string, or <c>null</c> if the user cancels.</returns>
|
||||
Task<string?> PromptAsync(string title, string label, string initialValue = "", string? placeholder = null);
|
||||
|
||||
/// <summary>
|
||||
/// Shows a modal hosting arbitrary custom body content and resolves to the
|
||||
/// value the body closes with, or <c>default</c> (<c>null</c> for reference
|
||||
/// types) if the user cancels (the body's own cancel path, the header close
|
||||
/// button, or Escape). The body fragment receives a
|
||||
/// <see cref="DialogContext{TResult}"/> and supplies its own action buttons —
|
||||
/// the standard Cancel/Confirm footer is NOT rendered for this kind. Use this
|
||||
/// to centralise modal chrome (backdrop, focus trap, focus restoration) while
|
||||
/// keeping page-specific form content inside the body.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type the body closes the dialog with.</typeparam>
|
||||
/// <param name="title">Modal title text.</param>
|
||||
/// <param name="body">Renders the modal body; receives the context whose
|
||||
/// <c>Close</c>/<c>Cancel</c> methods resolve the returned task.</param>
|
||||
/// <param name="size">Optional Bootstrap modal-dialog size modifier applied to
|
||||
/// the <c>modal-dialog</c> element (e.g. <c>modal-lg</c>, <c>modal-sm</c>).
|
||||
/// <c>null</c> leaves the default width.</param>
|
||||
/// <returns>A task that resolves to the value passed to
|
||||
/// <see cref="DialogContext{TResult}.Close"/>, or <c>default</c> on cancel.</returns>
|
||||
Task<TResult?> ShowAsync<TResult>(string title, RenderFragment<DialogContext<TResult>> body, string? size = null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handed to the body fragment of a <see cref="IDialogService.ShowAsync{TResult}"/>
|
||||
/// dialog so the body can close itself with a typed result or cancel. Both
|
||||
/// methods route back through the owning <see cref="DialogService"/> to complete
|
||||
/// the awaited <c>ShowAsync</c> task and tear down the modal.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type the dialog resolves with.</typeparam>
|
||||
public sealed class DialogContext<TResult>
|
||||
{
|
||||
// Routes the close back to the owning service's Resolve(). Held as a typed
|
||||
// delegate rather than a service reference so the context stays a small,
|
||||
// self-contained closure handle and never widens the body's surface.
|
||||
private readonly Action<object?> _resolve;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a context bound to the given resolve callback. The callback boxes
|
||||
/// the result and forwards it to <see cref="DialogService.Resolve"/>.
|
||||
/// </summary>
|
||||
/// <param name="resolve">Invoked with the boxed result (<c>null</c> = cancel).</param>
|
||||
internal DialogContext(Action<object?> resolve) => _resolve = resolve;
|
||||
|
||||
/// <summary>
|
||||
/// Closes the dialog and resolves the awaited <c>ShowAsync</c> task with
|
||||
/// <paramref name="result"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The value the caller awaits.</param>
|
||||
public void Close(TResult result) => _resolve(result);
|
||||
|
||||
/// <summary>
|
||||
/// Cancels the dialog and resolves the awaited <c>ShowAsync</c> task with
|
||||
/// <c>default</c> (<c>null</c> for reference types).
|
||||
/// </summary>
|
||||
public void Cancel() => _resolve(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user