UNPKG

@itwin/presentation-components

Version:

React components based on iTwin.js Presentation library

122 lines 5.53 kB
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