@microsoft/sp-dialog
Version:
SharePoint Framework support for displaying dialog boxes
302 lines (291 loc) • 13.8 kB
TypeScript
/**
* SharePoint Framework support for displaying pop-up dialog boxes.
*
* @remarks
* This library provides simple stock dialogs such as {@link Dialog.alert}
* and {@link Dialog.prompt}, along with a general framework for building
* custom dialog boxes that participate in the focus management system for
* SharePoint Framework applications.
*
* @packagedocumentation
*/
import type { Guid } from '@microsoft/sp-core-library';
/**
* The base class for implementing dialogs in SharePoint Framework. This provides a supported way for showing
* dialogs to the user inside SharePoint Framework components.
*
* @remarks
* Extend this class to create dialogs for SharePoint Framework. By following the guidelines in implementation,
* the framework can ensure that the dialogs are shown in a user-friendly manner. While the content of the dialog is
* controlled by this class by implementing the render method, the framework can decide when to show the dialog and
* how to render the overlay and modal. The application on the page can also have control on allowing dialogs to show.
* Refer to the documentation of the individual methods and properties to learn more about how to extend and use this
* class.
*
* @public
*/
export declare abstract class BaseDialog {
private static readonly _logSource;
private _closedWhileRendering;
private _config;
private _domElement;
private _isSecondary;
private _renderPromise;
private _requestId;
private _secondaryDialogProvider;
private _state;
/**
* Constructor for the `BaseDialog` class.
* @remarks
*
* It is important to keep the constructor lightweight. Use `onBeforeOpen()` for doing heavy-weight initialization
* that is needed for rendering the dialog such as resource allocations and asynchronous calls to fetch data. You
* can use the constructor to set initial parameters of your dialog such as references to resources in your
* application. The reason for this is that dialogs are usually constructed upon a UI event e.g. a button click,
* but the dialog may not always be shown right after construction. Keeping the constructor lightweight ensures
* smooth user experience and avoids doing throw-away work in case the dialog is not shown later e.g. if
* the framework rejects it. Another benefit of doing this is avoiding memory leaks by doing all the allocations and
* disposals in symmetric `onBeforeOpen()` and `onAfterClose()` events. If you allocate resources in the
* constructor, you have a memory leak because there is no guarantee onAfterClose() will get called,
* and onAfterClose() is your only opportunity to dispose.
*
* Example:
* ```
* constructor(cacheReference: any) {
* super();
*
* this._cache = cacheReference; // This is okay. Keeping a reference to my internal cache.
* this._cache.refresh(); // This is bad practice.
* // If you need to refresh the cache (or fetch data) for rendering, do it in onBeforeOpen()
* }
* ```
*
* @param config - the dialog configuration that affects how the dialog is displayed *
*/
constructor(config?: IDialogConfiguration);
/* Excluded from this release type: _configuration */
/**
* If the dialog is a secondary dialog. This means that there is another dialog hidden behind this dialog.
*/
get isSecondary(): boolean;
/**
* If the dialog is visually open. This returns true during onBeforeOpen() because there is a visual component.
* It returns false when the dialog is hidden.
*/
get isOpen(): boolean;
/**
* If the dialog is visually hidden.
*
* @remarks
* This happens when the dialog goes behind a secondary dialog.
* Note that this is different from closed, because the dialog still has the permission to show and will
* eventually unhide. This returns false if the dialog is closed.
*/
get isHidden(): boolean;
/**
* An active dialog is permitted to show a secondary dialog on top of itself. By design, only two layers of
* dialogs are permitted.
*
* @remarks
* Secondary dialogs do not have to wait for permission and will immediately be shown or rejected. All calls to
* show a secondary dialog reject while there is already a secondary dialog showing.
* This property may be undefined if a secondary dialog is not available i.e. the current dialog is secondary itself
* or the dialog is not active.
*/
get secondaryDialogProvider(): ISecondaryDialogProvider | undefined;
/**
* Request the framework to show this dialog.
*
* @returns A promise that resolves once the dialog is successfully closed (after being shown).
* The promise rejects if the request is rejected or aborted.
*
* @param options - Dialog showing options. See {@link IDialogShowOptions} for more information.
*/
show(options?: IDialogShowOptions): Promise<void>;
/**
* Close the dialog.
*
* @remarks
* This will void the permission to show for this dialog. Every dialog should have a mechanism to
* eventually close to avoid blocking the user interface. If called on an inactive dialog it will abort the request
* to show.
*
* @returns A promise that resolves when the dialog is visually closed, or if it was already closed
*/
close(): Promise<void>;
/* Excluded from this release type: _render */
/* Excluded from this release type: _setState */
/* Excluded from this release type: _requestAck */
/**
* Renders the contents of the dialog.
*
* @remarks
* The `render` method must be implemented to render the content of the dialog in the container element provided
* by the framework. Use `this.domElement` to access this container. The container is inside a modal rendered
* in the center of the page on top of a dark overlay.
*
* The render method is called once after the modal element is created and opened. It is recommended to
* use `onBeforeOpen()` for doing non-UI operations for your rendering that might take a long time. This
* will ensure that the framework can show a friendly UI such as a spinner to let the user know that the
* dialog is being prepared. If you choose to do your initialization or other costly operations inside render
* method, make sure to have a friendly UI so the user is informed about the state of your dialog. Otherwise,
* an empty element is shown to the user which is a bad user experience practice.
*/
protected abstract render(): void;
/**
* Use this property to access the container element provided by the framework for rendering.
*
* @remarks
* See {@link BaseDialog.render} for more information on rendering.
*/
protected get domElement(): HTMLElement;
/**
* This method is called before the render method and can be overridden to make preparations for rendering.
* The loading indicator is displayed during the lifetime of this method.
* virtual
* @remarks
* All resource allocations in onBeforeOpen() should be properly disposed in `onAfterClose()` to a avoid memory leak.
*
* @returns A promise that resolves when the operations are done and the dialog is ready to render. If the
* promise is rejected, the dialog will not be rendered and `onAfterClose()` will not be called.
*/
protected onBeforeOpen(): Promise<void>;
/**
* This method is called after the dialog is visually closed and gives an opportunity for doing clean up.
* @remarks
* The dialog lifecycle completes after closing and there should be no resources left inside the object. Even though
* the dialog may be revived again for a new lifecycle using show() method, this is considered a whole new lifecycle
* that should reallocate its own resources. If there are any resources that you would like to keep for multiple
* lifecycles, consider allocating it outside the dialog object and passing its reference to the dialog constructor.
*/
protected onAfterClose(): void;
/**
* A dialog is active if it is in one of these states:
* - The framework has approved to show it and has started the opening process
* - It is open and showing
* - It is visually hidden behind a secondary dialog
*
* When a dialog is active, the framework considers that dialog to have permission to show until it is closed.
*/
private get _isActive();
}
/**
* A static class for showing stock dialogs such as an alert or prompt.
*
* @public
*/
export declare class Dialog {
/**
* Alerts a message to the user with a user-friendly interface. Calling this method sends a request to application
* to show the alert dialog.
*
* @remarks
* There might be a delay until the dialog is approved and shown by the application, for
* example, if there is another dialog currently being shown. The returned promise resolves when the dialog is
* successfully shown and closed. The promise rejects if the application rejects the request for any reason.
*
* @param message - The message to alert
*/
static alert(message: string, options?: IAlertOptions): Promise<void>;
/**
* Prompts the user for a string value with a user-friendly interface. Calling this method sends a request to
* application to show the dialog.
*
* @remarks
* There might be a delay until the dialog is approved and shown by the application,
* for example, if there is another dialog currently being shown. The returned promise resolves when the dialog is
* successfully shown and closed. The promise rejects if the application rejects the request for any reason.
*
* @returns The input string or undefined if the dialog was canceled
*
* @param message - The message for prompt dialog
*/
static prompt(message: string, options?: IPromptOptions): Promise<string | undefined>;
}
/* Excluded from this release type: DialogState */
/**
* Options for showing an alert dialog
*
* @public
*/
export declare interface IAlertOptions extends IDialogShowOptions {
}
/**
* The interface for dialog configuration
* @public
*/
export declare interface IDialogConfiguration {
/**
* Whether the dialog can be closed by clicking outside the dialog (on the overlay).
*/
isBlocking?: boolean;
}
/**
* Options for showing a dialog
*
* @public
*/
export declare interface IDialogShowOptions {
/**
* A callback that is invoked immediately before the dialog receives focus.
*
* @remarks
* Provide this callback if there is a case when you want to abort showing the dialog before it's approved
* by the framework. For example, you can check if a long time has passed since the request was made or the
* the component requesting the dialog is disposed and you don't want to show the dialog anymore. It is
* important to keep this callback lightweight so the framework can resolve it quickly and the user interface
* does not have to wait a long time for it.
*/
confirmOpen?: () => boolean;
}
/**
* Options for showing a prompt dialog
*
* @public
*/
export declare interface IPromptOptions extends IDialogShowOptions {
/**
* The default value for the input text field of prompt dialog
*/
defaultValue?: string;
}
/**
* This interface handles calls to show a secondary dialog. It's only available by calling
* this.secondaryManagerProvider inside a dialog.
*
* @remarks
* Secondary dialogs do not need to request permission from dialog manager, because the primary dialog
* already has permission. Therefore, the secondary dialog will be immediately shown. This causes the primary dialog
* to hide until the secondary dialog is closed. There can be only one secondary dialog at a time. Additional requests
* to show more secondary dialogs are rejected.
*
* See {@link BaseDialog.secondaryDialogProvider} for how to use this.
*
* @public
*/
export declare interface ISecondaryDialogProvider {
/**
* Similar to {@link Dialog.alert}. The only difference is that the dialog is immediately shown
* if there are no other secondary dialogs. Otherwise, the promise rejects.
*
* @param options - Dialog showing options. See {@link IDialogShowOptions} for more information.
*/
alert(message: string, options?: IAlertOptions): Promise<void>;
/**
* Similar to {@link Dialog.prompt}. The only difference is that the dialog is immediately shown
* if there are no other secondary dialogs. Otherwise, the promise rejects.
*
* @param options - Dialog showing options. The confirmOpen option will be ignored.
* See {@link IDialogShowOptions} for more information.
*/
prompt(message: string, options?: IPromptOptions): Promise<string | undefined>;
/**
* Similar to {@link BaseDialog.show}. The dialog to show is passed in as parameter and the dialog is immediately
* shown if there are no other secondary dialogs. Otherwise, the promise rejects.
*
* @param options - Dialog showing options. The confirmOpen option will be ignored.
* See {@link IDialogShowOptions} for more information.
*/
show(dialog: BaseDialog, options?: IDialogShowOptions): Promise<void>;
}
export { }