@itwin/appui-react 4.5.1 → 4.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/lib/cjs/appui-react/accudraw/MenuButton.d.ts +2 -2
  3. package/lib/cjs/appui-react/accudraw/MenuButton.d.ts.map +1 -1
  4. package/lib/cjs/appui-react/accudraw/MenuButton.js.map +1 -1
  5. package/lib/cjs/appui-react/backstage/BackstageComposer.d.ts.map +1 -1
  6. package/lib/cjs/appui-react/backstage/BackstageComposer.js.map +1 -1
  7. package/lib/cjs/appui-react/childwindow/CopyStyles.d.ts.map +1 -1
  8. package/lib/cjs/appui-react/childwindow/CopyStyles.js +3 -1
  9. package/lib/cjs/appui-react/childwindow/CopyStyles.js.map +1 -1
  10. package/lib/cjs/appui-react/childwindow/InternalChildWindowManager.d.ts.map +1 -1
  11. package/lib/cjs/appui-react/childwindow/InternalChildWindowManager.js +2 -1
  12. package/lib/cjs/appui-react/childwindow/InternalChildWindowManager.js.map +1 -1
  13. package/lib/cjs/appui-react/cursor/CursorInformation.d.ts +6 -6
  14. package/lib/cjs/appui-react/cursor/CursorInformation.d.ts.map +1 -1
  15. package/lib/cjs/appui-react/cursor/CursorInformation.js.map +1 -1
  16. package/lib/cjs/appui-react/cursor/cursormenu/CursorMenu.d.ts.map +1 -1
  17. package/lib/cjs/appui-react/cursor/cursormenu/CursorMenu.js.map +1 -1
  18. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopup.d.ts +4 -4
  19. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopup.d.ts.map +1 -1
  20. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopup.js.map +1 -1
  21. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopupManager.d.ts +5 -5
  22. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopupManager.d.ts.map +1 -1
  23. package/lib/cjs/appui-react/cursor/cursorpopup/CursorPopupManager.js.map +1 -1
  24. package/lib/cjs/appui-react/cursor/cursorprompt/CursorPrompt.d.ts +2 -2
  25. package/lib/cjs/appui-react/cursor/cursorprompt/CursorPrompt.d.ts.map +1 -1
  26. package/lib/cjs/appui-react/cursor/cursorprompt/CursorPrompt.js.map +1 -1
  27. package/lib/cjs/appui-react/dialog/ContentDialog.js.map +1 -1
  28. package/lib/cjs/appui-react/feedback/ElementTooltip.d.ts +1 -2
  29. package/lib/cjs/appui-react/feedback/ElementTooltip.d.ts.map +1 -1
  30. package/lib/cjs/appui-react/feedback/ElementTooltip.js.map +1 -1
  31. package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts +22 -26
  32. package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
  33. package/lib/cjs/appui-react/frontstage/FrontstageDef.js +185 -254
  34. package/lib/cjs/appui-react/frontstage/FrontstageDef.js.map +1 -1
  35. package/lib/cjs/appui-react/frontstage/InternalFrontstageManager.d.ts +1 -7
  36. package/lib/cjs/appui-react/frontstage/InternalFrontstageManager.d.ts.map +1 -1
  37. package/lib/cjs/appui-react/frontstage/InternalFrontstageManager.js +0 -6
  38. package/lib/cjs/appui-react/frontstage/InternalFrontstageManager.js.map +1 -1
  39. package/lib/cjs/appui-react/hooks/useActiveIModelConnection.d.ts.map +1 -1
  40. package/lib/cjs/appui-react/hooks/useActiveIModelConnection.js.map +1 -1
  41. package/lib/cjs/appui-react/hooks/useActiveViewport.d.ts.map +1 -1
  42. package/lib/cjs/appui-react/hooks/useActiveViewport.js.map +1 -1
  43. package/lib/cjs/appui-react/keyboardshortcut/InternalKeyboardShortcut.d.ts.map +1 -1
  44. package/lib/cjs/appui-react/keyboardshortcut/InternalKeyboardShortcut.js.map +1 -1
  45. package/lib/cjs/appui-react/messages/MessageManager.d.ts +0 -1
  46. package/lib/cjs/appui-react/messages/MessageManager.d.ts.map +1 -1
  47. package/lib/cjs/appui-react/messages/MessageManager.js +1 -2
  48. package/lib/cjs/appui-react/messages/MessageManager.js.map +1 -1
  49. package/lib/cjs/appui-react/messages/Pointer.d.ts +1 -2
  50. package/lib/cjs/appui-react/messages/Pointer.d.ts.map +1 -1
  51. package/lib/cjs/appui-react/messages/Pointer.js +1 -1
  52. package/lib/cjs/appui-react/messages/Pointer.js.map +1 -1
  53. package/lib/cjs/appui-react/popup/PositionPopup.d.ts +2 -2
  54. package/lib/cjs/appui-react/popup/PositionPopup.d.ts.map +1 -1
  55. package/lib/cjs/appui-react/popup/PositionPopup.js.map +1 -1
  56. package/lib/cjs/appui-react/settings/ui/UiSettingsPage.js.map +1 -1
  57. package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts +16 -20
  58. package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
  59. package/lib/cjs/appui-react/stagepanels/StagePanelDef.js +80 -115
  60. package/lib/cjs/appui-react/stagepanels/StagePanelDef.js.map +1 -1
  61. package/lib/cjs/appui-react/statusfields/MessageCenter.d.ts.map +1 -1
  62. package/lib/cjs/appui-react/statusfields/MessageCenter.js +1 -2
  63. package/lib/cjs/appui-react/statusfields/MessageCenter.js.map +1 -1
  64. package/lib/cjs/appui-react/syncui/InternalSyncUiEventDispatcher.d.ts +36 -0
  65. package/lib/cjs/appui-react/syncui/InternalSyncUiEventDispatcher.d.ts.map +1 -0
  66. package/lib/cjs/appui-react/syncui/InternalSyncUiEventDispatcher.js +134 -0
  67. package/lib/cjs/appui-react/syncui/InternalSyncUiEventDispatcher.js.map +1 -0
  68. package/lib/cjs/appui-react/syncui/SyncUiEventDispatcher.d.ts +1 -1
  69. package/lib/cjs/appui-react/syncui/SyncUiEventDispatcher.d.ts.map +1 -1
  70. package/lib/cjs/appui-react/syncui/SyncUiEventDispatcher.js +2 -2
  71. package/lib/cjs/appui-react/syncui/SyncUiEventDispatcher.js.map +1 -1
  72. package/lib/cjs/appui-react/syncui/UiSyncEvent.d.ts +16 -0
  73. package/lib/cjs/appui-react/syncui/UiSyncEvent.d.ts.map +1 -0
  74. package/lib/cjs/appui-react/syncui/UiSyncEvent.js +18 -0
  75. package/lib/cjs/appui-react/syncui/UiSyncEvent.js.map +1 -0
  76. package/lib/cjs/appui-react/uistate/AppUiSettings.d.ts.map +1 -1
  77. package/lib/cjs/appui-react/uistate/AppUiSettings.js.map +1 -1
  78. package/lib/cjs/appui-react/uistate/useUiStateStorage.d.ts.map +1 -1
  79. package/lib/cjs/appui-react/uistate/useUiStateStorage.js.map +1 -1
  80. package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts +7 -29
  81. package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
  82. package/lib/cjs/appui-react/widget-panels/Frontstage.js +101 -434
  83. package/lib/cjs/appui-react/widget-panels/Frontstage.js.map +1 -1
  84. package/lib/cjs/appui-react/widget-panels/ToolSettings.d.ts.map +1 -1
  85. package/lib/cjs/appui-react/widget-panels/ToolSettings.js +16 -3
  86. package/lib/cjs/appui-react/widget-panels/ToolSettings.js.map +1 -1
  87. package/lib/cjs/appui-react/widgets/Widget.d.ts +10 -4
  88. package/lib/cjs/appui-react/widgets/Widget.d.ts.map +1 -1
  89. package/lib/cjs/appui-react/widgets/Widget.js.map +1 -1
  90. package/lib/cjs/appui-react/widgets/WidgetDef.d.ts +9 -29
  91. package/lib/cjs/appui-react/widgets/WidgetDef.d.ts.map +1 -1
  92. package/lib/cjs/appui-react/widgets/WidgetDef.js +89 -46
  93. package/lib/cjs/appui-react/widgets/WidgetDef.js.map +1 -1
  94. package/lib/cjs/appui-react.d.ts +1 -0
  95. package/lib/cjs/appui-react.d.ts.map +1 -1
  96. package/lib/cjs/appui-react.js +1 -0
  97. package/lib/cjs/appui-react.js.map +1 -1
  98. package/lib/esm/appui-react/accudraw/MenuButton.d.ts +2 -2
  99. package/lib/esm/appui-react/accudraw/MenuButton.d.ts.map +1 -1
  100. package/lib/esm/appui-react/accudraw/MenuButton.js.map +1 -1
  101. package/lib/esm/appui-react/backstage/BackstageComposer.d.ts.map +1 -1
  102. package/lib/esm/appui-react/backstage/BackstageComposer.js.map +1 -1
  103. package/lib/esm/appui-react/childwindow/CopyStyles.d.ts.map +1 -1
  104. package/lib/esm/appui-react/childwindow/CopyStyles.js +3 -1
  105. package/lib/esm/appui-react/childwindow/CopyStyles.js.map +1 -1
  106. package/lib/esm/appui-react/childwindow/InternalChildWindowManager.d.ts.map +1 -1
  107. package/lib/esm/appui-react/childwindow/InternalChildWindowManager.js +2 -1
  108. package/lib/esm/appui-react/childwindow/InternalChildWindowManager.js.map +1 -1
  109. package/lib/esm/appui-react/cursor/CursorInformation.d.ts +6 -6
  110. package/lib/esm/appui-react/cursor/CursorInformation.d.ts.map +1 -1
  111. package/lib/esm/appui-react/cursor/CursorInformation.js.map +1 -1
  112. package/lib/esm/appui-react/cursor/cursormenu/CursorMenu.d.ts.map +1 -1
  113. package/lib/esm/appui-react/cursor/cursormenu/CursorMenu.js.map +1 -1
  114. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopup.d.ts +4 -4
  115. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopup.d.ts.map +1 -1
  116. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopup.js.map +1 -1
  117. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopupManager.d.ts +5 -5
  118. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopupManager.d.ts.map +1 -1
  119. package/lib/esm/appui-react/cursor/cursorpopup/CursorPopupManager.js.map +1 -1
  120. package/lib/esm/appui-react/cursor/cursorprompt/CursorPrompt.d.ts +2 -2
  121. package/lib/esm/appui-react/cursor/cursorprompt/CursorPrompt.d.ts.map +1 -1
  122. package/lib/esm/appui-react/cursor/cursorprompt/CursorPrompt.js.map +1 -1
  123. package/lib/esm/appui-react/dialog/ContentDialog.js.map +1 -1
  124. package/lib/esm/appui-react/feedback/ElementTooltip.d.ts +1 -2
  125. package/lib/esm/appui-react/feedback/ElementTooltip.d.ts.map +1 -1
  126. package/lib/esm/appui-react/feedback/ElementTooltip.js.map +1 -1
  127. package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts +22 -26
  128. package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
  129. package/lib/esm/appui-react/frontstage/FrontstageDef.js +189 -258
  130. package/lib/esm/appui-react/frontstage/FrontstageDef.js.map +1 -1
  131. package/lib/esm/appui-react/frontstage/InternalFrontstageManager.d.ts +1 -7
  132. package/lib/esm/appui-react/frontstage/InternalFrontstageManager.d.ts.map +1 -1
  133. package/lib/esm/appui-react/frontstage/InternalFrontstageManager.js +0 -6
  134. package/lib/esm/appui-react/frontstage/InternalFrontstageManager.js.map +1 -1
  135. package/lib/esm/appui-react/hooks/useActiveIModelConnection.d.ts.map +1 -1
  136. package/lib/esm/appui-react/hooks/useActiveIModelConnection.js.map +1 -1
  137. package/lib/esm/appui-react/hooks/useActiveViewport.d.ts.map +1 -1
  138. package/lib/esm/appui-react/hooks/useActiveViewport.js.map +1 -1
  139. package/lib/esm/appui-react/keyboardshortcut/InternalKeyboardShortcut.d.ts.map +1 -1
  140. package/lib/esm/appui-react/keyboardshortcut/InternalKeyboardShortcut.js.map +1 -1
  141. package/lib/esm/appui-react/messages/MessageManager.d.ts +0 -1
  142. package/lib/esm/appui-react/messages/MessageManager.d.ts.map +1 -1
  143. package/lib/esm/appui-react/messages/MessageManager.js +1 -2
  144. package/lib/esm/appui-react/messages/MessageManager.js.map +1 -1
  145. package/lib/esm/appui-react/messages/Pointer.d.ts +1 -2
  146. package/lib/esm/appui-react/messages/Pointer.d.ts.map +1 -1
  147. package/lib/esm/appui-react/messages/Pointer.js +1 -1
  148. package/lib/esm/appui-react/messages/Pointer.js.map +1 -1
  149. package/lib/esm/appui-react/popup/PositionPopup.d.ts +2 -2
  150. package/lib/esm/appui-react/popup/PositionPopup.d.ts.map +1 -1
  151. package/lib/esm/appui-react/popup/PositionPopup.js.map +1 -1
  152. package/lib/esm/appui-react/settings/ui/UiSettingsPage.js.map +1 -1
  153. package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts +16 -20
  154. package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
  155. package/lib/esm/appui-react/stagepanels/StagePanelDef.js +78 -114
  156. package/lib/esm/appui-react/stagepanels/StagePanelDef.js.map +1 -1
  157. package/lib/esm/appui-react/statusfields/MessageCenter.d.ts.map +1 -1
  158. package/lib/esm/appui-react/statusfields/MessageCenter.js +1 -2
  159. package/lib/esm/appui-react/statusfields/MessageCenter.js.map +1 -1
  160. package/lib/esm/appui-react/syncui/InternalSyncUiEventDispatcher.d.ts +36 -0
  161. package/lib/esm/appui-react/syncui/InternalSyncUiEventDispatcher.d.ts.map +1 -0
  162. package/lib/esm/appui-react/syncui/InternalSyncUiEventDispatcher.js +130 -0
  163. package/lib/esm/appui-react/syncui/InternalSyncUiEventDispatcher.js.map +1 -0
  164. package/lib/esm/appui-react/syncui/SyncUiEventDispatcher.d.ts +1 -1
  165. package/lib/esm/appui-react/syncui/SyncUiEventDispatcher.d.ts.map +1 -1
  166. package/lib/esm/appui-react/syncui/SyncUiEventDispatcher.js +2 -2
  167. package/lib/esm/appui-react/syncui/SyncUiEventDispatcher.js.map +1 -1
  168. package/lib/esm/appui-react/syncui/UiSyncEvent.d.ts +16 -0
  169. package/lib/esm/appui-react/syncui/UiSyncEvent.d.ts.map +1 -0
  170. package/lib/esm/appui-react/syncui/UiSyncEvent.js +14 -0
  171. package/lib/esm/appui-react/syncui/UiSyncEvent.js.map +1 -0
  172. package/lib/esm/appui-react/uistate/AppUiSettings.d.ts.map +1 -1
  173. package/lib/esm/appui-react/uistate/AppUiSettings.js.map +1 -1
  174. package/lib/esm/appui-react/uistate/useUiStateStorage.d.ts.map +1 -1
  175. package/lib/esm/appui-react/uistate/useUiStateStorage.js.map +1 -1
  176. package/lib/esm/appui-react/widget-panels/Frontstage.d.ts +7 -29
  177. package/lib/esm/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
  178. package/lib/esm/appui-react/widget-panels/Frontstage.js +104 -433
  179. package/lib/esm/appui-react/widget-panels/Frontstage.js.map +1 -1
  180. package/lib/esm/appui-react/widget-panels/ToolSettings.d.ts.map +1 -1
  181. package/lib/esm/appui-react/widget-panels/ToolSettings.js +16 -3
  182. package/lib/esm/appui-react/widget-panels/ToolSettings.js.map +1 -1
  183. package/lib/esm/appui-react/widgets/Widget.d.ts +10 -4
  184. package/lib/esm/appui-react/widgets/Widget.d.ts.map +1 -1
  185. package/lib/esm/appui-react/widgets/Widget.js.map +1 -1
  186. package/lib/esm/appui-react/widgets/WidgetDef.d.ts +9 -29
  187. package/lib/esm/appui-react/widgets/WidgetDef.d.ts.map +1 -1
  188. package/lib/esm/appui-react/widgets/WidgetDef.js +89 -46
  189. package/lib/esm/appui-react/widgets/WidgetDef.js.map +1 -1
  190. package/lib/esm/appui-react.d.ts +1 -0
  191. package/lib/esm/appui-react.d.ts.map +1 -1
  192. package/lib/esm/appui-react.js +1 -0
  193. package/lib/esm/appui-react.js.map +1 -1
  194. package/package.json +10 -10
