UNPKG

@itwin/presentation-hierarchies-react

Version:

React components based on `@itwin/presentation-hierarchies`

128 lines 5.83 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { useEffect, useState } from "react"; import { assert } from "@itwin/core-bentley"; import { HierarchyNode } from "@itwin/presentation-hierarchies"; import { Selectables } from "@itwin/unified-selection"; import { useUnifiedSelectionStorage } from "../UnifiedSelectionContext.js"; import { isTreeModelHierarchyNode } from "./TreeModel.js"; /** @internal */ export function useUnifiedTreeSelection({ sourceName, selectionStorage, getTreeModelNode, createSelectableForGenericNode, }) { const [options, setOptions] = useState(() => ({ isNodeSelected: /* c8 ignore next */ () => false, selectNodes: /* c8 ignore next */ () => { }, })); const deprecatedSelectionStorage = useUnifiedSelectionStorage(); selectionStorage ??= deprecatedSelectionStorage; createSelectableForGenericNode ??= defaultCreateSelectableForGenericNode; useEffect(() => { if (!selectionStorage) { // TODO: make selectionStorage prop required setOptions({ isNodeSelected: () => false, selectNodes: () => { }, }); return; } setOptions(createOptions(sourceName, selectionStorage, createSelectableForGenericNode, getTreeModelNode)); return selectionStorage.selectionChangeEvent.addListener((args) => { if (args.level > 0) { return; } setOptions(createOptions(sourceName, selectionStorage, createSelectableForGenericNode, getTreeModelNode)); }); }, [selectionStorage, createSelectableForGenericNode, getTreeModelNode, sourceName]); return options; } const defaultCreateSelectableForGenericNode = (node, treeModelNodeId) => ({ identifier: treeModelNodeId, data: node, async *loadInstanceKeys() { }, }); function createOptions(source, storage, createSelectableForGenericNode, getNode) { return { isNodeSelected: (nodeId) => { const node = getNode(nodeId); if (!node || !isTreeModelHierarchyNode(node)) { return false; } return Object.entries(groupNodeSelectablesByIModelKey(node, createSelectableForGenericNode)).some(([imodelKey, nodeSelectables]) => { const storageSelectables = storage.getSelection({ imodelKey, level: 0 }); return Selectables.hasAny(storageSelectables, nodeSelectables); }); }, selectNodes: (nodeIds, changeType) => { const imodelSelectables = {}; for (const nodeId of nodeIds) { const node = getNode(nodeId); if (!node || !isTreeModelHierarchyNode(node)) { return; } Object.entries(groupNodeSelectablesByIModelKey(node, createSelectableForGenericNode)).forEach(([imodelKey, nodeSelectables]) => { let selectablesList = imodelSelectables[imodelKey]; if (!selectablesList) { selectablesList = []; imodelSelectables[imodelKey] = selectablesList; } nodeSelectables.forEach((selectable) => selectablesList.push(selectable)); }); } Object.entries(imodelSelectables).forEach(([imodelKey, selectables]) => { const actionProps = { imodelKey, source, selectables, level: 0 }; switch (changeType) { case "add": storage.addToSelection(actionProps); return; case "remove": storage.removeFromSelection(actionProps); return; case "replace": storage.replaceSelection(actionProps); return; } }); }, }; } function groupNodeSelectablesByIModelKey(modelNode, createSelectableForGenericNode) { const hierarchyNode = modelNode.nodeData; if (HierarchyNode.isInstancesNode(hierarchyNode)) { return groupIModelInstanceKeys(hierarchyNode.key.instanceKeys); } if (HierarchyNode.isGroupingNode(hierarchyNode)) { return Object.entries(groupIModelInstanceKeys(hierarchyNode.groupedInstanceKeys)).reduce((imodelSelectables, [imodelKey, instanceKeys]) => ({ ...imodelSelectables, [imodelKey]: [ { identifier: modelNode.id, data: hierarchyNode, async *loadInstanceKeys() { for (const key of instanceKeys) { yield key; } }, }, ], }), {}); } assert(HierarchyNode.isGeneric(hierarchyNode)); return { // note: generic nodes aren't associated with an imodel [""]: [createSelectableForGenericNode(hierarchyNode, modelNode.id)], }; } function groupIModelInstanceKeys(instanceKeys) { return instanceKeys.reduce((imodelSelectables, key) => { const imodelKey = key.imodelKey ?? ""; let selectablesList = imodelSelectables[imodelKey]; if (!selectablesList) { selectablesList = []; imodelSelectables[imodelKey] = selectablesList; } selectablesList.push(key); return imodelSelectables; }, {}); } //# sourceMappingURL=UseUnifiedSelection.js.map