Skip to content

Commit 0dda93b

Browse files
authored
Tree widget: Expose focused instances context provider (#1175)
* Expose `FocusedInstancesContextProvider` and `useFocusedInstancesContext` * change
1 parent f43e284 commit 0dda93b

File tree

9 files changed

+72
-32
lines changed

9 files changed

+72
-32
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "Expose `FocusedInstancesContextProvider` and `useFocusedInstancesContext` to allow using `ModelsTreeComponent.ToggleInstancesFocusButton` from outside of `ModelsTreeComponent` and accesing the context from other React components.",
4+
"packageName": "@itwin/tree-widget-react",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

packages/itwin/tree-widget/api/tree-widget-react.api.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,19 @@ export class FilterLimitExceededError extends Error {
156156
readonly limit: number;
157157
}
158158

159+
// @public (undocumented)
160+
interface FocusedInstancesContext {
161+
enabled: boolean;
162+
loadFocusedItems?: () => AsyncIterableIterator<InstanceKey | GroupingHierarchyNode>;
163+
toggle: () => void;
164+
}
165+
166+
// @public
167+
export function FocusedInstancesContextProvider({ selectionStorage, imodelKey, children, }: PropsWithChildren<{
168+
selectionStorage: SelectionStorage;
169+
imodelKey: string;
170+
}>): JSX.Element;
171+
159172
// @beta (undocumented)
160173
type FunctionProps<THook extends (props: any) => any> = Parameters<THook>[0];
161174

@@ -485,6 +498,9 @@ interface UseCategoriesTreeResult {
485498
rendererProps: Required<Pick<VisibilityTreeRendererProps, "getIcon" | "getSublabel">>;
486499
}
487500

501+
// @public
502+
export function useFocusedInstancesContext(): FocusedInstancesContext;
503+
488504
// @beta
489505
export function useModelsTree({ activeView, filter, hierarchyConfig, visibilityHandlerOverrides, getFilteredPaths, onModelsFiltered, selectionPredicate: nodeTypeSelectionPredicate, }: UseModelsTreeProps): UseModelsTreeResult;
490506

packages/itwin/tree-widget/api/tree-widget-react.exports.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public;const;CategoriesTreeComponent
44
public;function;createTreeWidget
55
beta;const;ExternalSourcesTreeComponent
66
beta;class;FilterLimitExceededError
7+
public;function;FocusedInstancesContextProvider
78
beta;interface;HierarchyVisibilityHandler
89
beta;const;IModelContentTreeComponent
910
public;const;ModelsTreeComponent
@@ -18,6 +19,7 @@ public;function;TreeWidgetComponent
1819
beta;function;TreeWithHeader
1920
beta;function;useCategoriesTree
2021
public;function;useCategoriesTreeButtonProps
22+
public;function;useFocusedInstancesContext
2123
beta;function;useModelsTree
2224
public;function;useModelsTreeButtonProps
2325
beta;interface;VisibilityStatus

packages/itwin/tree-widget/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"copy:cjs": "cpx \"./src/**/*.{scss,json}\" ./lib/cjs",
3939
"copy:esm": "cpx \"./src/**/*.{scss,json}\" ./lib/esm",
4040
"cover": "c8 npm run test",
41-
"extract-api": "betools extract-api --entry=tree-widget-react --apiReportFolder=./api --apiReportTempFolder=./api/temp --apiSummaryFolder=./api --includeUnexportedApis",
41+
"extract-api": "betools extract-api --entry=lib/esm/tree-widget-react --apiReportFolder=./api --apiReportTempFolder=./api/temp --apiSummaryFolder=./api --includeUnexportedApis",
4242
"check-internal": "node ../../../scripts/checkInternal.js --apiSummary ./api/tree-widget-react.api.md",
4343
"lint": "npm run lint:eslint && npm run lint:stylelint",
4444
"lint:eslint": "eslint -f visualstudio \"./src/**/*.{ts,tsx}\" 1>&2",

packages/itwin/tree-widget/src/test/trees/common/FocusedInstancesContext.test.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55

66
import { expect } from "chai";
77
import { createStorage } from "@itwin/unified-selection";
8-
import { useFocusedInstancesContext } from "../../../tree-widget-react/components/trees/common/FocusedInstancesContext.js";
9-
import { FocusedInstancesContextProvider } from "../../../tree-widget-react/components/trees/common/FocusedInstancesContextProvider.js";
8+
import { FocusedInstancesContextProvider, useFocusedInstancesContext } from "../../../tree-widget-react/components/trees/common/FocusedInstancesContext.js";
109
import { act, createAsyncIterator, renderHook, waitFor } from "../../TestUtils.js";
1110

1211
import type { GroupingHierarchyNode } from "@itwin/presentation-hierarchies";

packages/itwin/tree-widget/src/tree-widget-react/components/trees/common/FocusedInstancesContext.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,48 @@
33
* See LICENSE.md in the project root for license terms and full copyright notice.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { useEffect, useState } from "react";
6+
import { createContext, useContext, useEffect, useState } from "react";
77
import { HierarchyNode } from "@itwin/presentation-hierarchies-react";
88
import { Selectable, Selectables } from "@itwin/unified-selection";
9-
import { focusedInstancesContext } from "./FocusedInstancesContext.js";
109

11-
import type { SelectionStorage } from "@itwin/presentation-hierarchies-react";
1210
import type { PropsWithChildren } from "react";
13-
import type { InstanceKey } from "@itwin/presentation-common";
14-
import type { FocusedInstancesContext } from "./FocusedInstancesContext.js";
1511
import type { GroupingHierarchyNode } from "@itwin/presentation-hierarchies";
12+
import type { SelectionStorage } from "@itwin/presentation-hierarchies-react";
13+
import type { InstanceKey } from "@itwin/presentation-shared";
14+
15+
/** @public */
16+
interface FocusedInstancesContext {
17+
/**
18+
* A function, returning an async iterator of items that should be focused. The function is not set
19+
* when instances focus mode is disabled or selection is empty.
20+
*/
21+
loadFocusedItems?: () => AsyncIterableIterator<InstanceKey | GroupingHierarchyNode>;
22+
23+
/** A flag indicating whether instances focus mode is enabled. */
24+
enabled: boolean;
25+
26+
/** Toggle enable or disable instances focus mode. */
27+
toggle: () => void;
28+
}
29+
30+
const focusedInstancesContext = createContext<FocusedInstancesContext>({ enabled: false, toggle: () => {} });
31+
32+
/**
33+
* A React hook for getting focused instances context. The context must be provided
34+
* using `FocusedInstancesContextProvider`.
35+
*
36+
* @public
37+
*/
38+
export function useFocusedInstancesContext(): FocusedInstancesContext {
39+
return useContext(focusedInstancesContext);
40+
}
1641

42+
/**
43+
* A React context provider for setting up focused instances context, which can then be acquired
44+
* using `useFocusedInstancesContext` hook.
45+
*
46+
* @public
47+
*/
1748
export function FocusedInstancesContextProvider({
1849
selectionStorage,
1950
imodelKey,

packages/itwin/tree-widget/src/tree-widget-react/components/trees/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export { useCategoriesTree } from "./categories-tree/UseCategoriesTree.js";
1414
export { useModelsTreeButtonProps } from "./models-tree/ModelsTreeButtons.js";
1515
export { useCategoriesTreeButtonProps } from "./categories-tree/CategoriesTreeButtons.js";
1616

17+
export { FocusedInstancesContextProvider, useFocusedInstancesContext } from "./common/FocusedInstancesContext.js";
18+
1719
export { Tree } from "./common/components/Tree.js";
1820
export { VisibilityTree } from "./common/components/VisibilityTree.js";
1921
export { TreeRenderer } from "./common/components/TreeRenderer.js";

packages/itwin/tree-widget/src/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import { Fragment, useEffect } from "react";
77
import { useActiveIModelConnection } from "@itwin/appui-react";
88
import { TreeWidget } from "../../../TreeWidget.js";
99
import { TreeWithHeader } from "../../tree-header/TreeWithHeader.js";
10-
import { useFocusedInstancesContext } from "../common/FocusedInstancesContext.js";
11-
import { FocusedInstancesContextProvider } from "../common/FocusedInstancesContextProvider.js";
10+
import { FocusedInstancesContextProvider, useFocusedInstancesContext } from "../common/FocusedInstancesContext.js";
1211
import { useActiveViewport } from "../common/UseActiveViewport.js";
1312
import { useFiltering } from "../common/UseFiltering.js";
1413
import { TelemetryContextProvider } from "../common/UseTelemetryContext.js";
@@ -106,7 +105,12 @@ ModelsTreeComponent.View2DButton = View2DButton as ModelsTreeHeaderButtonType;
106105
ModelsTreeComponent.View3DButton = View3DButton as ModelsTreeHeaderButtonType;
107106

108107
/**
109-
* Renders a "Enable/Disable instances focus" button that enables/disables instances focusing mode.
108+
* Renders an "Instance focus" toggle button that enables/disables instances focusing mode.
109+
*
110+
* Requires instances focus context to be provided using `FocusedInstancesContextProvider`. The context
111+
* is provided automatically, when using `ModelsTreeComponent`, but needs to be provided by consumers
112+
* when rendering `ToggleInstancesFocusButton` outside of `ModelsTreeComponent`.
113+
*
110114
* @public
111115
*/
112116
ModelsTreeComponent.ToggleInstancesFocusButton = ToggleInstancesFocusButton as ModelsTreeHeaderButtonType;

0 commit comments

Comments
 (0)