UNPKG

@microsoft/sp-dialog

Version:

SharePoint Framework support for displaying dialog boxes

302 lines (291 loc) 13.8 kB
/** * 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 { }