@@ -10,10 +10,11 @@ import "./Frontstage.scss";
10
10
  import produce from "immer";
11
11
  import * as React from "react";
12
12
  import { unstable_batchedUpdates } from "react-dom";
13
- import { assert, Logger, ProcessDetector } from "@itwin/core-bentley";
14
- import { Rectangle, Size, UiStateStorageStatus } from "@itwin/core-react";
13
+ import { Logger, ProcessDetector } from "@itwin/core-bentley";
14
+ import { Rectangle, UiStateStorageStatus } from "@itwin/core-react";
15
15
  import { ToolbarPopupAutoHideContext } from "@itwin/components-react";
16
- import { addDockedToolSettings, addFloatingWidget, addPanelWidget, addTab, addTabToWidget, addWidgetToolSettings, convertAllPopupWidgetContainersToFloating, createLayoutStore, createNineZoneState, floatingWidgetBringToFront, FloatingWidgets, getTabLocation, getUniqueId, getWidgetPanelSectionId, insertPanelWidget, insertTabToWidget, isFloatingTabLocation, isHorizontalPanelSide, isPanelTabLocation, isPopoutTabLocation, NineZone, NineZoneStateReducer, panelSides, removeTab, removeTabFromWidget, removeToolSettings, WidgetPanels, } from "@itwin/appui-layout-react";
16
+ import { addDockedToolSettings, addFloatingWidget, addPanelWidget, addRemovedTab, addTab, addTabToWidget, createLayoutStore, createNineZoneState, floatingWidgetBringToFront, FloatingWidgets, getTabLocation, getUniqueId, getWidgetPanelSectionId, isFloatingTabLocation, isPanelTabLocation, NineZone, NineZoneStateReducer, removeTab, WidgetPanels, } from "@itwin/appui-layout-react";
17
+ import { useActiveFrontstageDef, } from "../frontstage/FrontstageDef";
17
18
  import { StagePanelState, toPanelSide } from "../stagepanels/StagePanelDef";
