using Microsoft.AspNetCore.Components; namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared; /// /// Centralised dialog/modal service. Pages inject this service and call /// , , or /// programmatically instead of embedding /// per-page modal components. A single DialogHost rendered in /// MainLayout displays the resulting dialog state. /// public interface IDialogService { /// /// Shows a confirmation dialog and resolves to true when the user /// confirms, or false when the user cancels (button click, Escape, /// or backdrop dismiss). /// /// Modal title text. /// Body text shown to the user. /// When true, the confirm button renders in /// btn-danger styling with the label "Delete"; otherwise a primary /// "Confirm" button is shown. /// A task that resolves to true when the user confirms, or false when cancelled. Task ConfirmAsync(string title, string message, bool danger = false); /// /// Shows a single-line text prompt and resolves to the entered value, or /// null if the user cancels. /// /// Modal title text. /// Label rendered above the input field. /// Pre-populated value for the input field. /// Optional placeholder shown when the input is empty. /// A task that resolves to the entered string, or null if the user cancels. Task PromptAsync(string title, string label, string initialValue = "", string? placeholder = null); /// /// Shows a modal hosting arbitrary custom body content and resolves to the /// value the body closes with, or default (null for reference /// types) if the user cancels (the body's own cancel path, the header close /// button, or Escape). The body fragment receives a /// 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. /// /// The type the body closes the dialog with. /// Modal title text. /// Renders the modal body; receives the context whose /// Close/Cancel methods resolve the returned task. /// Optional Bootstrap modal-dialog size modifier applied to /// the modal-dialog element (e.g. modal-lg, modal-sm). /// null leaves the default width. /// A task that resolves to the value passed to /// , or default on cancel. Task ShowAsync(string title, RenderFragment> body, string? size = null); } /// /// Handed to the body fragment of a /// dialog so the body can close itself with a typed result or cancel. Both /// methods route back through the owning to complete /// the awaited ShowAsync task and tear down the modal. /// /// The type the dialog resolves with. public sealed class DialogContext { // 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 _resolve; /// /// Creates a context bound to the given resolve callback. The callback boxes /// the result and forwards it to . /// /// Invoked with the boxed result (null = cancel). internal DialogContext(Action resolve) => _resolve = resolve; /// /// Closes the dialog and resolves the awaited ShowAsync task with /// . /// /// The value the caller awaits. public void Close(TResult result) => _resolve(result); /// /// Cancels the dialog and resolves the awaited ShowAsync task with /// default (null for reference types). /// public void Cancel() => _resolve(null); }