From a39e1f42ecd9147ed35dc227153dc13f2ff074dd Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Tue, 1 Mar 2022 15:06:57 -0500 Subject: [PATCH 1/6] Ensure that widgetDef set/get widgetState accounts for collapsed panel. --- .../src/ui/providers/NetworkTracingUiProvider.tsx | 3 ++- .../src/appui-react/frontstage/FrontstageDef.tsx | 7 ++++++- .../src/appui-react/widget-panels/Frontstage.tsx | 8 ++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/test-apps/ui-items-providers-test/src/ui/providers/NetworkTracingUiProvider.tsx b/test-apps/ui-items-providers-test/src/ui/providers/NetworkTracingUiProvider.tsx index 393f7b5f4660..50806b504028 100644 --- a/test-apps/ui-items-providers-test/src/ui/providers/NetworkTracingUiProvider.tsx +++ b/test-apps/ui-items-providers-test/src/ui/providers/NetworkTracingUiProvider.tsx @@ -166,7 +166,8 @@ export class NetworkTracingUiProvider implements UiItemsProvider { public provideWidgets(stageId: string, _stageUsage: string, location: StagePanelLocation, section?: StagePanelSection): ReadonlyArray { const widgets: AbstractWidgetProps[] = []; - if (stageId === NetworkTracingFrontstage.stageId && location === StagePanelLocation.Right && section === StagePanelSection.Start) { + if ((stageId === NetworkTracingFrontstage.stageId || stageId === "ui-test-app:no-widget-frontstage") && + location === StagePanelLocation.Right && section === StagePanelSection.Start) { /** This widget when only be displayed when there is an element selected. */ const widget: AbstractWidgetProps = { id: "ui-item-provider-test:elementDataListWidget", diff --git a/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx b/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx index 7d96d8584f84..199b35b59ad1 100644 --- a/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx +++ b/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx @@ -708,8 +708,13 @@ export class FrontstageDef { if (isFloatingLocation(location)) return WidgetState.Floating; + let collapsedPanel = false; + if ("side" in location) { + const panel = this.nineZoneState.panels[location.side]; + collapsedPanel = panel.collapsed || 0 === panel.size; + } const widgetContainer = this.nineZoneState.widgets[location.widgetId]; - if (widgetDef.id === widgetContainer.activeTabId) + if (widgetDef.id === widgetContainer.activeTabId && !collapsedPanel) return WidgetState.Open; else return WidgetState.Closed; diff --git a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx index d389d6fc93a4..6a67aeb69de6 100644 --- a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx +++ b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx @@ -841,6 +841,14 @@ export const setWidgetState = produce(( const widget = nineZone.widgets[location.widgetId]; widget.minimized = false; widget.activeTabId = id; + // ensure panel containing widget is not collapsed + if ("side" in location) { + const panel = nineZone.panels[location.side]; + panel.collapsed && (panel.collapsed = false); + if (0 === panel.size) { + panel.size = panel.minSize ?? 200; + } + } } else if (state === WidgetState.Closed) { const id = widgetDef.id; let location = findTab(nineZone, id); From d7c170e3edecf357c9402075e980fbb7743dcdbd Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:43:49 -0500 Subject: [PATCH 2/6] Update test coverage --- .../src/appui-abstract/UiItemsManager.ts | 6 + .../src/test/UiItemsManager.test.ts | 9 + .../appui-react/frontstage/FrontstageDef.tsx | 2 +- .../appui-react/widget-panels/Frontstage.tsx | 6 +- .../test/frontstage/FrontstageDef.test.tsx | 7 +- .../test/widget-panels/Frontstage.test.tsx | 183 +++++++++++++++++- 6 files changed, 206 insertions(+), 7 deletions(-) diff --git a/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts b/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts index bec381339058..e8425bae7a9e 100644 --- a/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts +++ b/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts @@ -138,6 +138,12 @@ export interface UiItemProviderRegisteredEventArgs { export class UiItemsManager { private static _registeredUiItemsProviders: Map = new Map(); + /** For use in unit testing + * @internal */ + public static clearAllProviders() { + UiItemsManager._registeredUiItemsProviders.clear(); + } + /** Event raised any time a UiProvider is registered or unregistered. */ public static readonly onUiProviderRegisteredEvent = new BeEvent<(ev: UiItemProviderRegisteredEventArgs) => void>(); diff --git a/ui/appui-abstract/src/test/UiItemsManager.test.ts b/ui/appui-abstract/src/test/UiItemsManager.test.ts index 41b93faaaae1..63f9fcd378ea 100644 --- a/ui/appui-abstract/src/test/UiItemsManager.test.ts +++ b/ui/appui-abstract/src/test/UiItemsManager.test.ts @@ -88,6 +88,15 @@ describe("UiItemsManager", () => { expect(UiItemsManager.hasRegisteredProviders).to.be.false; }); + it("can clear all providers", () => { + const testUiProvider = new TestUiItemsProvider("TestUiItemsProvider"); + expect(UiItemsManager.hasRegisteredProviders).to.be.false; + UiItemsManager.register(testUiProvider); + expect(UiItemsManager.hasRegisteredProviders).to.be.true; + UiItemsManager.clearAllProviders(); + expect(UiItemsManager.hasRegisteredProviders).to.be.false; + }); + it("if no registered providers no tools are available", () => { const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(0); diff --git a/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx b/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx index 199b35b59ad1..52c290c2b00b 100644 --- a/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx +++ b/ui/appui-react/src/appui-react/frontstage/FrontstageDef.tsx @@ -711,7 +711,7 @@ export class FrontstageDef { let collapsedPanel = false; if ("side" in location) { const panel = this.nineZoneState.panels[location.side]; - collapsedPanel = panel.collapsed || 0 === panel.size; + collapsedPanel = panel.collapsed || undefined === panel.size || 0 === panel.size; } const widgetContainer = this.nineZoneState.widgets[location.widgetId]; if (widgetDef.id === widgetContainer.activeTabId && !collapsedPanel) diff --git a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx index 6a67aeb69de6..64441f6a427a 100644 --- a/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx +++ b/ui/appui-react/src/appui-react/widget-panels/Frontstage.tsx @@ -278,6 +278,7 @@ export function addWidgets(state: NineZoneState, widgets: ReadonlyArray widget.isActive); const minimized = !activeWidget; + // istanbul ignore else if (activeWidget?.defaultState !== WidgetState.Floating) { state = addPanelWidget(state, side, widgetId, tabs, { activeTabId: activeWidget ? activeWidget.id : tabs[0], @@ -638,6 +639,7 @@ const stateVersion = 11; // this needs to be bumped when NineZoneState is change export function initializeNineZoneState(frontstageDef: FrontstageDef): NineZoneState { let nineZone = defaultNineZone; nineZone = produce(nineZone, (stateDraft) => { + // istanbul ignore next if (!FrontstageManager.nineZoneSize) return; stateDraft.size = { @@ -842,10 +844,12 @@ export const setWidgetState = produce(( widget.minimized = false; widget.activeTabId = id; // ensure panel containing widget is not collapsed + // istanbul ignore else if ("side" in location) { const panel = nineZone.panels[location.side]; panel.collapsed && (panel.collapsed = false); - if (0 === panel.size) { + // istanbul ignore next + if (undefined === panel.size || 0 === panel.size) { panel.size = panel.minSize ?? 200; } } diff --git a/ui/appui-react/src/test/frontstage/FrontstageDef.test.tsx b/ui/appui-react/src/test/frontstage/FrontstageDef.test.tsx index 40c93cb9beb5..599f2bf1419c 100644 --- a/ui/appui-react/src/test/frontstage/FrontstageDef.test.tsx +++ b/ui/appui-react/src/test/frontstage/FrontstageDef.test.tsx @@ -6,6 +6,7 @@ import { expect } from "chai"; import * as React from "react"; import * as sinon from "sinon"; +import produce from "immer"; import { MockRender } from "@itwin/core-frontend"; import { CoreTools, Frontstage, FRONTSTAGE_SETTINGS_NAMESPACE, FrontstageDef, FrontstageManager, FrontstageProps, FrontstageProvider, getFrontstageStateSettingName, StagePanelDef, UiFramework, WidgetDef } from "../../appui-react"; import TestUtils, { storageMock } from "../TestUtils"; @@ -323,12 +324,15 @@ describe("float and dock widget", () => { it("panel widget should popout", async () => { let state = createNineZoneState({ size: { height: 1000, width: 1600 } }); - state = addPanelWidget(state, "right", "rightStart", ["t1"], { minimized: true }); + state = addPanelWidget(state, "left", "leftStart", ["t1"], { minimized: true }); state = addPanelWidget(state, "right", "rightMiddle", ["t2", "t4"], { activeTabId: "t2" }); state = addPanelWidget(state, "right", "rightEnd", ["t3"]); state = addTab(state, "t1", { preferredPopoutWidgetSize: { width: 99, height: 99, x: 99, y: 99 } }); state = addTab(state, "t2"); state = addTab(state, "t3"); + state = produce(state, (draft) => { + draft.panels.right.size = 300; + }); const frontstageDef = new FrontstageDef(); const nineZoneStateSetter = sinon.spy(); @@ -354,6 +358,7 @@ describe("float and dock widget", () => { .onFirstCall().returns(t1); findWidgetDefGetter.returns(t2); + expect(frontstageDef.getWidgetCurrentState(t1)).to.eql(WidgetState.Closed); expect(frontstageDef.getWidgetCurrentState(t2)).to.eql(WidgetState.Open); expect(frontstageDef.getWidgetCurrentState(t4)).to.eql(WidgetState.Closed); diff --git a/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx b/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx index ddfcffb8d5a3..f210b5380c71 100644 --- a/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx +++ b/ui/appui-react/src/test/widget-panels/Frontstage.test.tsx @@ -87,6 +87,24 @@ export class TestFrontstageUi2 extends FrontstageProvider { } } +/** @internal */ +export class TestFrontstageWithHiddenWidget extends FrontstageProvider { + public static stageId = "TestFrontstageWithHiddenWidget"; + public get id(): string { + return TestFrontstageWithHiddenWidget.stageId; + } + + public get frontstage() { + return ( + + ); + } +} + /** @internal */ export class TestFrontstageUi1 extends FrontstageProvider { public static stageId = "TestFrontstageUi1"; @@ -377,6 +395,25 @@ class TestDuplicateWidgetProvider implements UiItemsProvider { } } +class TestHiddenWidgetProvider implements UiItemsProvider { + public static stageId = "TestFrontstageWithHiddenWidget"; + public get id(): string { + return TestHiddenWidgetProvider.stageId; + } + + public provideWidgets(_stageId: string, _stageUsage: string, location: StagePanelLocation, section?: StagePanelSection) { + const widgets: Array = []; + if (location === StagePanelLocation.Left && section === StagePanelSection.Middle) + widgets.push({ + id: "TestHiddenWidgetProviderLM1", + label: "TestHiddenWidgetProvider Hidden LM1", + getWidgetContent: () => "TestHiddenWidgetProvider LM1 widget", + defaultState: WidgetState.Hidden, + }); + return widgets; + } +} + describe("Frontstage local storage wrapper", () => { const localStorageToRestore = Object.getOwnPropertyDescriptor(window, "localStorage")!; const localStorageMock = storageMock(); @@ -683,6 +720,91 @@ describe("Frontstage local storage wrapper", () => { spy.called.should.true; }); + it("should show WidgetState as closed in panel size is undefined", () => { + const frontstageDef = new FrontstageDef(); + sinon.stub(frontstageDef, "isReady").get(() => true); + + let nineZoneState = createNineZoneState(); + nineZoneState = addPanelWidget(nineZoneState, "left", "start", ["t1", "t2"], { activeTabId: "t1" }); + nineZoneState = addTab(nineZoneState, "t1"); + frontstageDef.nineZoneState = nineZoneState; + const widgetDef = new WidgetDef({ + id: "t1", + defaultState: WidgetState.Hidden, + }); + + const leftPanel = new StagePanelDef(); + leftPanel.initializeFromProps({ + resizable: true, + widgets: [ + , + ], + }, StagePanelLocation.Left); + sinon.stub(frontstageDef, "leftPanel").get(() => leftPanel); + + sinon.stub(frontstageDef, "getStagePanelDef").withArgs(StagePanelLocation.Left).returns(leftPanel); + sinon.stub(frontstageDef, "findWidgetDef").withArgs("t1").returns(widgetDef); + + // const panel = frontstageDef.nineZoneState.panels.left; + expect(frontstageDef.getWidgetCurrentState(widgetDef)).to.be.eql(WidgetState.Closed); + }); + + it("should show WidgetState as closed in panel size is 0", () => { + const frontstageDef = new FrontstageDef(); + sinon.stub(frontstageDef, "isReady").get(() => true); + + let nineZoneState = createNineZoneState(); + nineZoneState = addPanelWidget(nineZoneState, "left", "start", ["t1", "t2"], { activeTabId: "t1" }); + nineZoneState = addTab(nineZoneState, "t1"); + frontstageDef.nineZoneState = nineZoneState; + const widgetDef = new WidgetDef({ + id: "t1", + defaultState: WidgetState.Hidden, + }); + + const leftPanel = new StagePanelDef(); + leftPanel.initializeFromProps({ + resizable: true, + size: 0, + widgets: [ + , + ], + }, StagePanelLocation.Left); + sinon.stub(frontstageDef, "leftPanel").get(() => leftPanel); + + sinon.stub(frontstageDef, "getStagePanelDef").withArgs(StagePanelLocation.Left).returns(leftPanel); + sinon.stub(frontstageDef, "findWidgetDef").withArgs("t1").returns(widgetDef); + + // const panel = frontstageDef.nineZoneState.panels.left; + expect(frontstageDef.getWidgetCurrentState(widgetDef)).to.be.eql(WidgetState.Closed); + }); + + it("should show WidgetState as closed in panel is collapsed", () => { + const frontstageDef = new FrontstageDef(); + sinon.stub(frontstageDef, "isReady").get(() => true); + + let nineZoneState = createNineZoneState(); + nineZoneState = addPanelWidget(nineZoneState, "left", "start", ["t1", "t2"], { activeTabId: "t1" }); + nineZoneState = addTab(nineZoneState, "t1"); + nineZoneState = produce(nineZoneState, (draft) => { + draft.panels.left.collapsed = true; + }); + frontstageDef.nineZoneState = nineZoneState; + const widgetDef = new WidgetDef({ + id: "t1", + defaultState: WidgetState.Open, + }); + + sinon.stub(frontstageDef, "findWidgetDef").withArgs("t1").returns(widgetDef); + expect(frontstageDef.getWidgetCurrentState(widgetDef)).to.be.eql(WidgetState.Closed); + }); + it("should ignore nineZoneState changes of other frontstages", () => { const frontstageDef = new FrontstageDef(); const nineZoneState = createNineZoneState(); @@ -1837,13 +1959,10 @@ describe("Frontstage local storage wrapper", () => { }); afterEach(() => { - UiItemsManager.unregister("TestUi2Provider"); + UiItemsManager.clearAllProviders(); FrontstageManager.clearFrontstageProviders(); FrontstageManager.setActiveFrontstageDef(undefined); FrontstageManager.nineZoneSize = undefined; - }); - - afterEach(() => { TestUtils.terminateUiFramework(); IModelApp.shutdown(); }); @@ -1875,6 +1994,62 @@ describe("Frontstage local storage wrapper", () => { await wrapper.findByText("TestUi2Provider W1"); expect(wrapper.queryAllByText("Left Start 1").length).to.equal(1); expect(wrapper.queryAllByText("TestUi2Provider RM1").length).to.equal(1); + + }); + + it("should support widgets with default state of hidden", async () => { + UiItemsManager.register(new TestHiddenWidgetProvider()); + + const frontstageProvider = new TestFrontstageWithHiddenWidget(); + FrontstageManager.addFrontstageProvider(frontstageProvider); + const frontstageDef = await FrontstageManager.getFrontstageDef(frontstageProvider.frontstage.props.id); + if (frontstageDef) + frontstageDef.nineZoneState = createNineZoneState(); + + await FrontstageManager.setActiveFrontstageDef(frontstageDef); + const widgetDef = frontstageDef?.findWidgetDef("TestHiddenWidgetProviderLM1"); + expect (widgetDef).to.not.be.undefined; + + const wrapper = render(); + // should be hidden initially + expect(wrapper.queryAllByText("TestHiddenWidgetProvider LM1 widget").length).to.equal(0); + + act(() => { + widgetDef?.setWidgetState(WidgetState.Open); + }); + + // should be present after setting state to Open + expect(wrapper.queryAllByText("TestHiddenWidgetProvider LM1 widget").length).to.equal(1); + }); + + it("should open collapsed panel when widget is opened", async () => { + UiItemsManager.register(new TestHiddenWidgetProvider()); + + const frontstageProvider = new TestFrontstageWithHiddenWidget(); + FrontstageManager.addFrontstageProvider(frontstageProvider); + const frontstageDef = await FrontstageManager.getFrontstageDef(frontstageProvider.frontstage.props.id); + if (frontstageDef) { + let state = createNineZoneState(); + state = produce(state, (draft) => { + draft.panels.left.collapsed = true; + }); + frontstageDef.nineZoneState = state; + } + + await FrontstageManager.setActiveFrontstageDef(frontstageDef); + const widgetDef = frontstageDef?.findWidgetDef("TestHiddenWidgetProviderLM1"); + expect (widgetDef).to.not.be.undefined; + + const wrapper = render(); + // should be hidden initially + expect(wrapper.queryAllByText("TestHiddenWidgetProvider LM1 widget").length).to.equal(0); + + act(() => { + widgetDef?.setWidgetState(WidgetState.Open); + }); + + // should be present after setting state to Open + expect(wrapper.queryAllByText("TestHiddenWidgetProvider LM1 widget").length).to.equal(1); }); it("should listen for window close event", async () => { From 28ea8ea16589cef5ae03fd0185dd66a6c294fa30 Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:57:21 -0500 Subject: [PATCH 3/6] rush change --- .../ui-updateSetWidgetState_2022-03-02-16-51.json | 10 ++++++++++ .../ui-updateSetWidgetState_2022-03-02-16-51.json | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 common/changes/@itwin/appui-abstract/ui-updateSetWidgetState_2022-03-02-16-51.json create mode 100644 common/changes/@itwin/appui-react/ui-updateSetWidgetState_2022-03-02-16-51.json diff --git a/common/changes/@itwin/appui-abstract/ui-updateSetWidgetState_2022-03-02-16-51.json b/common/changes/@itwin/appui-abstract/ui-updateSetWidgetState_2022-03-02-16-51.json new file mode 100644 index 000000000000..d5d2daef5bb4 --- /dev/null +++ b/common/changes/@itwin/appui-abstract/ui-updateSetWidgetState_2022-03-02-16-51.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-abstract", + "comment": "Provide internal method to clear out all registered item providers for use in unit testing.", + "type": "none" + } + ], + "packageName": "@itwin/appui-abstract" +} \ No newline at end of file diff --git a/common/changes/@itwin/appui-react/ui-updateSetWidgetState_2022-03-02-16-51.json b/common/changes/@itwin/appui-react/ui-updateSetWidgetState_2022-03-02-16-51.json new file mode 100644 index 000000000000..0265a16771d3 --- /dev/null +++ b/common/changes/@itwin/appui-react/ui-updateSetWidgetState_2022-03-02-16-51.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-react", + "comment": "Add the ability to Open a collapsed Panel when a request to Open a widget in a collapsed panel is made.", + "type": "none" + } + ], + "packageName": "@itwin/appui-react" +} \ No newline at end of file From 3778e6d383ca7784ea82b0c6dfde02877e85418c Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:31:24 -0500 Subject: [PATCH 4/6] extract-api and add change info to NextVersion.md --- common/api/appui-abstract.api.md | 2 ++ docs/changehistory/NextVersion.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/common/api/appui-abstract.api.md b/common/api/appui-abstract.api.md index aa894beea9b9..cd6030c73e97 100644 --- a/common/api/appui-abstract.api.md +++ b/common/api/appui-abstract.api.md @@ -2099,6 +2099,8 @@ export enum UiItemsApplicationAction { // @public export class UiItemsManager { + // @internal + static clearAllProviders(): void; static getBackstageItems(): BackstageItem[]; static getStatusBarItems(stageId: string, stageUsage: string, stageAppData?: any): CommonStatusBarItem[]; static getToolbarButtonItems(stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation, stageAppData?: any): CommonToolbarItem[]; diff --git a/docs/changehistory/NextVersion.md b/docs/changehistory/NextVersion.md index c5185ff70f2b..7f8ae08daed5 100644 --- a/docs/changehistory/NextVersion.md +++ b/docs/changehistory/NextVersion.md @@ -84,3 +84,9 @@ It is now possible to retrieve `Units` from schemas stored in IModels. The new [ UiFramework.setIModelConnection(iModelConnection, true); ``` + +## AppUI Updates + +### WidgetState changes + +The property [WidgetDef.state]($appui-react) will now return `WidgetState.Closed` if the widget is in a panel that is collapsed or the panel size is 0 or undefined. When `WidgetState.Open` is passed to the method [WidgetDef.setWidgetState] the containing panel will also open if it is in a collapsed state. From 4cfa89392952b23bcb2ef6c3094af7529d0ba33e Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:37:50 -0500 Subject: [PATCH 5/6] add comma to break up sentence --- docs/changehistory/NextVersion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changehistory/NextVersion.md b/docs/changehistory/NextVersion.md index 7f8ae08daed5..5c47dc34f507 100644 --- a/docs/changehistory/NextVersion.md +++ b/docs/changehistory/NextVersion.md @@ -89,4 +89,4 @@ It is now possible to retrieve `Units` from schemas stored in IModels. The new [ ### WidgetState changes -The property [WidgetDef.state]($appui-react) will now return `WidgetState.Closed` if the widget is in a panel that is collapsed or the panel size is 0 or undefined. When `WidgetState.Open` is passed to the method [WidgetDef.setWidgetState] the containing panel will also open if it is in a collapsed state. +The property [WidgetDef.state]($appui-react) will now return `WidgetState.Closed` if the widget is in a panel that is collapsed, or the panel size is 0 or undefined. When `WidgetState.Open` is passed to the method [WidgetDef.setWidgetState] the containing panel will also open if it is in a collapsed state. From da18daf4f5130e2b35c986982e3f487585f89cb1 Mon Sep 17 00:00:00 2001 From: bsteinbk <65047615+bsteinbk@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:44:47 -0500 Subject: [PATCH 6/6] Add missing package reference. --- docs/changehistory/NextVersion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changehistory/NextVersion.md b/docs/changehistory/NextVersion.md index 5c47dc34f507..77dce2603294 100644 --- a/docs/changehistory/NextVersion.md +++ b/docs/changehistory/NextVersion.md @@ -89,4 +89,4 @@ It is now possible to retrieve `Units` from schemas stored in IModels. The new [ ### WidgetState changes -The property [WidgetDef.state]($appui-react) will now return `WidgetState.Closed` if the widget is in a panel that is collapsed, or the panel size is 0 or undefined. When `WidgetState.Open` is passed to the method [WidgetDef.setWidgetState] the containing panel will also open if it is in a collapsed state. +The property [WidgetDef.state]($appui-react) will now return `WidgetState.Closed` if the widget is in a panel that is collapsed, or the panel size is 0 or undefined. When `WidgetState.Open` is passed to the method [WidgetDef.setWidgetState]($appui-react) the containing panel will also open if it is in a collapsed state.