18
19
  import { UiFramework } from "../UiFramework";
19
20
  import { useUiStateStorageHandler } from "../uistate/useUiStateStorage";
@@ -50,30 +51,19 @@ const widgetContent = React.createElement(WidgetContent, null);
50
51
  const toolSettingsContent = React.createElement(ToolSettingsContent, null);
51
52
  const widgetPanelsFrontstage = React.createElement(WidgetPanelsFrontstageComponent, null);
52
53
  /** @internal */
53
- export function useLayoutStore() {
54
- const [def, setDef] = React.useState(UiFramework.frontstages.activeFrontstageDef);
55
- const [layout, setLayout] = React.useState(() => createLayoutStore(def?.nineZoneState));
56
- React.useEffect(() => {
57
- return UiFramework.frontstages.onFrontstageActivatedEvent.addListener((args) => {
58
- unstable_batchedUpdates(() => {
59
- setDef(args.activatedFrontstageDef);
60
- setLayout(createLayoutStore(args.activatedFrontstageDef.nineZoneState));
61
- });
62
- });
63
- }, []);
54
+ export function useLayoutStore(frontstageDef) {
55
+ const layoutStore = React.useMemo(() => createLayoutStore(frontstageDef?.nineZoneState), [frontstageDef]);
64
56
  React.useEffect(() => {
65
57
  return InternalFrontstageManager.onFrontstageNineZoneStateChangedEvent.addListener((args) => {
66
- if (args.frontstageDef !== def ||
67
- def.isStageClosing ||
68
- def.isApplicationClosing)
58
+ if (args.frontstageDef !== frontstageDef)
69
59
  return;
70
60
  unstable_batchedUpdates(() => {
71
61
  // https://github.com/pmndrs/zustand/blob/main/docs/guides/event-handler-in-pre-react-18.md
72
- layout.setState(args.state || defaultNineZone);
62
+ layoutStore.setState(args.state || defaultNineZone);
73
63
  });
74
64
  });
75
- }, [def, layout]);
76
- return [layout, def];
65
+ }, [frontstageDef, layoutStore]);
66
+ return layoutStore;
77
67
  }
