@microsoft/sp-webpart-base
Version:
SharePoint Framework support for building web parts
467 lines • 21.7 kB
TypeScript
import type { IA11yCheckResult } from '@msinternal/sp-a11y-checker-util';
import { DisplayMode } from '@microsoft/sp-core-library';
import type { IClientSideWebPartManifest, IAdaptiveCardExtensionManifest } from '@microsoft/sp-module-interfaces';
import type { _IPropertyPaneConsumer as IPropertyPaneConsumer, _PropertyPaneAction as PropertyPaneAction } from '@microsoft/sp-property-pane';
import type { ITopActions } from '@microsoft/sp-top-actions';
import type { IRenderProps } from '@msinternal/sp-renderable-components-base';
import BaseClientSideWebPart from './BaseClientSideWebPart';
import type IWebPartData from './IWebPartData';
import type IWebPartHost from '../components/host/IWebPartHost';
import type IWebPartManagerContext from './IWebPartManagerContext';
import WebPartContext from './WebPartContext';
import type { ITranspileContext } from './transpile/ITranspileContext';
import { WebPartIdleLoad } from './idleLoad/WebPartIdleLoad';
/**
* The ClientSideWebPartManager is expected to be the public interface to client-side web parts. Each
* host is expected to create an instance of this class and manage loading of all web parts in that host
* through that one instance. e.g. On one page, if there are multiple Canvas objects, each one could have
* one instance of this class. If the page hosts web parts without the Canvas, then the page can have an
* instance of this class. Overall this class is expected to provide the following purpose:
*
* - Orchestrates loading of one or more web parts in a host.
* - It takes care of loading web part dependencies asynchronously. Each web part loads completely
* independently of the other web parts in the host.
* - Keep a reference to all the loaded web parts and help provide bulk operations on the web parts.
* - Help manage memory leak type issues in one place.
* - Integrate the web parts with the PropertyPane and other external entities.
* - Help troubleshoot web parts during escalations.
*
* @internal
*/
export default class ClientSideWebPartManager {
/**
* Reference to the instances of all ClientSideWebPartManager instances in the app.
*/
private static readonly _webPartManagerList;
private static readonly _1PIsolatedDomainRegex;
private static readonly _logSource;
private static _manifestRequestPromiseCache;
/**
* A promise that resolves to the component responsible for managing web part prefetching.
*
* note: You must call `enablePrefetching` prior to reading this property.
*/
webPartPrefetching: WebPartIdleLoad | undefined;
/**
* Reference to the PropertyPane controller.
* Note, all instances of ClientSideWebPartManager share the same PropertyPane controller.
*/
private _propertyPane;
/**
* Dictionary of all the active web parts in this instance of the manager.
*/
private _webParts;
/**
* Host for this instance of the web part manager.
* Note, at the current time there is no support for multiple hosts and the host is not expected to change.
*/
private readonly _host;
/**
* Timer to mark the canvas dirty.
*/
private _dirtyBitTimer;
/**
* Web part status renderer instance scoped to this web part manager instance.
*/
private _statusRenderer;
/**
* Page context reference.
*/
private readonly _pageContext;
/**
* Teams apps client instance.
*/
private _deferredTeamsAppsClient;
private _toolboxTeamsAppComponentsManifests;
/**
* Promise for the async call to get edit-time web parts.
*/
private _toolboxManifestsPromise;
/**
* Promise for the async call to get edit-time AdaptiveCardExtensions
* This currently requires a separate call to a different endpoint (GetAdaptiveCardExtensions)
* When the webpart and ACE endpoints are merged, this will be removed
*/
private _toolboxACEManifestsPromise;
/**
* Promise for the async call to get edit-time Teams ACEs.
*/
private _toolboxTeamsACEManifestsPromise;
/**
* Dictionary of all the iframed web parts in this instance of the manager.
*/
private _iframedWebpartInstanceIds;
/**
* Reference to IframedWebPartController instance.
* The instance is chunked loaded for the first time in 'this.loadWebPart'
* and should be checked for existence before using.
*/
private _iframedWebPartController;
private _propertyPaneLoader;
private _propertyPaneConsumerQueue;
private _displayMode;
/**
* Create the web part tag. Web part tag is a unique tag per web part instance and is used for logging and telemetry.
*/
static createWebPartTag(manifest: IClientSideWebPartManifest<any>, instanceId: string): string;
private static _instanceOfBase;
private static _getWebPartTag;
private static _isLoadingIsolatedWebPart;
private static _getWebPartTitle;
private static _loadDynamicComponentDependencies;
/**
* Returns true if the maintenanceMode query string parameter is provided.
*/
static get isMaintenanceMode(): boolean;
/**
* Initialize the ClientSideWebPartManager.
*
* @param host - Reference to the host. A web part host is a component that is deemed capable of hosting a web
* part. Any component that implements the IWebPartHost is allowed to host a web part.
*/
constructor(host: IWebPartHost);
/**
* Enables prefetching for the specified set of web parts.
*
* @privateRemarks
* This is a prerequiste for prefetching and it does not initiate prefetching.
* You must call `prefetchWebParts` to start the prefetching process (see example below).
*
* Example:
* ```
* ClientSideWebpartManager.webPartPrefetching?.then((prefetching) =>
* prefetching.prefetchWebParts()
* );
* ```
* @param controls - The web parts to enable prefetching for.
* @beta
*/
enablePrefetching(controls: IWebPartData[]): void;
/**
* Load a web part in the provided DOM element. Does the following steps
*
* 1. Validate params.
* 2. Validate the web part manifest.
* 3. Perform an async import of the web part modules from the provided manifest
* - i.e ClientSideWebPartManager._loadComponentModules
* 4. Instantiate and initialize the web part object
* - i.e. ClientSideWebPartManager._initializeWebPart
* 5. Render the web part in the provided DOM element
* - i.e. ClientSideWebPartManager._renderWebPart
*
* If an error happens during any of the above steps, catch the error and log it.
*
* @param webPartManagerContext - web part manager context.
*/
loadWebPart(webPartManagerContext: IWebPartManagerContext): Promise<void>;
/**
* Set a IPropertyPaneConsumer object into the set of the Client-side Web Part Manager's
* managed web parts.
*
* @param id - A unique instance id.
* @param control - A component which wants to use the property Pane.
*
* @internal
*/
setPropertyPaneConsumer(id: string, control: IPropertyPaneConsumer): void;
/**
* Fetch web part manifests. This makes a REST call to load the current site's web parts into the module loader.
*
* Previously, this method only fetched WebPart manifests through a REST call to GetClientSideWebParts
* Then, an extra call to fetch AdaptiveCardExtension manifests via GetAdaptiveCardExtensions was added when MEEDashboard is enabled
*
* To consolidate these calls into a single request, we use a new endpoint, GetClientSideComponentsByComponentType
*
* If the CallGetClientSideComponentsByComponentType flight is enabled
* - call GetClientSideComponentsByComponentType(["WebPart", "AdaptiveCardExtension"]) if MEEDashboard flight enabled
* - call GetClientSideWebParts, since GetClientSideComponentsByComponentType server endpoint checks for MEEDashboard flight: Workitem 1119156
* If the CallGetClientSideComponentsByComponentType flight is disabled
* - call GetClientSideWebParts and GetAdaptiveCardExtensions if MEEDashboard flight is enabled
* - call GetClientSideWebParts, only, if MEEDashboard flight is disabled
*
* This method will also initiate fetching of Teams-connected manifests from Teams App Catalog.
*/
fetchWebPartManifests(): Promise<void>;
/**
* Get list of active web part manifests.
*
* @param includeAdaptiveCardExtensions - Include ACE manifests (casted as webpart manifests) in the returned array.
*
* @returns - array of manifests.
*/
getWebPartManifests(includeAdaptiveCardExtensions?: boolean): IClientSideWebPartManifest<unknown>[];
/**
* Get list of Adaptive Card Extension manifests.
*
* @returns - array of ACE manifests
*/
getAdaptiveCardExtensionManifests(): IAdaptiveCardExtensionManifest<unknown>[];
/**
* Set the display mode of the specified web part. If no web part id is specified, switch mode of all web parts.
* If the display mode passed is same as the current mode, no change is applied.
*
* @param displayMode - the new DisplayMode.
* @param instanceId - instance id of the web part.
*/
setDisplayMode(displayMode: DisplayMode, instanceId?: string): void;
/**
* @remarks
* Only use this API if you need to immediately call property pane APIs after switching the mode.
*
* @internal
*/
_setDisplayMode(displayMode: DisplayMode, instanceId?: string): Promise<void>;
/**
* Serialize the specified web part. If no web part is specified, serialize all web parts.
*
* @param instanceId - instance id of the web part.
*/
serialize(instanceId?: string): Map<string, IWebPartData | undefined>;
/**
* Set the web part data for the specified web part using data that is not persisted.
*
* _Warning: This method can throw and Promise.catch will not catch it. You should wrap the usage in a try/catch._
*
* @param webPartData - the new webPartData.
* @param instanceId - instance id of the web part.
* @returns - A promise that resolves immediately.
*/
setWebPartData(webPartData: IWebPartData, instanceId: string): Promise<void>;
/**
* Set the web part data for the specified web part.
*
* The setWebPartData API has 3 possible scenarios when the web part data is updated externally.
* - Web part declares useFallbackWhenPropertiesUpdatedExternally manifest field as `true`, web part manager will
* trigger the default fallback logic which disposes the web part and reload it using the given context.
* - Web part overrides `onAfterPropertiesUpdatedExternally` life cycle events, web part manager will first
* deserialize the web part data, then invokes the `onAfterPropertiesUpdatedExternally` event to allow web part to
* do their customized handling logic.
* - If useFallbackWhenPropertiesUpdatedExternally manifest field is `false` or `undefined`, and web part does not
* override `onAfterPropertiesUpdatedExternally` life cycle events, web part manager will first deserialize the
* web part data, then invokes the `_refresh` life cycle to re-render the web part.
*
* _Warning: This method can throw and Promise.catch will not catch it. You should wrap the usage in a try/catch._
*
* @param context - the new context.
* @param instanceId - instance id of the web part.
* @param shouldFallback - whether it should fallback to dispose & reload logic.
* @returns - A promise that resolves immediately if fallback is not used, or returns the loadWebPart promise
* when fallback is used.
*/
setWebPartData(context: IWebPartManagerContext, instanceId: string, shouldFallback?: boolean): Promise<void>;
/**
* Dispose of the current webpart manager and all of the webparts it has loaded.
*/
dispose(): void;
/**
* Dispose the specified web part. If no web part is specified, dispose all web parts.
*
* @param instanceId - instance id of the web part.
*/
disposeWebparts(instanceId?: string): void;
tryGeneratePreviewImageUrl(instanceIds?: string[]): string | undefined;
/**
* Gets the top action configuration for the webpart with the specified instanceId
* @param instanceId - the specified instanceId
* @returns undefined if the webpart isn't loaded yet or the webpart doesn't support top actions.
*/
getWebpartTopActions(instanceId: string): ITopActions | undefined;
/**
* Gets the accessibility results for the webpart with the specified instanceId
* @param instanceId - the specified instanceId
* @returns undefined if the webpart isn't loaded yet or the webpart doesn't support accessibility assistant.
*/
getWebpartA11yResult(instanceId: string): Promise<(IA11yCheckResult | undefined)[]>;
/**
* Calls the preOnClickA11yResult method for the webpart with the specified instanceId
* to help users redirect to the specific item editing configuration pane to fix the accessibility issues.
* @param result - the accessibility result to be passed to the webpart
*/
preOnClickA11yResult(result: IA11yCheckResult): void;
/**
* Request property pane or content panel to perform the given action.
*
* @param instanceId - web part instance id.
* @param propertyPaneAction - indicates what action needs to be performed on the property pane.
* @param renderedByWebPart - indicates whether the the property pane rendered by a web part or not.
* @param context - pass additional context to property pane
*/
requestPropertyPaneAction(instanceId: string, propertyPaneAction?: PropertyPaneAction, renderedByWebPart?: boolean, context?: any): void;
/**
* Returns true if the current property pane or content panel source is a web part and not the Canvas or any other source.
*/
isPropertyPaneRenderedByWebPart(): boolean;
/**
* Returns the state of the PropertyPane if it is open or not.
* Also true if Property Pane is rendered by Content Panel.
*
* @param instanceId - optional param to check isopen based on the supported consumer (content panel or property pane).
* see IConfigurableOptionsController.isOpen(instanceId) for more details
*/
isPropertyPaneOpen(instanceId?: string): boolean;
/**
* Returns the state of the ContentPanel if it is open or not.
* Returns true if the Content Panel is open, regardless if the Content Panel is rendering the property pane.
*/
isContentPanelOpen(): boolean;
/**
* Method to handle the web part delete action from the host. There is a key distinction between delete and dispose.
* Delete implies that the web part has been deleted from the page and the web part should dispose all the server
* side or other external resources attached to the web part. Dispose implies that an in-place navigation is
* happening and the web part manager should delete the web part from its cache.
*
* @param instanceId - instance id of the webpart which is deleted.
*/
onWebPartDelete(instanceId: string): void;
/**
* Render an error message in the web part container div. Also logs the error message to the IWebPartHost logger.
*/
renderError(domElement: HTMLElement, error: Error): void;
/**
* Notify webparts that their container has resized.
*
* @param instanceId - if specified only notify one webpart that its container has resized
*/
notifyWebPartContainerResize(instanceId?: string): void;
/**
* Notify web parts to check dirty bit without waiting for dirty bit timer to run.
* @see ClientSideWebPartManager._startDirtyBitTimer for more details about the dirty bit timer.
*/
notifyWebPartsSetDirtyBit(): void;
/**
* Used to ensure the next request for webpart manifests makes a call to the server.
*/
clearManifestPromise(): void;
/**
* Find the render props for the web part with the given instance id.
* @param webPartManagerContext - web part manager context.
* @param request - transpile context.
* @returns render props for the web part.
*
* @internal
*/
getWebPartTranspileRenderProps(webPartManagerContext: IWebPartManagerContext, request: ITranspileContext): Promise<IRenderProps[]>;
/**
* Find the instance of the web part with the given instance id within the manager instance.
* @param instanceId - Instance Id of the web part
* @returns Instance of the web part, if it exists in this manager.
*
* @internal
*/
getWebPartByInstanceId(instanceId: string): BaseClientSideWebPart<unknown & {}> | undefined;
/** ------------------- PROTECTED ------------------- **/
/**
* Generate web part context.
*/
protected _getWebPartContext(context: IWebPartManagerContext): WebPartContext;
/** ------------------- PRIVATE ------------------- **/
private _getLoadedWebPart;
/**
* Load a web part in the provided DOM element. Does the following steps
*
* 1. Validate params.
* 2. Validate the web part manifest.
* 3. Perform an async import of the web part modules from the provided manifest
* - i.e ClientSideWebPartManager._loadComponentModules
* 4. Instantiate and initialize the web part object
* - i.e. ClientSideWebPartManager._initializeWebPart
* 5. Render the web part in the provided DOM element
* - i.e. ClientSideWebPartManager._renderWebPart
*
* If an error happens during any of the above steps, catch the error and log it.
*
* @param webPartManagerContext - web part manager context.
*/
private _loadWebPartOld;
private _isIsolatedWebPart;
private _isACE;
private _isPrefab;
/**
* Load a web part in the provided DOM element. Does the following steps
*
* 1. Validate params.
* 2. Validate the web part manifest.
* 3. Perform an async import of the web part modules from the provided manifest
* - i.e ClientSideWebPartManager._loadComponentModules
* 4. Instantiate and initialize the web part object
* - i.e. ClientSideWebPartManager._initializeWebPart
*
* If an error happens during any of the above steps, catch the error and log it.
*
* @param webPartManagerContext - web part manager context.
*/
private _loadAndInitWebPart;
private _initializeWebPart;
private _fetchManifestsWithCache;
private _fetchAdaptiveCardExtensionManifests;
private _fetchTeamsACEManifests;
private _clearManifestCacheItem;
/**
* Workaround for a server issue - disambiguate manifest locales if they haven't already been disambiguated
* (VSO#243888) tracks fixing this issue.
*/
private _disambiguateWebPartManifestLocales;
private _loadIsolatedWebPart;
private _waitForTeamsAppSync;
private _loadComponentModules;
/**
* Execute the provided callback for the list of provided web part ids. If no list if provided,
* execute the callback on all web parts.
*/
private _executeForIdsOrAll;
/**
* This is a temporary implementation of updating the host that a web part has updated properties.
* Currently we run a timer that regularly checks for updated properties and raises the dirty bit
* handler to the host. todo (VSO SPPPLAT#200728) tracks fixing this scenario in a better way.
*/
private _startDirtyBitTimer;
private _notifyWebPartsSetDirtyBit;
private _deleteWebPart;
/**
* Get web part manifest instance from manifest. Promotes the pre-configured entries.
*/
private _getManifestInstance;
/**
* If non-non parameter passed, return array else return undefined.
*/
private _getArrayOrUndefined;
private _initialzeOnResizeEventHandler;
/**
* Window onresize event handler.
*/
private _onContainerResize;
/**
* Listener for window post message that the property pane.
*
* todo (SPPPLAT Bug #299413): Implement missing schema for property pane post messages
* todo (SPPPLAT PBI #687467): Refactor IframedWebPartContoller
*/
private _onPropertyPaneNotifications;
private _renderWebPart;
private _loadPropertyPaneModule;
private _getDataUpdatedEventName;
/**
* Registers a component as a property pane consumer.
* @param instanceId - Instance id of the consumer, to be registered with the property pane.
*/
private _registerWebPartAsPropertyPaneConsumer;
private _registerPendingPropertyPaneConsumers;
private _closeIsolatedPropertyPaneIfRequired;
/**
* Load the fabric core library, for third-party web parts if required.
* @param context - Current context of the web part manager
*/
private _loadLegacyFabricCssIfRequired;
private get _isDebugSession();
/**
* Loads the property pane module asynchronously, if not already loaded.
*/
private _loadPropertyPaneModuleOld;
private _validateIfWPIsNotDisposed;
private _swapManifestForWebparts;
private _doesUserHasPermissions;
private get _teamsAppsClient();
private _isTitleAreaBannerWebPart;
private _loadWebPartPrefetching;
}
//# sourceMappingURL=ClientSideWebPartManager.d.ts.map