@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
122 lines • 5.53 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module PropertyGrid
*/
import { createContext, useContext, useEffect, useState } from "react";
import { from, map, Subject, switchMap, takeLast } from "rxjs";
import { KeySet } from "@itwin/presentation-common";
import { createIModelKey } from "@itwin/presentation-core-interop";
import { Presentation, SelectionHandler } from "@itwin/presentation-frontend";
import { createKeySetFromSelectables, safeDispose } from "../common/Utils.js";
const DEFAULT_REQUESTED_CONTENT_INSTANCES_LIMIT = 100;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const SelectionHandlerContext = createContext(undefined);
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-deprecated
export function SelectionHandlerContextProvider({ selectionHandler, children }) {
return _jsx(SelectionHandlerContext.Provider, { value: selectionHandler, children: children });
}
/** @internal */
export function useSelectionHandlerContext() {
return useContext(SelectionHandlerContext);
}
/**
* A React hook that adds unified selection functionality to the provided data provider.
* @public
*/
export function usePropertyDataProviderWithUnifiedSelection(props) {
const { dataProvider, selectionStorage } = props;
const { imodel, rulesetId } = dataProvider;
const requestedContentInstancesLimit = props.requestedContentInstancesLimit ?? DEFAULT_REQUESTED_CONTENT_INSTANCES_LIMIT;
const [numSelectedElements, setNumSelectedElements] = useState(0);
const suppliedSelectionHandler = useSelectionHandlerContext();
useEffect(() => {
function onSelectionChanged(newSelection) {
setNumSelectedElements(newSelection.size);
dataProvider.keys = isOverLimit(newSelection.size, requestedContentInstancesLimit) ? new KeySet() : newSelection;
}
if (selectionStorage) {
return initUnifiedSelectionFromStorage({ imodel, selectionStorage, onSelectionChanged });
}
return initUnifiedSelectionFromPresentationFrontend({
imodel,
rulesetId,
suppliedSelectionHandler,
onSelectionChanged,
});
}, [dataProvider, imodel, rulesetId, requestedContentInstancesLimit, suppliedSelectionHandler, selectionStorage]);
return { isOverLimit: isOverLimit(numSelectedElements, requestedContentInstancesLimit), numSelectedElements };
}
function initUnifiedSelectionFromStorage({ imodel, selectionStorage, onSelectionChanged, }) {
const imodelKey = createIModelKey(imodel);
const update = new Subject();
const subscription = update
.pipe(map((level) => selectionStorage.getSelection({ imodelKey, level })), switchMap(async (selectables) => createKeySetFromSelectables(selectables)))
.subscribe({
next: onSelectionChanged,
});
const removeSelectionChangesListener = selectionStorage.selectionChangeEvent.addListener((args) => {
const isMyIModel = args.imodelKey === imodelKey;
isMyIModel && update.next(args.level);
});
from(selectionStorage.getSelectionLevels({ imodelKey }))
.pipe(takeLast(1))
.subscribe({
next: (level) => update.next(level),
});
return () => {
removeSelectionChangesListener();
subscription.unsubscribe();
};
}
function initUnifiedSelectionFromPresentationFrontend({ suppliedSelectionHandler, imodel, rulesetId, onSelectionChanged, }) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const updateProviderSelection = (selectionHandler, selectionLevel) => {
const selection = getSelectedKeys(selectionHandler, selectionLevel);
selection && onSelectionChanged(selection);
};
/* c8 ignore start */
const handler = suppliedSelectionHandler ??
// eslint-disable-next-line @typescript-eslint/no-deprecated
new SelectionHandler({
// eslint-disable-next-line @typescript-eslint/no-deprecated
manager: Presentation.selection,
name: "PropertyGrid",
imodel,
rulesetId,
});
/* c8 ignore end */
// eslint-disable-next-line @typescript-eslint/no-deprecated
handler.onSelect = (evt) => {
updateProviderSelection(handler, evt.level);
};
updateProviderSelection(handler);
return () => {
safeDispose(handler);
};
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
function getSelectedKeys(selectionHandler, selectionLevel) {
if (undefined === selectionLevel) {
const availableLevels = selectionHandler.getSelectionLevels();
if (0 === availableLevels.length) {
return undefined;
}
selectionLevel = availableLevels[availableLevels.length - 1];
}
for (let i = selectionLevel; i >= 0; i--) {
const selection = selectionHandler.getSelection(i);
if (!selection.isEmpty) {
return new KeySet(selection);
}
}
return new KeySet();
}
function isOverLimit(numSelectedElements, limit) {
return numSelectedElements > limit;
}
//# sourceMappingURL=UseUnifiedSelection.js.map