78
68
  /** Update in-memory NineZoneState of newly activated frontstage with up to date size.
79
69
  * @internal
@@ -81,65 +71,30 @@ export function useLayoutStore() {
81
71
  export function useUpdateNineZoneSize(frontstageDef) {
82
72
  React.useEffect(() => {
83
73
  const size = InternalFrontstageManager.nineZoneSize;
84
- let state = frontstageDef.nineZoneState;
74
+ const state = frontstageDef.nineZoneState;
85
75
  if (!size || !state)
86
76
  return;
87
- state = FrameworkStateReducer(state, {
77
+ frontstageDef.dispatch({
88
78
  type: "RESIZE",
89
79
  size: {
90
80
  height: size.height,
91
81
  width: size.width,
92
82
  },
93
- }, frontstageDef);
94
- frontstageDef.nineZoneState = state;
95
- }, [frontstageDef]);
96
- }
97
- /** @internal */
98
- export function FrameworkStateReducer(state, action, frontstageDef) {
99
- state = NineZoneStateReducer(state, action);
100
- if (action.type === "RESIZE") {
101
- state = produce(state, (draft) => {
102
- for (const panelSide of panelSides) {
103
- const panel = draft.panels[panelSide];
104
- const location = toStagePanelLocation(panelSide);
105
- const panelDef = frontstageDef.getStagePanelDef(location);
106
- if (panelDef?.maxSizeSpec) {
107
- panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide, action.size);
108
- if (panel.size) {
109
- panel.size = Math.min(Math.max(panel.size, panel.minSize), panel.maxSize);
110
- }
111
- }
112
- }
113
83
  });
114
- }
115
- return state;
84
+ }, [frontstageDef]);
116
85
  }
117
86
  /** @internal */
118
87
  export function useNineZoneDispatch(frontstageDef) {
119
- const dispatch = React.useCallback((action) => {
120
- if (action.type === "RESIZE") {
121
- InternalFrontstageManager.nineZoneSize = Size.create(action.size);
122
- }
123
- if (action.type === "WIDGET_TAB_POPOUT") {
124
- const tabId = action.id;
125
- frontstageDef.popoutWidget(tabId);
126
- return;
127
- }
128
- const state = frontstageDef.nineZoneState;
129
- if (!state)
130
- return;
131
- frontstageDef.nineZoneState = FrameworkStateReducer(state, action, frontstageDef);
132
- }, [frontstageDef]);
133
- return dispatch;
88
+ return React.useMemo(() => frontstageDef.dispatch, [frontstageDef]);
134
89
  }
135
90
  /** @internal */
