@itwin/presentation-frontend
Version:
Frontend of iModel.js Presentation library
583 lines • 29.2 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Core
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PresentationManager = void 0;
const core_bentley_1 = require("@itwin/core-bentley");
const core_frontend_1 = require("@itwin/core-frontend");
const presentation_common_1 = require("@itwin/presentation-common");
const internal_1 = require("@itwin/presentation-common/internal");
const unified_selection_1 = require("@itwin/unified-selection");
const IModelConnectionInitialization_js_1 = require("./IModelConnectionInitialization.js");
const InternalSymbols_js_1 = require("./InternalSymbols.js");
const IpcRequestsHandler_js_1 = require("./IpcRequestsHandler.js");
const LocalizationHelper_js_1 = require("./LocalizationHelper.js");
const RulesetManager_js_1 = require("./RulesetManager.js");
const RulesetVariablesManager_js_1 = require("./RulesetVariablesManager.js");
const StreamedResponseGenerator_js_1 = require("./StreamedResponseGenerator.js");
/**
* Frontend Presentation manager which basically just forwards all calls to
* the backend implementation.
*
* @public
*/
class PresentationManager {
_requestsHandler;
_rulesets;
_localizationHelper;
_explicitActiveUnitSystem;
_rulesetVars;
_clearEventListener;
_schemaContextProvider;
// eslint-disable-next-line @typescript-eslint/no-deprecated
_defaultFormats;
_ipcRequestsHandler;
/**
* An event raised when hierarchies created using specific ruleset change.
*
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
// eslint-disable-next-line @typescript-eslint/no-deprecated
onIModelHierarchyChanged = new core_bentley_1.BeEvent();
/**
* An event raised when content created using specific ruleset changes
*/
onIModelContentChanged = new core_bentley_1.BeEvent();
/**
* Get / set active unit system used to format property values with units.
*
* @deprecated in 4.0 - will not be removed until after 2026-06-13. `IModelApp.quantityFormatter` should be used to get/set the active unit system. At the moment
* [[PresentationManager]] allows overriding it, but returns `IModelApp.quantityFormatter.activeUnitSystem` if override
* is not set.
*/
get activeUnitSystem() {
return this._explicitActiveUnitSystem ?? core_frontend_1.IModelApp.quantityFormatter.activeUnitSystem;
}
set activeUnitSystem(value) {
this._explicitActiveUnitSystem = value;
}
constructor(props) {
if (props) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
this._explicitActiveUnitSystem = props.activeUnitSystem;
}
this._requestsHandler =
props?.rpcRequestsHandler ??
new internal_1.RpcRequestsHandler(props ? { clientId: props.clientId, timeout: props.requestTimeout } : undefined);
this._rulesetVars = new Map();
this._rulesets = RulesetManager_js_1.RulesetManagerImpl.create();
this._localizationHelper = new LocalizationHelper_js_1.FrontendLocalizationHelper(props?.activeLocale);
// eslint-disable-next-line @typescript-eslint/no-deprecated
this._schemaContextProvider = props?.schemaContextProvider ?? ((imodel) => imodel.schemaContext);
// eslint-disable-next-line @typescript-eslint/no-deprecated
this._defaultFormats = props?.defaultFormats;
if (core_frontend_1.IpcApp.isValid) {
// Ipc only works in ipc apps, so the `onUpdate` callback will only be called there.
this._clearEventListener = core_frontend_1.IpcApp.addListener(internal_1.PresentationIpcEvents.Update, this.onUpdate);
this._ipcRequestsHandler = props?.ipcRequestsHandler ?? new IpcRequestsHandler_js_1.IpcRequestsHandler(this._requestsHandler.clientId);
}
}
/** Get / set active locale used for localizing presentation data */
get activeLocale() {
return this._localizationHelper.locale;
}
set activeLocale(locale) {
this._localizationHelper.locale = locale;
}
[Symbol.dispose]() {
if (this._clearEventListener) {
this._clearEventListener();
this._clearEventListener = undefined;
}
}
/** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
/* c8 ignore next 3 */
dispose() {
this[Symbol.dispose]();
}
onUpdate = (_evt, report) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.handleUpdateAsync(report);
};
/** @note This is only called in native apps after changes in iModels */
async handleUpdateAsync(report) {
for (const imodelKey in report) {
/* c8 ignore next 3 */
if (!report.hasOwnProperty(imodelKey)) {
continue;
}
const imodelReport = report[imodelKey];
for (const rulesetId in imodelReport) {
/* c8 ignore next 3 */
if (!imodelReport.hasOwnProperty(rulesetId)) {
continue;
}
const updateInfo = imodelReport[rulesetId];
if (updateInfo.content) {
this.onIModelContentChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.content, imodelKey });
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
if (updateInfo.hierarchy) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
this.onIModelHierarchyChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.hierarchy, imodelKey });
}
}
}
}
/**
* Create a new PresentationManager instance
* @param props Optional properties used to configure the manager
*/
static create(props) {
return new PresentationManager(props);
}
/** @internal */
get [InternalSymbols_js_1._presentation_manager_rpcRequestsHandler]() {
return this._requestsHandler;
}
/** @internal */
get [InternalSymbols_js_1._presentation_manager_ipcRequestsHandler]() {
return this._ipcRequestsHandler;
}
/**
* Get rulesets manager
*/
rulesets() {
return this._rulesets;
}
/**
* Get ruleset variables manager for specific ruleset
* @param rulesetId Id of the ruleset to get the vars manager for
*/
vars(rulesetId) {
if (!this._rulesetVars.has(rulesetId)) {
const varsManager = new RulesetVariablesManager_js_1.RulesetVariablesManagerImpl(rulesetId, this._ipcRequestsHandler);
this._rulesetVars.set(rulesetId, varsManager);
}
return this._rulesetVars.get(rulesetId);
}
toRpcTokenOptions(requestOptions) {
// 1. put default `locale` and `unitSystem`
// 2. put all `requestOptions` members (if `locale` or `unitSystem` are set, they'll override the defaults put at #1)
// 3. put `imodel` of type `IModelRpcProps` which overwrites the `imodel` from `requestOptions` put at #2
const defaultOptions = {};
if (this.activeLocale) {
defaultOptions.locale = this.activeLocale;
}
defaultOptions.unitSystem = this.activeUnitSystem; // eslint-disable-line @typescript-eslint/no-deprecated
const { imodel, rulesetVariables, ...rpcRequestOptions } = requestOptions;
return {
...defaultOptions,
...rpcRequestOptions,
...(rulesetVariables ? { rulesetVariables: rulesetVariables.map(presentation_common_1.RulesetVariable.toJSON) } : {}),
imodel: imodel.getRpcProps(),
};
}
async addRulesetAndVariablesToOptions(options) {
const { rulesetOrId, rulesetVariables } = options;
let foundRulesetOrId;
if (typeof rulesetOrId === "object") {
foundRulesetOrId = rulesetOrId;
}
else {
const foundRuleset = await this._rulesets.get(rulesetOrId);
foundRulesetOrId = foundRuleset ? foundRuleset.toJSON() : rulesetOrId;
}
const rulesetId = typeof foundRulesetOrId === "object" ? foundRulesetOrId.id : foundRulesetOrId;
// All Id64Array variable values must be sorted for serialization to JSON to work. RulesetVariablesManager
// sorts them before storing, so that part is taken care of, but we need to ensure that variables coming from
// request options are also sorted.
const variables = (rulesetVariables ?? []).map((variable) => {
if (variable.type === presentation_common_1.VariableValueTypes.Id64Array) {
return { ...variable, value: core_bentley_1.OrderedId64Iterable.sortArray(variable.value) };
}
return variable;
});
if (!this._ipcRequestsHandler) {
// only need to add variables from variables manager if there's no IPC
// handler - if there is one, the variables are already known by the backend
variables.push(...this.vars(rulesetId).getAllVariables());
}
return { ...options, rulesetOrId: foundRulesetOrId, rulesetVariables: variables };
}
/* eslint-disable @typescript-eslint/no-deprecated */
/**
* Returns an iterator that polls nodes asynchronously.
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
async getNodesIterator(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({ ...options });
const generator = new StreamedResponseGenerator_js_1.StreamedResponseGenerator({
...requestOptions,
getBatch: async (paging) => {
const result = await this._requestsHandler.getPagedNodes({ ...rpcOptions, paging });
return {
total: result.total,
items: this._localizationHelper.getLocalizedNodes(result.items),
};
},
});
return generator.createAsyncIteratorResponse();
}
/**
* Retrieves nodes.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getNodesIterator]] instead.
*/
async getNodes(requestOptions) {
const result = await this.getNodesIterator(requestOptions);
return collect(result.items);
}
/**
* Retrieves nodes count.
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
async getNodesCount(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({ ...options });
return this._requestsHandler.getNodesCount(rpcOptions);
}
/**
* Retrieves total nodes count and a single page of nodes.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getNodesIterator]] instead.
*/
async getNodesAndCount(requestOptions) {
const result = await this.getNodesIterator(requestOptions);
return {
count: result.total,
nodes: await collect(result.items),
};
}
/**
* Retrieves hierarchy level descriptor.
* @public
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
async getNodesDescriptor(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
try {
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({ ...options });
const result = await this._requestsHandler.getNodesDescriptor(rpcOptions);
const descriptor = presentation_common_1.Descriptor.fromJSON(result);
return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
}
finally {
await (0, IModelConnectionInitialization_js_1.ensureIModelInitialized)(requestOptions.imodel);
}
}
/**
* Retrieves paths from root nodes to children nodes according to specified keys. Intersecting paths will be merged.
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
async getNodePaths(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({ ...options });
const result = await this._requestsHandler.getNodePaths(rpcOptions);
return result.map((npe) => this._localizationHelper.getLocalizedNodePathElement(npe));
}
/**
* Retrieves paths from root nodes to nodes containing filter text in their label.
* @deprecated in 5.2 - will not be removed until after 2026-10-01. Use the new [@itwin/presentation-hierarchies](https://github.com/iTwin/presentation/blob/master/packages/hierarchies/README.md)
* package for creating hierarchies.
*/
async getFilteredNodePaths(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const result = await this._requestsHandler.getFilteredNodePaths(this.toRpcTokenOptions(options));
return result.map((npe) => this._localizationHelper.getLocalizedNodePathElement(npe));
}
/* eslint-enable @typescript-eslint/no-deprecated */
/**
* Get information about the sources of content when building it for specific ECClasses. Sources involve classes of the primary select instance,
* its related instances for loading related and navigation properties.
* @public
*/
async getContentSources(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const rpcOptions = this.toRpcTokenOptions(requestOptions);
const result = await this._requestsHandler.getContentSources(rpcOptions);
return result.sources.map((sourceJson) => presentation_common_1.SelectClassInfo.fromCompressedJSON(sourceJson, result.classesMap));
}
/** Retrieves the content descriptor which describes the content and can be used to customize it. */
async getContentDescriptor(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
try {
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({
...options,
keys: stripTransientElementKeys(options.keys).toJSON(),
});
const result = await this._requestsHandler.getContentDescriptor(rpcOptions);
const descriptor = presentation_common_1.Descriptor.fromJSON(result);
return descriptor ? this._localizationHelper.getLocalizedContentDescriptor(descriptor) : undefined;
}
finally {
await (0, IModelConnectionInitialization_js_1.ensureIModelInitialized)(requestOptions.imodel);
}
}
/** Retrieves overall content set size. */
async getContentSetSize(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = this.toRpcTokenOptions({
...options,
descriptor: getDescriptorOverrides(requestOptions.descriptor),
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
});
return this._requestsHandler.getContentSetSize(rpcOptions);
}
async getContentIteratorInternal(requestOptions) {
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const firstPageSize = options.batchSize ?? requestOptions.paging?.size;
const rpcOptions = this.toRpcTokenOptions({
...options,
descriptor: getDescriptorOverrides(requestOptions.descriptor),
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
omitFormattedValues: true,
...(firstPageSize ? { paging: { ...requestOptions.paging, size: firstPageSize } } : undefined),
});
let contentFormatter;
if (!requestOptions.omitFormattedValues) {
const schemaContext = this._schemaContextProvider(requestOptions.imodel);
const unitSystem = requestOptions.unitSystem ?? this._explicitActiveUnitSystem ?? core_frontend_1.IModelApp.quantityFormatter.activeUnitSystem;
const koqPropertyFormatter = new presentation_common_1.KoqPropertyValueFormatter({
schemaContext,
formatsProvider: core_frontend_1.IModelApp.formatsProvider,
});
koqPropertyFormatter.defaultFormats = this._defaultFormats;
contentFormatter = new internal_1.ContentFormatter(new internal_1.ContentPropertyValueFormatter(koqPropertyFormatter), unitSystem);
}
let descriptor = requestOptions.descriptor instanceof presentation_common_1.Descriptor ? requestOptions.descriptor : undefined;
let firstPage;
if (!descriptor) {
const firstPageResponse = await this._requestsHandler.getPagedContent(rpcOptions);
if (!firstPageResponse?.descriptor || !firstPageResponse.contentSet) {
return undefined;
}
descriptor = presentation_common_1.Descriptor.fromJSON(firstPageResponse?.descriptor);
firstPage = firstPageResponse?.contentSet;
}
/* c8 ignore next 3 */
if (!descriptor) {
return undefined;
}
descriptor = this._localizationHelper.getLocalizedContentDescriptor(descriptor);
const getPage = async (paging, requestIndex) => {
let contentSet = requestIndex === 0 ? firstPage : undefined;
contentSet ??= await this._requestsHandler.getPagedContentSet({ ...rpcOptions, paging });
let items = contentSet.items.map((x) => presentation_common_1.Item.fromJSON(x)).filter((x) => x !== undefined);
if (contentFormatter) {
items = await contentFormatter.formatContentItems(items, descriptor);
}
items = this._localizationHelper.getLocalizedContentItems(items);
return {
total: contentSet.total,
items,
};
};
const generator = new StreamedResponseGenerator_js_1.StreamedResponseGenerator({
...requestOptions,
getBatch: getPage,
});
return {
...(await generator.createAsyncIteratorResponse()),
descriptor,
};
}
/** Retrieves a content descriptor, item count and async generator for the items themselves. */
async getContentIterator(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const response = await this.getContentIteratorInternal(requestOptions);
if (!response) {
return undefined;
}
await (0, IModelConnectionInitialization_js_1.ensureIModelInitialized)(requestOptions.imodel);
return response;
}
/**
* Retrieves content which consists of a content descriptor and a page of records.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getContentIterator]] instead.
*/
async getContent(requestOptions) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return (await this.getContentAndSize(requestOptions))?.content;
}
/**
* Retrieves content set size and content which consists of a content descriptor and a page of records.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getContentIterator]] instead.
*/
async getContentAndSize(requestOptions) {
const response = await this.getContentIterator(requestOptions);
if (!response) {
return undefined;
}
const { descriptor, total } = response;
const items = await collect(response.items);
return {
content: new presentation_common_1.Content(descriptor, items),
size: total,
};
}
/** Returns an iterator that asynchronously polls distinct values of specific field from the content. */
async getDistinctValuesIterator(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = {
...this.toRpcTokenOptions(options),
descriptor: getDescriptorOverrides(options.descriptor),
keys: stripTransientElementKeys(options.keys).toJSON(),
};
const generator = new StreamedResponseGenerator_js_1.StreamedResponseGenerator({
...requestOptions,
getBatch: async (paging) => {
const response = await this._requestsHandler.getPagedDistinctValues({ ...rpcOptions, paging });
return {
total: response.total,
items: response.items.map((x) => this._localizationHelper.getLocalizedDisplayValueGroup(x)),
};
},
});
return generator.createAsyncIteratorResponse();
}
/**
* Retrieves distinct values of specific field from the content.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getDistinctValuesIterator]] instead.
*/
async getPagedDistinctValues(requestOptions) {
const result = await this.getDistinctValuesIterator(requestOptions);
return {
total: result.total,
items: await collect(result.items),
};
}
/**
* Retrieves property data in a simplified format for a single element specified by ID.
* @public
*/
async getElementProperties(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const { elementId, contentParser, ...optionsNoElementId } = requestOptions;
const parser = contentParser ?? internal_1.buildElementProperties;
const iter = await this.getContentIterator({
...optionsNoElementId,
descriptor: {
displayType: presentation_common_1.DefaultContentDisplayTypes.PropertyPane,
contentFlags: presentation_common_1.ContentFlags.ShowLabels,
},
rulesetOrId: "ElementProperties",
keys: new presentation_common_1.KeySet([{ className: "BisCore:Element", id: elementId }]),
});
if (!iter || iter.total === 0) {
return undefined;
}
return parser(iter.descriptor, (await iter.items.next()).value);
}
/**
* Retrieves content item instance keys.
* @public
*/
async getContentInstanceKeys(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
const rpcOptions = {
...this.toRpcTokenOptions(options),
keys: stripTransientElementKeys(options.keys).toJSON(),
};
const generator = new StreamedResponseGenerator_js_1.StreamedResponseGenerator({
...requestOptions,
getBatch: async (page) => {
const keys = await this._requestsHandler.getContentInstanceKeys({ ...rpcOptions, paging: page });
return {
total: keys.total,
items: keys.items.instanceKeys.reduce((instanceKeys, entry) => {
for (const id of core_bentley_1.CompressedId64Set.iterable(entry[1])) {
instanceKeys.push({ className: entry[0], id });
}
return instanceKeys;
}, new Array()),
};
},
});
const { total, items } = await generator.createAsyncIteratorResponse();
return {
total,
async *items() {
yield* items;
},
};
}
/** Retrieves display label definition of specific item. */
async getDisplayLabelDefinition(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
const result = await this._requestsHandler.getDisplayLabelDefinition(rpcOptions);
return this._localizationHelper.getLocalizedLabelDefinition(result);
}
/** Retrieves display label definition of specific items. */
async getDisplayLabelDefinitionsIterator(requestOptions) {
(0, IModelConnectionInitialization_js_1.startIModelInitialization)(requestOptions.imodel);
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
const generator = new StreamedResponseGenerator_js_1.StreamedResponseGenerator({
...requestOptions,
getBatch: async (page) => {
const partialKeys = !page.start ? rpcOptions.keys : rpcOptions.keys.slice(page.start);
const result = await this._requestsHandler.getPagedDisplayLabelDefinitions({ ...rpcOptions, keys: partialKeys });
result.items = this._localizationHelper.getLocalizedLabelDefinitions(result.items);
return result;
},
});
return generator.createAsyncIteratorResponse();
}
/**
* Retrieves display label definition of specific items.
* @deprecated in 4.5 - will not be removed until after 2026-06-13. Use [[getDisplayLabelDefinitionsIterator]] instead.
*/
async getDisplayLabelDefinitions(requestOptions) {
const { items } = await this.getDisplayLabelDefinitionsIterator(requestOptions);
return collect(items);
}
}
exports.PresentationManager = PresentationManager;
const getDescriptorOverrides = (descriptorOrOverrides) => {
if (descriptorOrOverrides instanceof presentation_common_1.Descriptor) {
return descriptorOrOverrides.createDescriptorOverrides();
}
return descriptorOrOverrides;
};
const stripTransientElementKeys = (keys) => {
if (!keys.some((key) => presentation_common_1.Key.isInstanceKey(key) && key.className === unified_selection_1.TRANSIENT_ELEMENT_CLASSNAME)) {
return keys;
}
const copy = new presentation_common_1.KeySet();
copy.add(keys, (key) => {
// the callback is not going to be called with EntityProps as KeySet converts them
// to InstanceKeys, but we want to keep the EntityProps case for correctness
/* c8 ignore next 3 */
const isTransient = (presentation_common_1.Key.isInstanceKey(key) && key.className === unified_selection_1.TRANSIENT_ELEMENT_CLASSNAME) ||
(presentation_common_1.Key.isEntityProps(key) && key.classFullName === unified_selection_1.TRANSIENT_ELEMENT_CLASSNAME);
return !isTransient;
});
return copy;
};
async function collect(iter) {
const result = new Array();
for await (const value of iter) {
result.push(value);
}
return result;
}
//# sourceMappingURL=PresentationManager.js.map