UNPKG

@itwin/presentation-components

Version:

React components based on iTwin.js Presentation library

136 lines 6.61 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-deprecated */ /** @packageDocumentation * @module Tree */ Object.defineProperty(exports, "__esModule", { value: true }); exports.usePresentationTreeState = usePresentationTreeState; require("../../common/DisposePolyfill.js"); const react_1 = require("react"); const components_react_1 = require("@itwin/components-react"); const DataProvider_js_1 = require("../DataProvider.js"); const ReportingTreeNodeLoader_js_1 = require("../ReportingTreeNodeLoader.js"); const UseControlledTreeFiltering_js_1 = require("./UseControlledTreeFiltering.js"); const UseTreeReload_js_1 = require("./UseTreeReload.js"); /** * Custom hook that creates and manages state for [ControlledTree]($components-react) component based on presentation data. * @public * @deprecated in 5.7. All tree-related APIs have been deprecated in favor of the new generation hierarchy * building APIs (see https://github.com/iTwin/presentation/blob/33e79ee8d77f30580a9bab81a72884bda008db25/README.md#the-packages). */ function usePresentationTreeState({ onHierarchyLimitExceeded, onNodeLoaded, eventHandlerFactory, seedTreeModel, filteringParams, ...dataProviderProps }) { const firstRenderRef = (0, react_1.useRef)(true); const treeStateProps = (0, react_1.useMemo)(() => ({ ...dataProviderProps, treeModel: firstRenderRef.current ? seedTreeModel : undefined, }), Object.values(dataProviderProps)); const { state, onReload } = useTreeState({ treeStateProps, onNodeLoaded, onHierarchyLimitExceeded }); const renderedItems = (0, react_1.useRef)(undefined); /* c8 ignore next 3 */ const onItemsRendered = (0, react_1.useCallback)((items) => { renderedItems.current = items; }, []); (0, UseTreeReload_js_1.useTreeReload)({ pageSize: dataProviderProps.pagingSize, modelSource: state?.nodeLoader.modelSource, dataProviderProps: treeStateProps, ruleset: dataProviderProps.ruleset, onReload, renderedItems, }); const filteredTree = usePresentationTreeFiltering({ dataProvider: state?.nodeLoader.dataProvider, filter: filteringParams?.filter, activeMatchIndex: filteringParams?.activeMatchIndex, }); const activeNodeLoader = filteredTree?.filteredNodeLoader ?? state?.nodeLoader; const eventHandler = useEventHandler(eventHandlerFactory, activeNodeLoader); firstRenderRef.current = false; if (!activeNodeLoader || !eventHandler) { return undefined; } return { nodeLoader: activeNodeLoader, eventHandler, onItemsRendered, filteringResult: filteredTree ? { isFiltering: filteredTree.isFiltering, filteredProvider: filteredTree.filteredProvider, highlightProps: filteredTree.highlightProps, matchesCount: filteredTree.matchesCount, } : undefined, }; } function useTreeState(props) { const [state, setState] = (0, react_1.useState)(); const onNodeLoadedRef = useLatest(props.onNodeLoaded); const onHierarchyLimitExceededRef = useLatest(props.onHierarchyLimitExceeded); const prevStateRef = useLatest(state); (0, react_1.useEffect)(() => { const { treeModel, ...providerProps } = props.treeStateProps; const modelSource = new components_react_1.TreeModelSource(new components_react_1.MutableTreeModel(treeModel)); const dataProvider = new DataProvider_js_1.PresentationTreeDataProvider({ ...providerProps, onHierarchyLimitExceeded: () => onHierarchyLimitExceededRef.current?.() }); const pagedLoader = new components_react_1.PagedTreeNodeLoader(dataProvider, modelSource, providerProps.pagingSize); const nodeLoader = new ReportingTreeNodeLoader_js_1.ReportingTreeNodeLoader(pagedLoader, (nodeLoadedProps) => onNodeLoadedRef.current?.(nodeLoadedProps)); const newState = { modelSource, nodeLoader, dataProvider, }; setState(newState); return () => { // eslint-disable-next-line react-hooks/exhaustive-deps prevStateRef.current?.dataProvider[Symbol.dispose](); }; }, [props.treeStateProps, onNodeLoadedRef, onHierarchyLimitExceededRef, prevStateRef]); const onReload = (0, react_1.useCallback)((reloadedTree) => { prevStateRef.current?.dataProvider[Symbol.dispose](); const { modelSource, dataProvider } = reloadedTree; const pagedLoader = new components_react_1.PagedTreeNodeLoader(dataProvider, modelSource, dataProvider.pagingSize); const nodeLoader = new ReportingTreeNodeLoader_js_1.ReportingTreeNodeLoader(pagedLoader, (nodeLoadedProps) => onNodeLoadedRef.current?.(nodeLoadedProps)); setState({ dataProvider, nodeLoader }); }, [onNodeLoadedRef, prevStateRef]); return { state, onReload }; } function useEventHandler(factory, nodeLoader) { const [state, setState] = (0, react_1.useState)(); (0, react_1.useEffect)(() => { if (!nodeLoader) { return; } const params = { modelSource: nodeLoader.modelSource, nodeLoader }; const newHandler = factory ? factory(params) : new components_react_1.TreeEventHandler(params); setState(newHandler); return () => { newHandler?.dispose(); }; }, [factory, nodeLoader]); return state; } function usePresentationTreeFiltering({ activeMatchIndex, ...rest }) { const { filteredNodeLoader, filteredProvider, isFiltering, matchesCount } = (0, UseControlledTreeFiltering_js_1.useFilteredNodeLoader)(rest); const highlightProps = (0, UseControlledTreeFiltering_js_1.useNodeHighlightingProps)(rest.filter, filteredProvider, activeMatchIndex); return rest.filter && rest.dataProvider ? { highlightProps, filteredNodeLoader, filteredProvider, isFiltering, matchesCount, } : undefined; } function useLatest(value) { const ref = (0, react_1.useRef)(value); (0, react_1.useEffect)(() => { ref.current = value; }, [value]); return ref; } //# sourceMappingURL=UsePresentationTreeState.js.map