136
91
  export function WidgetPanelsFrontstage() {
137
- const [layout, frontstageDef] = useLayoutStore();
92
+ const frontstageDef = useActiveFrontstageDef();
93
+ const layout = useLayoutStore(frontstageDef);
138
94
  React.useEffect(() => {
139
95
  const triggerWidowCloseProcessing = () => {
140
96
  frontstageDef && frontstageDef.setIsApplicationClosing(true);
141
97
  };
142
- frontstageDef && frontstageDef.setIsApplicationClosing(false);
143
98
  window.addEventListener("unload", triggerWidowCloseProcessing);
144
99
  return () => {
145
100
  window.removeEventListener("unload", triggerWidowCloseProcessing);
@@ -198,16 +153,17 @@ export function useLabels() {
198
153
  }
199
154
  function toTabArgs(widget) {
200
155
  const label = getWidgetLabel(widget.label);
201
- return {
156
+ const args = {
202
157
  allowedPanelTargets: widget.allowedPanelTargets?.map((location) => toPanelSide(location)),
203
158
  hideWithUiWhenFloating: !!widget.hideWithUiWhenFloating,
204
159
  canPopout: widget.canPopout,
205
160
  iconSpec: widget.iconSpec,
206
- isFloatingStateWindowResizable: widget.isFloatingStateWindowResizable,
161
+ isFloatingWidgetResizable: widget.isFloatingStateWindowResizable,
207
162
  label,
208
163
  preferredFloatingWidgetSize: widget.defaultFloatingSize,
209
164
  preferredPanelWidgetSize: widget.preferredPanelSize,
210
165
  };
166
+ return args;
211
167
  }
212
168
  /** @internal */
213
169
  export function addWidgets(state, widgets, side, widgetId) {
@@ -255,9 +211,15 @@ export function appendWidgets(state, widgetDefs, location, section) {
255
211
  preferredPanelWidgetSize,
256
212
  userSized,
257
213
  });
258
- if (widgetDef.isFloatingStateSupported &&
214
+ const savedTab = state.savedTabs.byId[widgetDef.id];
215
+ if (savedTab) {
216
+ state = addRemovedTab(state, widgetDef.id);
217
+ }
218
+ else if (widgetDef.isFloatingStateSupported &&
259
219
  widgetDef.defaultState === WidgetState.Floating) {
260
- const floatingContainerId = widgetDef.floatingContainerId ?? getUniqueId();
220
+ const floatingContainerId = widgetDef.floatingContainerId
221
+ ? widgetDef.floatingContainerId
222
+ : getUniqueId();
261
223
  const widgetContainerId = getWidgetId(location, section);
262
224
  const home = {
263
225
  side,
@@ -286,8 +248,6 @@ export function appendWidgets(state, widgetDefs, location, section) {
286
248
  bounds: containedBounds.toProps(),
287
249
  home,
288
250
  userSized,
289
- }, {
290
- isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
291
251
  });
292
252
  }
293
253
  }
@@ -311,24 +271,29 @@ export function appendWidgets(state, widgetDefs, location, section) {
311
271
  }
312
272
  }
313
273
  }
274
+ if (widgetDef.defaultState === WidgetState.Hidden) {
275
+ state = NineZoneStateReducer(state, {
276
+ type: "WIDGET_TAB_HIDE",
277
+ id: widgetDef.id,
278
+ });
279
+ }
314
280
  }
315
281
  return state;
316
282
  }
317
- function processPopoutWidgets(initialState, frontstageDef) {
318
- // istanbul ignore next
319
- if (!initialState.popoutWidgets)
320
- return initialState;
321
- // istanbul ignore next - not unit testing electron case that reopens popout windows
322
- if (initialState.popoutWidgets && ProcessDetector.isElectronAppFrontend) {
323
- if (initialState.popoutWidgets.allIds.length &&
324
- ProcessDetector.isElectronAppFrontend) {
325
- for (const widgetContainerId of initialState.popoutWidgets.allIds) {
326
- frontstageDef.openPopoutWidgetContainer(initialState, widgetContainerId);
327
- }
328
- }
329
- return initialState;
283
+ function processPopoutWidgets(state) {
284
+ // Electron reopens popout windows
285
+ if (ProcessDetector.isElectronAppFrontend) {
286
+ return state;
330
287
  }
331
- return convertAllPopupWidgetContainersToFloating(initialState);
288
+ for (const popoutWidgetId of state.popoutWidgets.allIds) {
289
+ const widget = state.widgets[popoutWidgetId];
290
+ const id = widget.tabs[0];
291
+ state = NineZoneStateReducer(state, {
292
+ type: "WIDGET_TAB_FLOAT",
293
+ id,
294
+ });
295
+ }
296
+ return state;
332
297
  }
333
298
  /** Adds frontstageDef widgets that are missing in NineZoneState.
334
299
  * @internal
@@ -367,7 +332,10 @@ function hideWidgets(state, frontstageDef) {
367
332
  if (!widgetDef)
368
333
  continue;
369
334
  if (widgetDef.defaultState === WidgetState.Hidden) {
370
- state = hideWidget(state, widgetDef);
335
+ state = NineZoneStateReducer(state, {
336
+ type: "WIDGET_TAB_HIDE",
337
+ id: widgetDef.id,
338
+ });
371
339
  }
372
340
  }
373
341
  return state;
@@ -375,7 +343,7 @@ function hideWidgets(state, frontstageDef) {
375
343
  /** Removes NineZoneState widgets that are missing in frontstageDef.
376
344
  * @internal
377
345
  */
378
- export function removeMissingWidgets(frontstageDef, state) {
346
+ function removeMissingWidgets(frontstageDef, state) {
379
347
  const toolSettingsTabId = state.toolSettings?.tabId;
380
348
  for (const [, tab] of Object.entries(state.tabs)) {
381
349
  if (tab.id === toolSettingsTabId)
@@ -383,6 +351,10 @@ export function removeMissingWidgets(frontstageDef, state) {
383
351
  const widgetDef = frontstageDef.findWidgetDef(tab.id);
384
352
  if (widgetDef)
385
353
  continue;
354
+ state = NineZoneStateReducer(state, {
355
+ type: "WIDGET_TAB_HIDE",
356
+ id: tab.id,
357
+ });
386
358
  state = removeTab(state, tab.id);
387
359
  }
388
360
  return state;
@@ -390,18 +362,6 @@ export function removeMissingWidgets(frontstageDef, state) {
390
362
  function getWidgetLabel(label) {
391
363
  return label === "" ? "Widget" : label;
392
364
  }
393
- function toStagePanelLocation(side) {
394
- switch (side) {
395
- case "bottom":
396
- return StagePanelLocation.Bottom;
397
- case "left":
398
- return StagePanelLocation.Left;
399
- case "right":
400
- return StagePanelLocation.Right;
401
- case "top":
402
- return StagePanelLocation.Top;
403
- }
404
- }
405
365
  /** @internal */
406
366
  export function getWidgetId(location, section) {
407
367
  switch (location) {
@@ -452,36 +412,27 @@ export function isFrontstageStateSettingResult(settingsResult) {
452
412
  }
453
413
  /** @internal */
454
414
  export function initializePanel(state, frontstageDef, location) {
455
- const panelSide = toPanelSide(location);
415
+ const side = toPanelSide(location);
456
416
  state = addPanelWidgets(state, frontstageDef, location);
457
417
  const panelDef = frontstageDef.getStagePanelDef(location);
458
418
  state = produce(state, (draft) => {
459
- const panel = draft.panels[panelSide];
460
- panel.minSize = panelDef?.minSize ?? panel.minSize;
419
+ const panel = draft.panels[side];
420
+ panel.minSize = panelDef?.initialConfig?.minSize ?? panel.minSize;
461
421
  panel.pinned = panelDef?.pinned ?? panel.pinned;
462
422
  panel.resizable = panelDef?.resizable ?? panel.resizable;
463
- if (panelDef?.maxSizeSpec) {
464
- panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide, state.size);
465
- }
466
- const size = panelDef?.size;
467
- panel.size =
468
- size === undefined
469
- ? size
470
- : Math.min(Math.max(size, panel.minSize), panel.maxSize);
423
+ panel.maxSize = panelDef?.initialConfig?.maxSize ?? panel.maxSize;
471
424
  });
472
- return state;
473
- }
474
- function getPanelMaxSize(maxSizeSpec, panel, nineZoneSize) {
475
- if (typeof maxSizeSpec === "number") {
476
- return maxSizeSpec;
425
+ if (panelDef?.size !== undefined) {
426
+ state = NineZoneStateReducer(state, {
427
+ type: "PANEL_SET_SIZE",
428
+ side,
429
+ size: panelDef.size,
430
+ });
477
431
  }
478
- const size = isHorizontalPanelSide(panel)
479
- ? nineZoneSize.height
480
- : nineZoneSize.width;
481
- return (maxSizeSpec.percentage / 100) * size;
432
+ return state;
482
433
  }
483
434
  /** @internal */
484
- export const stateVersion = 14; // this needs to be bumped when NineZoneState is changed (to recreate the layout).
435
+ export const stateVersion = 16; // this needs to be bumped when NineZoneState is changed (to recreate the layout).
485
436
  /** @internal */
486
437
  export function initializeNineZoneState(frontstageDef) {
487
438
  let nineZone = defaultNineZone;
@@ -519,7 +470,7 @@ export function initializeNineZoneState(frontstageDef) {
519
470
  nineZone = addDockedToolSettings(nineZone, toolSettingsTabId);
520
471
  }
521
472
  nineZone = hideWidgets(nineZone, frontstageDef);
522
- nineZone = processPopoutWidgets(nineZone, frontstageDef);
473
+ nineZone = processPopoutWidgets(nineZone);
523
474
  return nineZone;
524
475
  }
525
476
  /** Converts from saved NineZoneState to NineZoneState.
@@ -528,23 +479,23 @@ export function initializeNineZoneState(frontstageDef) {
528
479
  * @internal
529
480
  */
530
481
  export function restoreNineZoneState(frontstageDef, saved) {
531
- let restored = {
482
+ let state = {
532
483
  ...saved,
533
484
  tabs: {},
534
485
  };
535
486
  for (const [, tab] of Object.entries(saved.tabs)) {
536
487
  // Re-add the placeholder tab in order to correctly remove it from the state if WidgetDef is not found.
537
- restored = addTab(restored, tab.id);
488
+ state = addTab(state, tab.id);
538
489
  const widgetDef = frontstageDef.findWidgetDef(tab.id);
539
490
  if (!widgetDef) {
540
491
  Logger.logInfo(UiFramework.loggerCategory(restoreNineZoneState), "WidgetDef is not found for saved tab.", () => ({
541
492
  frontstageId: frontstageDef.id,
542
493
  tabId: tab.id,
543
494
  }));
544
- restored = removeTab(restored, tab.id);
495
+ state = removeTab(state, tab.id);
545
496
  continue;
546
497
  }
547
- restored = produce(restored, (draft) => {
498
+ state = produce(state, (draft) => {
548
499
  draft.tabs[tab.id] = {
549
500
  ...tab,
550
501
  ...toTabArgs(widgetDef),
@@ -553,7 +504,7 @@ export function restoreNineZoneState(frontstageDef, saved) {
553
504
  };
554
505
  });
555
506
  }
556
- restored = produce(restored, (draft) => {
507
+ state = produce(state, (draft) => {
557
508
  // remove center panel section if one is found in left or right panels
558
509
  const oldLeftMiddleIndex = saved.panels.left.widgets.findIndex((value) => value === "leftMiddle");
559
510
  // istanbul ignore next
@@ -584,15 +535,18 @@ export function restoreNineZoneState(frontstageDef, saved) {
584
535
  if (InternalFrontstageManager.nineZoneSize &&
585
536
  (0 !== InternalFrontstageManager.nineZoneSize.height ||
586
537
  0 !== InternalFrontstageManager.nineZoneSize.width)) {
587
- restored = FrameworkStateReducer(restored, {
538
+ state = NineZoneStateReducer(state, {
588
539
  type: "RESIZE",
589
540
  size: {
590
541
  height: InternalFrontstageManager.nineZoneSize.height,
591
542
  width: InternalFrontstageManager.nineZoneSize.width,
592
543
  },
593
- }, frontstageDef);
544
+ });
594
545
  }
595
- return restored;
546
+ state = addMissingWidgets(frontstageDef, state);
547
+ state = hideWidgets(state, frontstageDef);
548
+ state = processPopoutWidgets(state);
549
+ return state;
596
550
  }
597
551
  /** Prepares NineZoneState to be saved.
598
552
  * @note Removes toolSettings tab.
@@ -615,220 +569,10 @@ export function packNineZoneState(state) {
615
569
  });
616
570
  return packed;
617
571
  }
618
- // istanbul ignore next
619
- function packSavedWidgets(frontstageDef) {
620
- let savedWidgets = [];
621
- for (const widgetDef of frontstageDef.widgetDefs) {
622
- const id = widgetDef.id;
623
- const initialWidget = {
624
- id,
625
- };
626
- const widget = produce(initialWidget, (draft) => {
627
- if (widgetDef.tabLocation) {
628
- draft.tabLocation = { ...widgetDef.tabLocation };
629
- }
630
- if (widgetDef.popoutBounds) {
631
- draft.popoutBounds = widgetDef.popoutBounds.toProps();
632
- }
633
- });
634
- if (widget === initialWidget)
635
- continue;
636
- savedWidgets.push(widget);
637
- }
638
- // Add previously saved widgets.
639
- const prevSavedWidgets = frontstageDef.savedWidgetDefs || [];
640
- for (const prevWidget of prevSavedWidgets) {
641
- if (savedWidgets.find((w) => w.id === prevWidget.id))
642
- continue;
643
- savedWidgets.push(prevWidget);
644
- }
645
- // Limit number of saved widgets.
646
- const maxWidgets = 100;
647
- if (savedWidgets.length > maxWidgets)
648
- savedWidgets = savedWidgets.slice(0, maxWidgets);
649
- return savedWidgets;
650
- }
651
- // istanbul ignore next
652
- function restoreSavedWidgets(frontstage) {
653
- const savedWidgets = frontstage.savedWidgetDefs || [];
654
- for (const savedWidget of savedWidgets) {
655
- const widgetId = savedWidget.id;
656
- const widgetDef = frontstage.findWidgetDef(widgetId);
657
- if (!widgetDef)
658
- continue;
659
- if (savedWidget.tabLocation) {
660
- widgetDef.tabLocation = { ...savedWidget.tabLocation };
661
- }
662
- if (savedWidget.popoutBounds) {
663
- widgetDef.popoutBounds = Rectangle.create(savedWidget.popoutBounds);
664
- }
665
- }
666
- }
667
572
  /** @internal */
668
573
  export function isPanelCollapsed(panelState) {
669
574
  return panelState !== StagePanelState.Open;
670
575
  }
671
- function addHiddenWidget(state, widgetDef) {
672
- const tabLocation = widgetDef.tabLocation || widgetDef.defaultTabLocation;
673
- const tabId = widgetDef.id;
674
- const { widgetId, tabIndex } = tabLocation;
675
- if (widgetId in state.widgets) {
676
- // Add to an existing widget (by widget id).
677
- return insertTabToWidget(state, tabId, widgetId, tabIndex);
678
- }
679
- else if (tabLocation.floatingWidget) {
680
- const floatingWidget = tabLocation.floatingWidget;
681
- assert(widgetId === floatingWidget.id);
682
- // Add to a new floating widget.
683
- const nzBounds = Rectangle.createFromSize(state.size);
684
- const bounds = Rectangle.create(floatingWidget.bounds).containIn(nzBounds);
685
- return addFloatingWidget(state, floatingWidget.id, [tabId], {
686
- ...floatingWidget,
687
- bounds: bounds.toProps(),
688
- });
689
- }
690
- // Add to a panel section.
691
- const panel = state.panels[tabLocation.side];
692
- // Add to existing panel section.
693
- if (panel.widgets.length >= panel.maxWidgetCount) {
694
- const sectionIndex = Math.min(panel.maxWidgetCount - 1, tabLocation.widgetIndex);
695
- const sectionId = panel.widgets[sectionIndex];
696
- return insertTabToWidget(state, tabId, sectionId, tabLocation.tabIndex);
697
- }
698
- // Create a new panel section.
699
- const newSectionId = getUniqueId();
700
- return insertPanelWidget(state, panel.side, newSectionId, [tabId], tabLocation.widgetIndex);
701
- }
702
- /** @internal */
703
- export function setWidgetState(state, widgetDef, widgetState) {
704
- if (widgetState === WidgetState.Hidden) {
705
- return hideWidget(state, widgetDef);
706
- }
707
- else if (widgetState === WidgetState.Open) {
708
- const id = widgetDef.id;
709
- if (widgetDef.isToolSettings) {
710
- if (!state.toolSettings && !widgetDef.tabLocation) {
711
- state = addDockedToolSettings(state, id);
712
- }
713
- if (state.toolSettings?.type === "docked")
714
- return state;
715
- }
716
- let location = getTabLocation(state, id);
717
- if (!location) {
718
- state = addHiddenWidget(state, widgetDef);
719
- location = getTabLocation(state, id);
720
- if (widgetDef.isToolSettings) {
721
- state = addWidgetToolSettings(state, id);
722
- }
723
- }
724
- return produce(state, (draft) => {
725
- assert(!!location);
726
- const widget = draft.widgets[location.widgetId];
727
- widget.minimized = false;
728
- widget.activeTabId = id;
729
- if (isFloatingTabLocation(location)) {
730
- const floatingWidget = draft.floatingWidgets.byId[location.floatingWidgetId];
731
- floatingWidget.hidden = false;
732
- // istanbul ignore else
733
- }
734
- else if (isPanelTabLocation(location)) {
735
- const panel = draft.panels[location.side];
736
- panel.collapsed = false;
737
- if (undefined === panel.size || 0 === panel.size) {
738
- // istanbul ignore next
739
- panel.size = panel.minSize ?? 200;
740
- }
741
- }
742
- });
743
- }
744
- else if (widgetState === WidgetState.Closed) {
745
- const id = widgetDef.id;
746
- if (widgetDef.isToolSettings && state.toolSettings?.type !== "widget") {
747
- return state;
748
- }
749
- let location = getTabLocation(state, id);
750
- if (!location) {
751
- state = addHiddenWidget(state, widgetDef);
752
- location = getTabLocation(state, id);
753
- }
754
- // TODO: should change activeTabId of a widget with multiple tabs.
755
- return produce(state, (draft) => {
756
- assert(!!location);
757
- const widget = draft.widgets[location.widgetId];
758
- if (isFloatingTabLocation(location)) {
759
- if (id === widget.activeTabId) {
760
- widget.minimized = true;
761
- }
762
- }
763
- });
764
- }
765
- else if (widgetState === WidgetState.Floating) {
766
- const id = widgetDef.id;
767
- let location = getTabLocation(state, id);
768
- if (!location) {
769
- state = addHiddenWidget(state, widgetDef);
770
- location = getTabLocation(state, id);
771
- }
772
- assert(!!location);
773
- if (isFloatingTabLocation(location))
774
- return state;
775
- // Widget is not floating.
776
- state = removeTabFromWidget(state, id);
777
- const bounds = widgetDef.tabLocation?.floatingWidget?.bounds;
778
- state = addFloatingWidget(state, getUniqueId(), [id], { bounds });
779
- if (widgetDef.isToolSettings) {
780
- if (state.toolSettings?.type === "docked") {
781
- state = removeToolSettings(state);
782
- }
783
- if (!state.toolSettings) {
784
- state = addWidgetToolSettings(state, id);
785
- }
786
- }
787
- }
788
- return state;
789
- }
790
- /** Stores widget location and hides it in the UI. */
791
- function hideWidget(state, widgetDef) {
792
- const toolSettingsTabId = state.toolSettings?.tabId;
793
- if (widgetDef.id === toolSettingsTabId) {
794
- widgetDef.tabLocation = undefined;
795
- state = produce(state, (draft) => {
796
- draft.toolSettings = undefined;
797
- });
798
- if (state.toolSettings?.type === "docked")
799
- return state;
800
- }
801
- const location = getTabLocation(state, widgetDef.id);
802
- if (!location)
803
- return state;
804
- // istanbul ignore else
805
- if (isFloatingTabLocation(location)) {
806
- const floatingWidget = state.floatingWidgets.byId[location.widgetId];
807
- widgetDef.setFloatingContainerId(location.floatingWidgetId);
808
- widgetDef.tabLocation = {
809
- side: floatingWidget.home.side,
810
- tabIndex: floatingWidget.home.widgetIndex,
811
- widgetId: floatingWidget.id,
812
- widgetIndex: floatingWidget.home.widgetIndex,
813
- floatingWidget,
814
- };
815
- }
816
- else if (!isPopoutTabLocation(location)) {
817
- const widgetId = location.widgetId;
818
- const side = isPanelTabLocation(location) ? location.side : "left";
819
- const widgetIndex = isPanelTabLocation(location)
820
- ? state.panels[side].widgets.indexOf(widgetId)
821
- : 0;
822
- const tabIndex = state.widgets[location.widgetId].tabs.indexOf(widgetDef.id);
823
- widgetDef.tabLocation = {
824
- side,
825
- tabIndex,
826
- widgetId,
827
- widgetIndex,
828
- };
829
- }
830
- return removeTabFromWidget(state, widgetDef.id);
831
- }
832
576
  /** @internal */
833
577
  export function showWidget(state, id) {
834
578
  const location = getTabLocation(state, id);
@@ -866,15 +610,6 @@ export function expandWidget(state, id) {
866
610
  });
867
611
  }
868
612
  /** @internal */
869
- export function setWidgetLabel(state, id, label) {
870
- if (!(id in state.tabs))
871
- return state;
872
- return produce(state, (draft) => {
873
- const tab = draft.tabs[id];
874
- tab.label = label;
875
- });
876
- }
877
- /** @internal */
878
613
  export function useSavedFrontstageState(frontstageDef) {
879
614
  const uiStateStorage = useUiStateStorageHandler();
880
615
  const uiStateStorageRef = React.useRef(uiStateStorage);
@@ -891,7 +626,7 @@ export function useSavedFrontstageState(frontstageDef) {
891
626
  React.useEffect(() => {
892
627
  async function fetchFrontstageState() {
893
628
  if (frontstageDef.nineZoneState) {
894
- frontstageDef.nineZoneState = processPopoutWidgets(frontstageDef.nineZoneState, frontstageDef);
629
+ frontstageDef.nineZoneState = processPopoutWidgets(frontstageDef.nineZoneState);
895
630
  return;
896
631
  }
897
632
  const id = frontstageDef.id;
@@ -903,13 +638,7 @@ export function useSavedFrontstageState(frontstageDef) {
903
638
  const setting = settingResult.setting;
904
639
  if (setting.version === version &&
905
640
  setting.stateVersion === stateVersion) {
906
- const restored = restoreNineZoneState(frontstageDef, setting.nineZone);
907
- frontstageDef.savedWidgetDefs = setting.widgets;
908
- restoreSavedWidgets(frontstageDef);
909
- let state = addMissingWidgets(frontstageDef, restored);
910
- state = hideWidgets(state, frontstageDef);
911
- state = processPopoutWidgets(state, frontstageDef);
912
- frontstageDef.nineZoneState = state;
641
+ frontstageDef.nineZoneState = restoreNineZoneState(frontstageDef, setting.nineZone);
913
642
  return;
914
643
  }
915
644
  }
@@ -924,14 +653,11 @@ export function useSaveFrontstageSettings(frontstageDef, store) {
924
653
  const saveSetting = React.useMemo(() => {
925
654
  const debounced = debounce(async (frontstage, state) => {
926
655
  const id = frontstage.id;
927
- const widgets = packSavedWidgets(frontstage);
928
- frontstage.savedWidgetDefs = widgets;
929
656
  const setting = {
930
657
  id,
931
658
  version: frontstage.version,
932
659
  stateVersion,
933
660
  nineZone: packNineZoneState(state),
934
- widgets,
935
661
  };
936
662
  await uiSettingsStorage.saveSetting(FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id), setting);
937
663
  }, 1000);
@@ -979,49 +705,11 @@ function debounce(func, duration) {
979
705
  };
980
706
  return debounced;
981
707
  }
982
- const createListener = (frontstageDef, listener) => {
983
- return (...args) => {
984
- if (!frontstageDef.nineZoneState)
985
- return;
986
- listener(...args);
987
- };
988
- };
989
708
  /** @internal */
990
709
  export function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
991
- React.useEffect(() => {
992
- return UiFramework.frontstages.onWidgetStateChangedEvent.addListener(({ widgetDef, widgetState }) => {
993
- if (!frontstageDef.nineZoneState)
994
- return;
995
- frontstageDef.nineZoneState = setWidgetState(frontstageDef.nineZoneState, widgetDef, widgetState);
996
- });
997
- }, [frontstageDef]);
998
- React.useEffect(() => {
999
- const listener = createListener(frontstageDef, ({ widgetDef }) => {
1000
- assert(!!frontstageDef.nineZoneState);
1001
- const nineZoneState = setWidgetState(frontstageDef.nineZoneState, widgetDef, WidgetState.Open);
1002
- frontstageDef.nineZoneState = showWidget(nineZoneState, widgetDef.id);
1003
- });
1004
- InternalFrontstageManager.onWidgetShowEvent.addListener(listener);
1005
- return () => {
1006
- InternalFrontstageManager.onWidgetShowEvent.removeListener(listener);
1007
- };
1008
- }, [frontstageDef]);
1009
- React.useEffect(() => {
1010
- const listener = createListener(frontstageDef, ({ widgetDef }) => {
1011
- assert(!!frontstageDef.nineZoneState);
1012
- let nineZoneState = setWidgetState(frontstageDef.nineZoneState, widgetDef, WidgetState.Open);
1013
- nineZoneState = showWidget(nineZoneState, widgetDef.id);
1014
- nineZoneState = expandWidget(nineZoneState, widgetDef.id);
1015
- frontstageDef.nineZoneState = nineZoneState;
1016
- });
1017
- InternalFrontstageManager.onWidgetExpandEvent.addListener(listener);
1018
- return () => {
1019
- InternalFrontstageManager.onWidgetExpandEvent.removeListener(listener);
1020
- };
1021
- }, [frontstageDef]);
1022
710
  const uiSettingsStorage = useUiStateStorageHandler();
1023
711
  React.useEffect(() => {
1024
- const listener = (args) => {
712
+ return InternalFrontstageManager.onFrontstageRestoreLayoutEvent.addListener((args) => {
1025
713
  // TODO: track restoring frontstages to support workflows: i.e. prevent loading frontstage OR saving layout when delete is pending
1026
714
  void uiSettingsStorage.deleteSetting(FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(args.frontstageDef.id));
1027
715
  if (frontstageDef.id === args.frontstageDef.id) {
@@ -1031,52 +719,36 @@ export function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel)
1031
719
  else {
1032
720
  args.frontstageDef.nineZoneState = undefined;
1033
721
  }
1034
- };
1035
- InternalFrontstageManager.onFrontstageRestoreLayoutEvent.addListener(listener);
1036
- return () => {
1037
- InternalFrontstageManager.onFrontstageRestoreLayoutEvent.removeListener(listener);
1038
- };
1039
- }, [uiSettingsStorage, frontstageDef]);
1040
- React.useEffect(() => {
1041
- const listener = createListener(frontstageDef, ({ widgetDef }) => {
1042
- assert(!!frontstageDef.nineZoneState);
1043
- const label = widgetDef.label;
1044
- frontstageDef.nineZoneState = setWidgetLabel(frontstageDef.nineZoneState, widgetDef.id, label);
1045
722
  });
1046
- InternalFrontstageManager.onWidgetLabelChangedEvent.addListener(listener);
1047
- return () => {
1048
- InternalFrontstageManager.onWidgetLabelChangedEvent.removeListener(listener);
1049
- };
1050
- }, [frontstageDef]);
723
+ }, [uiSettingsStorage, frontstageDef]);
1051
724
  const defaultLabel = React.useMemo(() => UiFramework.translate("widget.labels.toolSettings"), []);
1052
725
  React.useEffect(() => {
1053
- const updateLabel = createListener(frontstageDef, () => {
726
+ const updateLabel = () => {
727
+ const state = frontstageDef.nineZoneState;
728
+ if (!state)
729
+ return;
730
+ const toolSettingsTabId = state.toolSettings?.tabId;
731
+ if (!toolSettingsTabId)
732
+ return;
1054
733
  const toolId = UiFramework.frontstages.activeToolId;
1055
- assert(!!frontstageDef.nineZoneState);
1056
734
  const label = useToolAsToolSettingsLabel
1057
735
  ? IModelApp.tools.find(toolId)?.flyover || defaultLabel
1058
736
  : defaultLabel;
1059
- const toolSettingsTabId = frontstageDef.nineZoneState.toolSettings?.tabId;
1060
- if (!toolSettingsTabId)
1061
- return;
1062
- frontstageDef.nineZoneState = setWidgetLabel(frontstageDef.nineZoneState, toolSettingsTabId, label);
1063
- });
737
+ frontstageDef.dispatch({
738
+ type: "WIDGET_TAB_SET_LABEL",
739
+ id: toolSettingsTabId,
740
+ label,
741
+ });
742
+ };
1064
743
  // Whenever the frontstageDef or the useTool... changes, keep the label up to date.
1065
744
  updateLabel();
745
+ const removeListenerFuncs = [];
1066
746
  // If useTool... is true, listen for events to keep up the label up to date.
1067
747
  if (useToolAsToolSettingsLabel) {
1068
- UiFramework.frontstages.onFrontstageReadyEvent.addListener(updateLabel);
1069
- InternalFrontstageManager.onFrontstageRestoreLayoutEvent.addListener(updateLabel);
1070
- UiFramework.frontstages.onToolActivatedEvent.addListener(updateLabel);
1071
- UiFramework.frontstages.onToolSettingsReloadEvent.addListener(updateLabel);
748
+ removeListenerFuncs.push(UiFramework.frontstages.onFrontstageReadyEvent.addListener(updateLabel), InternalFrontstageManager.onFrontstageRestoreLayoutEvent.addListener(updateLabel), UiFramework.frontstages.onToolActivatedEvent.addListener(updateLabel), UiFramework.frontstages.onToolSettingsReloadEvent.addListener(updateLabel));
1072
749
  }
1073
750
  return () => {
1074
- if (useToolAsToolSettingsLabel) {
1075
- UiFramework.frontstages.onFrontstageReadyEvent.removeListener(updateLabel);
1076
- InternalFrontstageManager.onFrontstageRestoreLayoutEvent.removeListener(updateLabel);
1077
- UiFramework.frontstages.onToolActivatedEvent.removeListener(updateLabel);
1078
- UiFramework.frontstages.onToolSettingsReloadEvent.removeListener(updateLabel);
1079
- }
751
+ removeListenerFuncs.forEach((removeListener) => removeListener());
1080
752
  };
1081
753
  }, [frontstageDef, useToolAsToolSettingsLabel, defaultLabel]);
1082
754
  }
@@ -1086,23 +758,22 @@ export function useItemsManager(frontstageDef) {
1086
758
  const refreshNineZoneState = (def) => {
1087
759
  // Fired for both registered/unregistered. Update definitions and remove/add missing widgets.
1088
760
  def.updateWidgetDefs();
1089
- restoreSavedWidgets(def);
1090
761
  let state = def.nineZoneState;
1091
762
  if (!state)
1092
763
  return;
1093
764
  state = addMissingWidgets(def, state);
1094
765
  state = removeMissingWidgets(def, state);
1095
- state = hideWidgets(state, def); // TODO: should only apply to widgets provided by registered provider in onUiProviderRegisteredEvent.
1096
766
  def.nineZoneState = state;
1097
767
  };
1098
768
  React.useEffect(() => {
1099
- const remove = UiItemsManager.onUiProviderRegisteredEvent.addListener(() => {
1100
- refreshNineZoneState(frontstageDef);
1101
- });
1102
769
  // Need to refresh anytime frontstageDef changes because uiItemsProvider may have added something to
1103
770
  // another stage before it was possibly unloaded in this stage.
1104
771
  refreshNineZoneState(frontstageDef);
1105
- return remove;
772
+ }, [frontstageDef]);
773
+ React.useEffect(() => {
774
+ return UiItemsManager.onUiProviderRegisteredEvent.addListener(() => {
775
+ refreshNineZoneState(frontstageDef);
776
+ });
1106
777
  }, [frontstageDef]);
1107
778
  }
1108
779
  // istanbul ignore next