@itwin/appui-react 3.4.0-dev.9 → 3.5.0-dev.12

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 (131) hide show
  1. package/CHANGELOG.md +43 -1
  2. package/lib/cjs/appui-react/childwindow/ChildWindowManager.d.ts.map +1 -1
  3. package/lib/cjs/appui-react/childwindow/ChildWindowManager.js +4 -5
  4. package/lib/cjs/appui-react/childwindow/ChildWindowManager.js.map +1 -1
  5. package/lib/cjs/appui-react/dialog/DialogManagerBase.d.ts +7 -0
  6. package/lib/cjs/appui-react/dialog/DialogManagerBase.d.ts.map +1 -1
  7. package/lib/cjs/appui-react/dialog/DialogManagerBase.js +23 -0
  8. package/lib/cjs/appui-react/dialog/DialogManagerBase.js.map +1 -1
  9. package/lib/cjs/appui-react/dialog/ModelessDialogManager.d.ts +0 -2
  10. package/lib/cjs/appui-react/dialog/ModelessDialogManager.d.ts.map +1 -1
  11. package/lib/cjs/appui-react/dialog/ModelessDialogManager.js +6 -18
  12. package/lib/cjs/appui-react/dialog/ModelessDialogManager.js.map +1 -1
  13. package/lib/cjs/appui-react/dialog/StandardMessageBox.d.ts.map +1 -1
  14. package/lib/cjs/appui-react/dialog/StandardMessageBox.js +2 -1
  15. package/lib/cjs/appui-react/dialog/StandardMessageBox.js.map +1 -1
  16. package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts +13 -1
  17. package/lib/cjs/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
  18. package/lib/cjs/appui-react/frontstage/FrontstageDef.js +140 -96
  19. package/lib/cjs/appui-react/frontstage/FrontstageDef.js.map +1 -1
  20. package/lib/cjs/appui-react/frontstage/FrontstageManager.d.ts +2 -0
  21. package/lib/cjs/appui-react/frontstage/FrontstageManager.d.ts.map +1 -1
  22. package/lib/cjs/appui-react/frontstage/FrontstageManager.js +4 -0
  23. package/lib/cjs/appui-react/frontstage/FrontstageManager.js.map +1 -1
  24. package/lib/cjs/appui-react/imodel-components/category-tree/Categories.json +2 -2
  25. package/lib/cjs/appui-react/imodel-components/models-tree/Hierarchy.GroupedByClass.json +1 -0
  26. package/lib/cjs/appui-react/imodel-components/models-tree/Hierarchy.json +1 -0
  27. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsTree.d.ts +1 -1
  28. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsTree.d.ts.map +1 -1
  29. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsTree.js +11 -8
  30. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsTree.js.map +1 -1
  31. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.d.ts +15 -1
  32. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.d.ts.map +1 -1
  33. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.js +5 -2
  34. package/lib/cjs/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.js.map +1 -1
  35. package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts +0 -6
  36. package/lib/cjs/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
  37. package/lib/cjs/appui-react/tools/CoreToolDefinitions.d.ts +1 -0
  38. package/lib/cjs/appui-react/tools/CoreToolDefinitions.d.ts.map +1 -1
  39. package/lib/cjs/appui-react/tools/CoreToolDefinitions.js +23 -4
  40. package/lib/cjs/appui-react/tools/CoreToolDefinitions.js.map +1 -1
  41. package/lib/cjs/appui-react/tools/RestoreLayoutTool.d.ts +9 -0
  42. package/lib/cjs/appui-react/tools/RestoreLayoutTool.d.ts.map +1 -1
  43. package/lib/cjs/appui-react/tools/RestoreLayoutTool.js +17 -1
  44. package/lib/cjs/appui-react/tools/RestoreLayoutTool.js.map +1 -1
  45. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsProvider.d.ts.map +1 -1
  46. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsProvider.js +2 -0
  47. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsProvider.js.map +1 -1
  48. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.d.ts +1 -0
  49. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.d.ts.map +1 -1
  50. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.js +2 -0
  51. package/lib/cjs/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.js.map +1 -1
  52. package/lib/cjs/appui-react/widget-panels/FloatingWidget.d.ts +7 -0
  53. package/lib/cjs/appui-react/widget-panels/FloatingWidget.d.ts.map +1 -0
  54. package/lib/cjs/appui-react/widget-panels/FloatingWidget.js +19 -0
  55. package/lib/cjs/appui-react/widget-panels/FloatingWidget.js.map +1 -0
  56. package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts +20 -697
  57. package/lib/cjs/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
  58. package/lib/cjs/appui-react/widget-panels/Frontstage.js +300 -271
  59. package/lib/cjs/appui-react/widget-panels/Frontstage.js.map +1 -1
  60. package/lib/cjs/appui-react/widget-panels/useWidgetDirection.js +1 -1
  61. package/lib/cjs/appui-react/widget-panels/useWidgetDirection.js.map +1 -1
  62. package/lib/cjs/appui-react/widgets/WidgetDef.d.ts +16 -6
  63. package/lib/cjs/appui-react/widgets/WidgetDef.d.ts.map +1 -1
  64. package/lib/cjs/appui-react/widgets/WidgetDef.js +13 -1
  65. package/lib/cjs/appui-react/widgets/WidgetDef.js.map +1 -1
  66. package/lib/esm/appui-react/childwindow/ChildWindowManager.d.ts.map +1 -1
  67. package/lib/esm/appui-react/childwindow/ChildWindowManager.js +4 -5
  68. package/lib/esm/appui-react/childwindow/ChildWindowManager.js.map +1 -1
  69. package/lib/esm/appui-react/dialog/DialogManagerBase.d.ts +7 -0
  70. package/lib/esm/appui-react/dialog/DialogManagerBase.d.ts.map +1 -1
  71. package/lib/esm/appui-react/dialog/DialogManagerBase.js +23 -0
  72. package/lib/esm/appui-react/dialog/DialogManagerBase.js.map +1 -1
  73. package/lib/esm/appui-react/dialog/ModelessDialogManager.d.ts +0 -2
  74. package/lib/esm/appui-react/dialog/ModelessDialogManager.d.ts.map +1 -1
  75. package/lib/esm/appui-react/dialog/ModelessDialogManager.js +6 -18
  76. package/lib/esm/appui-react/dialog/ModelessDialogManager.js.map +1 -1
  77. package/lib/esm/appui-react/dialog/StandardMessageBox.d.ts.map +1 -1
  78. package/lib/esm/appui-react/dialog/StandardMessageBox.js +2 -1
  79. package/lib/esm/appui-react/dialog/StandardMessageBox.js.map +1 -1
  80. package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts +13 -1
  81. package/lib/esm/appui-react/frontstage/FrontstageDef.d.ts.map +1 -1
  82. package/lib/esm/appui-react/frontstage/FrontstageDef.js +142 -98
  83. package/lib/esm/appui-react/frontstage/FrontstageDef.js.map +1 -1
  84. package/lib/esm/appui-react/frontstage/FrontstageManager.d.ts +2 -0
  85. package/lib/esm/appui-react/frontstage/FrontstageManager.d.ts.map +1 -1
  86. package/lib/esm/appui-react/frontstage/FrontstageManager.js +4 -0
  87. package/lib/esm/appui-react/frontstage/FrontstageManager.js.map +1 -1
  88. package/lib/esm/appui-react/imodel-components/category-tree/Categories.json +2 -2
  89. package/lib/esm/appui-react/imodel-components/models-tree/Hierarchy.GroupedByClass.json +1 -0
  90. package/lib/esm/appui-react/imodel-components/models-tree/Hierarchy.json +1 -0
  91. package/lib/esm/appui-react/imodel-components/models-tree/ModelsTree.d.ts +1 -1
  92. package/lib/esm/appui-react/imodel-components/models-tree/ModelsTree.d.ts.map +1 -1
  93. package/lib/esm/appui-react/imodel-components/models-tree/ModelsTree.js +12 -9
  94. package/lib/esm/appui-react/imodel-components/models-tree/ModelsTree.js.map +1 -1
  95. package/lib/esm/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.d.ts +15 -1
  96. package/lib/esm/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.d.ts.map +1 -1
  97. package/lib/esm/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.js +4 -2
  98. package/lib/esm/appui-react/imodel-components/models-tree/ModelsVisibilityHandler.js.map +1 -1
  99. package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts +0 -6
  100. package/lib/esm/appui-react/stagepanels/StagePanelDef.d.ts.map +1 -1
  101. package/lib/esm/appui-react/tools/CoreToolDefinitions.d.ts +1 -0
  102. package/lib/esm/appui-react/tools/CoreToolDefinitions.d.ts.map +1 -1
  103. package/lib/esm/appui-react/tools/CoreToolDefinitions.js +25 -6
  104. package/lib/esm/appui-react/tools/CoreToolDefinitions.js.map +1 -1
  105. package/lib/esm/appui-react/tools/RestoreLayoutTool.d.ts +9 -0
  106. package/lib/esm/appui-react/tools/RestoreLayoutTool.d.ts.map +1 -1
  107. package/lib/esm/appui-react/tools/RestoreLayoutTool.js +15 -0
  108. package/lib/esm/appui-react/tools/RestoreLayoutTool.js.map +1 -1
  109. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsProvider.d.ts.map +1 -1
  110. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsProvider.js +2 -0
  111. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsProvider.js.map +1 -1
  112. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.d.ts +1 -0
  113. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.d.ts.map +1 -1
  114. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.js +2 -0
  115. package/lib/esm/appui-react/ui-items-provider/StandardNavigationToolsUiItemsProvider.js.map +1 -1
  116. package/lib/esm/appui-react/widget-panels/FloatingWidget.d.ts +7 -0
  117. package/lib/esm/appui-react/widget-panels/FloatingWidget.d.ts.map +1 -0
  118. package/lib/esm/appui-react/widget-panels/FloatingWidget.js +15 -0
  119. package/lib/esm/appui-react/widget-panels/FloatingWidget.js.map +1 -0
  120. package/lib/esm/appui-react/widget-panels/Frontstage.d.ts +20 -697
  121. package/lib/esm/appui-react/widget-panels/Frontstage.d.ts.map +1 -1
  122. package/lib/esm/appui-react/widget-panels/Frontstage.js +291 -265
  123. package/lib/esm/appui-react/widget-panels/Frontstage.js.map +1 -1
  124. package/lib/esm/appui-react/widget-panels/useWidgetDirection.js +2 -2
  125. package/lib/esm/appui-react/widget-panels/useWidgetDirection.js.map +1 -1
  126. package/lib/esm/appui-react/widgets/WidgetDef.d.ts +16 -6
  127. package/lib/esm/appui-react/widgets/WidgetDef.d.ts.map +1 -1
  128. package/lib/esm/appui-react/widgets/WidgetDef.js +13 -1
  129. package/lib/esm/appui-react/widgets/WidgetDef.js.map +1 -1
  130. package/lib/public/locales/en/UiFramework.json +10 -3
  131. package/package.json +37 -35
@@ -5,7 +5,7 @@
5
5
  *--------------------------------------------------------------------------------------------*/
6
6
  /* eslint-disable deprecation/deprecation */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.saveFrontstagePopoutWidgetSizeAndPosition = exports.useItemsManager = exports.useFrontstageManager = exports.getFrontstageStateSettingName = exports.FRONTSTAGE_SETTINGS_NAMESPACE = exports.useSaveFrontstageSettings = exports.useSavedFrontstageState = exports.setWidgetLabel = exports.expandWidget = exports.showWidget = exports.setWidgetState = exports.isPanelCollapsed = exports.packNineZoneState = exports.restoreNineZoneState = exports.initializeNineZoneState = exports.initializePanel = exports.isFrontstageStateSettingResult = exports.addPanelWidgets = exports.getPanelZoneWidgets = exports.getWidgetId = exports.removeMissingWidgets = exports.addMissingWidgets = exports.appendWidgets = exports.addWidgets = exports.useLabels = exports.ActiveFrontstageDefProvider = exports.WidgetPanelsFrontstage = exports.useNineZoneDispatch = exports.useUpdateNineZoneSize = exports.useNineZoneState = void 0;
8
+ exports.useItemsManager = exports.useFrontstageManager = exports.getFrontstageStateSettingName = exports.FRONTSTAGE_SETTINGS_NAMESPACE = exports.useSaveFrontstageSettings = exports.useSavedFrontstageState = exports.setWidgetLabel = exports.expandWidget = exports.showWidget = exports.setWidgetState = exports.isPanelCollapsed = exports.packNineZoneState = exports.restoreNineZoneState = exports.initializeNineZoneState = exports.initializePanel = exports.isFrontstageStateSettingResult = exports.addPanelWidgets = exports.getPanelZoneWidgets = exports.getWidgetId = exports.removeMissingWidgets = exports.addMissingWidgets = exports.appendWidgets = exports.addWidgets = exports.useLabels = exports.ActiveFrontstageDefProvider = exports.WidgetPanelsFrontstage = exports.useNineZoneDispatch = exports.useUpdateNineZoneSize = exports.useNineZoneState = void 0;
9
9
  /** @packageDocumentation
10
10
  * @module Frontstage
11
11
  */
@@ -35,6 +35,7 @@ const useEscapeSetFocusToHome_1 = require("../hooks/useEscapeSetFocusToHome");
35
35
  const react_redux_1 = require("react-redux");
36
36
  const useUiVisibility_1 = require("../hooks/useUiVisibility");
37
37
  const core_frontend_1 = require("@itwin/core-frontend");
38
+ const FloatingWidget_1 = require("./FloatingWidget");
38
39
  const panelZoneKeys = ["start", "end"];
39
40
  const WidgetInternals = React.memo(function WidgetInternals() {
40
41
  const activeModalFrontstageInfo = (0, ModalFrontstageComposer_1.useActiveModalFrontstageInfo)();
@@ -177,6 +178,7 @@ exports.WidgetPanelsFrontstage = React.memo(function WidgetPanelsFrontstage() {
177
178
  });
178
179
  const defaultNineZone = (0, appui_layout_react_1.createNineZoneState)();
179
180
  const tabElement = React.createElement(Tab_1.WidgetPanelsTab, null);
181
+ const floatingWidgetElement = React.createElement(FloatingWidget_1.FloatingWidget, null);
180
182
  /** @internal */
181
183
  function ActiveFrontstageDefProvider({ frontstageDef }) {
182
184
  let nineZone = useNineZoneState(frontstageDef);
@@ -207,7 +209,7 @@ function ActiveFrontstageDefProvider({ frontstageDef }) {
207
209
  useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel);
208
210
  const handleKeyDown = (0, useEscapeSetFocusToHome_1.useEscapeSetFocusToHome)();
209
211
  return (React.createElement("div", { className: "uifw-widgetPanels-frontstage", onKeyDown: handleKeyDown, role: "presentation" },
210
- React.createElement(appui_layout_react_1.NineZone, { dispatch: dispatch, labels: labels, state: nineZone, tab: tabElement, showWidgetIcon: showWidgetIcon, autoCollapseUnpinnedPanels: autoCollapseUnpinnedPanels, toolSettingsContent: toolSettingsContent, widgetContent: widgetContent, animateDockedToolSettings: animateToolSettings, uiIsVisible: uiIsVisible }, widgetPanelsFrontstage)));
212
+ React.createElement(appui_layout_react_1.NineZone, { dispatch: dispatch, labels: labels, state: nineZone, tab: tabElement, floatingWidget: floatingWidgetElement, showWidgetIcon: showWidgetIcon, autoCollapseUnpinnedPanels: autoCollapseUnpinnedPanels, toolSettingsContent: toolSettingsContent, widgetContent: widgetContent, animateDockedToolSettings: animateToolSettings, uiIsVisible: uiIsVisible }, widgetPanelsFrontstage)));
211
213
  }
212
214
  exports.ActiveFrontstageDefProvider = ActiveFrontstageDefProvider;
213
215
  /** @internal */
@@ -241,6 +243,7 @@ function addWidgets(state, widgets, side, widgetId) {
241
243
  canPopout: widget.canPopout,
242
244
  isFloatingStateWindowResizable: widget.isFloatingStateWindowResizable,
243
245
  hideWithUiWhenFloating: !!widget.hideWithUiWhenFloating,
246
+ allowedPanelTargets: widget.allowedPanelTargets,
244
247
  });
245
248
  tabs.push(widget.id);
246
249
  }
@@ -268,7 +271,6 @@ function appendWidgets(state, widgetDefs, side, preferredWidgetIndex) {
268
271
  const saveTab = state.tabs[widgetDef.id];
269
272
  const preferredPanelWidgetSize = saveTab ? saveTab.preferredPanelWidgetSize : widgetDef.preferredPanelSize;
270
273
  const preferredFloatingWidgetSize = saveTab ? saveTab.preferredFloatingWidgetSize : widgetDef.defaultFloatingSize;
271
- const preferredPopoutWidgetSize = saveTab ? saveTab.preferredPopoutWidgetSize : undefined;
272
274
  // if a defaultFloatingSize is specified then this mean the widget can't determine its intrinsic size and must be explicitly sized
273
275
  const userSized = saveTab ? (saveTab.userSized || !!widgetDef.defaultFloatingSize && !!saveTab.preferredFloatingWidgetSize)
274
276
  : !!widgetDef.defaultFloatingSize;
@@ -278,21 +280,51 @@ function appendWidgets(state, widgetDefs, side, preferredWidgetIndex) {
278
280
  canPopout: widgetDef.canPopout,
279
281
  preferredPanelWidgetSize,
280
282
  preferredFloatingWidgetSize,
281
- preferredPopoutWidgetSize,
282
283
  userSized,
283
284
  isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
284
285
  hideWithUiWhenFloating: !!widgetDef.hideWithUiWhenFloating,
286
+ allowedPanelTargets: widgetDef.allowedPanelTargets,
285
287
  });
286
288
  if (widgetDef.isFloatingStateSupported && widgetDef.defaultState === appui_abstract_1.WidgetState.Floating) {
287
289
  const floatingContainerId = (_a = widgetDef.floatingContainerId) !== null && _a !== void 0 ? _a : (0, appui_layout_react_1.getUniqueId)();
288
290
  const widgetContainerId = getWidgetId(side, panelZoneKeys[preferredWidgetIndex]);
289
- const homePanelInfo = { side, widgetId: widgetContainerId, widgetIndex: 0 };
291
+ const home = { side, widgetId: widgetContainerId, widgetIndex: 0 };
290
292
  const preferredPosition = widgetDef.defaultFloatingPosition;
291
- state = (0, appui_layout_react_1.addWidgetTabToFloatingPanel)(state, floatingContainerId, widgetDef.id, homePanelInfo, preferredFloatingWidgetSize, preferredPosition, userSized, widgetDef.isFloatingStateWindowResizable);
293
+ if (floatingContainerId in state.widgets) {
294
+ state = (0, appui_layout_react_1.addTabToWidget)(state, widgetDef.id, floatingContainerId);
295
+ }
296
+ else {
297
+ const tab = state.tabs[widgetDef.id];
298
+ const size = { height: 200, width: 300, ...tab.preferredFloatingWidgetSize };
299
+ const preferredPoint = preferredPosition !== null && preferredPosition !== void 0 ? preferredPosition : { x: (state.size.width - size.width) / 2, y: (state.size.height - size.height) / 2 };
300
+ const nzBounds = core_react_1.Rectangle.createFromSize(state.size);
301
+ const bounds = core_react_1.Rectangle.createFromSize(size).offset(preferredPoint);
302
+ const containedBounds = bounds.containIn(nzBounds);
303
+ state = (0, appui_layout_react_1.addFloatingWidget)(state, floatingContainerId, [widgetDef.id], {
304
+ bounds: containedBounds.toProps(),
305
+ home,
306
+ userSized,
307
+ }, {
308
+ isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
309
+ });
310
+ }
292
311
  }
293
312
  else {
294
313
  const widgetPanelSectionId = (0, appui_layout_react_1.getWidgetPanelSectionId)(side, preferredWidgetIndex);
295
- state = (0, appui_layout_react_1.addWidgetTabToPanelSection)(state, side, widgetPanelSectionId, widgetDef.id);
314
+ if (widgetPanelSectionId in state.widgets) {
315
+ state = (0, appui_layout_react_1.addTabToWidget)(state, widgetDef.id, widgetPanelSectionId);
316
+ }
317
+ else {
318
+ const panel = state.panels[side];
319
+ if (panel.widgets.length < panel.maxWidgetCount) {
320
+ state = (0, appui_layout_react_1.addPanelWidget)(state, side, widgetPanelSectionId, [widgetDef.id]);
321
+ }
322
+ else {
323
+ const widgetIndex = Math.min(preferredWidgetIndex, panel.widgets.length - 1);
324
+ const widgetId = panel.widgets[widgetIndex];
325
+ state = (0, appui_layout_react_1.addTabToWidget)(state, widgetDef.id, widgetId);
326
+ }
327
+ }
296
328
  }
297
329
  }
298
330
  return state;
@@ -340,17 +372,15 @@ function addMissingWidgets(frontstageDef, initialState) {
340
372
  return state;
341
373
  }
342
374
  exports.addMissingWidgets = addMissingWidgets;
343
- /** Removes widgets with Hidden defaultState. */
344
- function removeHiddenWidgets(state, frontstageDef) {
375
+ /** Hide widgets with Hidden defaultState. */
376
+ function hideWidgets(state, frontstageDef) {
345
377
  const tabs = Object.values(state.tabs);
346
378
  for (const tab of tabs) {
347
379
  const widgetDef = frontstageDef.findWidgetDef(tab.id);
348
380
  if (!widgetDef)
349
381
  continue;
350
382
  if (widgetDef.defaultState === appui_abstract_1.WidgetState.Hidden) {
351
- state = (0, immer_1.default)(state, (draft) => {
352
- hideWidget(draft, widgetDef);
353
- });
383
+ state = hideWidget(state, widgetDef);
354
384
  }
355
385
  }
356
386
  return state;
@@ -359,16 +389,15 @@ function removeHiddenWidgets(state, frontstageDef) {
359
389
  * @internal
360
390
  */
361
391
  function removeMissingWidgets(frontstageDef, initialState) {
362
- const state = (0, immer_1.default)(initialState, (draft) => {
363
- for (const [, tab] of Object.entries(draft.tabs)) {
364
- if (tab.id === appui_layout_react_1.toolSettingsTabId)
365
- continue;
366
- const widgetDef = frontstageDef.findWidgetDef(tab.id);
367
- if (widgetDef)
368
- continue;
369
- (0, appui_layout_react_1.removeTab)(draft, tab.id);
370
- }
371
- });
392
+ let state = initialState;
393
+ for (const [, tab] of Object.entries(state.tabs)) {
394
+ if (tab.id === appui_layout_react_1.toolSettingsTabId)
395
+ continue;
396
+ const widgetDef = frontstageDef.findWidgetDef(tab.id);
397
+ if (widgetDef)
398
+ continue;
399
+ state = (0, appui_layout_react_1.removeTab)(state, tab.id);
400
+ }
372
401
  return state;
373
402
  }
374
403
  exports.removeMissingWidgets = removeMissingWidgets;
@@ -524,23 +553,23 @@ function isFrontstageStateSettingResult(settingsResult) {
524
553
  }
525
554
  exports.isFrontstageStateSettingResult = isFrontstageStateSettingResult;
526
555
  /** @internal */
527
- function initializePanel(nineZone, frontstageDef, panelSide) {
528
- nineZone = addPanelWidgets(nineZone, frontstageDef, panelSide);
556
+ function initializePanel(state, frontstageDef, panelSide) {
557
+ state = addPanelWidgets(state, frontstageDef, panelSide);
529
558
  const location = toStagePanelLocation(panelSide);
530
559
  const panelDef = frontstageDef.getStagePanelDef(location);
531
- nineZone = (0, immer_1.default)(nineZone, (draft) => {
560
+ state = (0, immer_1.default)(state, (draft) => {
532
561
  var _a, _b, _c;
533
562
  const panel = draft.panels[panelSide];
534
563
  panel.minSize = (_a = panelDef === null || panelDef === void 0 ? void 0 : panelDef.minSize) !== null && _a !== void 0 ? _a : panel.minSize;
535
564
  panel.pinned = (_b = panelDef === null || panelDef === void 0 ? void 0 : panelDef.pinned) !== null && _b !== void 0 ? _b : panel.pinned;
536
565
  panel.resizable = (_c = panelDef === null || panelDef === void 0 ? void 0 : panelDef.resizable) !== null && _c !== void 0 ? _c : panel.resizable;
537
566
  if (panelDef === null || panelDef === void 0 ? void 0 : panelDef.maxSizeSpec) {
538
- panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide, nineZone.size);
567
+ panel.maxSize = getPanelMaxSize(panelDef.maxSizeSpec, panelSide, state.size);
539
568
  }
540
569
  const size = panelDef === null || panelDef === void 0 ? void 0 : panelDef.size;
541
570
  panel.size = size === undefined ? size : Math.min(Math.max(size, panel.minSize), panel.maxSize);
542
571
  });
543
- return nineZone;
572
+ return state;
544
573
  }
545
574
  exports.initializePanel = initializePanel;
546
575
  function getPanelMaxSize(maxSizeSpec, panel, nineZoneSize) {
@@ -550,7 +579,7 @@ function getPanelMaxSize(maxSizeSpec, panel, nineZoneSize) {
550
579
  const size = (0, appui_layout_react_1.isHorizontalPanelSide)(panel) ? nineZoneSize.height : nineZoneSize.width;
551
580
  return maxSizeSpec.percentage / 100 * size;
552
581
  }
553
- const stateVersion = 12; // this needs to be bumped when NineZoneState is changed (to recreate layout).
582
+ const stateVersion = 13; // this needs to be bumped when NineZoneState is changed (to recreate the layout).
554
583
  /** @internal */
555
584
  function initializeNineZoneState(frontstageDef) {
556
585
  let nineZone = defaultNineZone;
@@ -572,6 +601,7 @@ function initializeNineZoneState(frontstageDef) {
572
601
  for (const [, panel] of Object.entries(stateDraft.panels)) {
573
602
  const expanded = panel.widgets.find((widgetId) => stateDraft.widgets[widgetId].minimized === false);
574
603
  const firstWidget = panel.widgets.length > 0 ? stateDraft.widgets[panel.widgets[0]] : undefined;
604
+ // istanbul ignore next
575
605
  if (!expanded && firstWidget) {
576
606
  firstWidget.minimized = false;
577
607
  }
@@ -600,7 +630,7 @@ function initializeNineZoneState(frontstageDef) {
600
630
  }
601
631
  });
602
632
  nineZone = addMissingWidgets(frontstageDef, nineZone);
603
- nineZone = removeHiddenWidgets(nineZone, frontstageDef);
633
+ nineZone = hideWidgets(nineZone, frontstageDef);
604
634
  nineZone = processPopoutWidgets(nineZone, frontstageDef);
605
635
  return nineZone;
606
636
  }
@@ -613,29 +643,33 @@ exports.initializeNineZoneState = initializeNineZoneState;
613
643
  function restoreNineZoneState(frontstageDef, saved) {
614
644
  let restored = {
615
645
  ...saved,
616
- tabs: (0, appui_layout_react_1.createTabsState)(),
646
+ tabs: defaultNineZone.tabs,
617
647
  };
618
- restored = (0, immer_1.default)(restored, (draft) => {
619
- var _a;
620
- for (const [, tab] of Object.entries(saved.tabs)) {
621
- const widgetDef = frontstageDef.findWidgetDef(tab.id);
622
- if (!widgetDef) {
623
- core_bentley_1.Logger.logInfo(UiFramework_1.UiFramework.loggerCategory(restoreNineZoneState), "WidgetDef is not found for saved tab.", () => ({
624
- frontstageId: frontstageDef.id,
625
- tabId: tab.id,
626
- }));
627
- (0, appui_layout_react_1.removeTab)(draft, tab.id);
628
- // let fall through so we preserve preferred sizes of widgets load via UiItemsProvider
629
- }
648
+ for (const [, tab] of Object.entries(saved.tabs)) {
649
+ // Re-add the placeholder tab in order to correctly remove it from the state if WidgetDef is not found.
650
+ restored = (0, appui_layout_react_1.addTab)(restored, tab.id);
651
+ const widgetDef = frontstageDef.findWidgetDef(tab.id);
652
+ if (!widgetDef) {
653
+ core_bentley_1.Logger.logInfo(UiFramework_1.UiFramework.loggerCategory(restoreNineZoneState), "WidgetDef is not found for saved tab.", () => ({
654
+ frontstageId: frontstageDef.id,
655
+ tabId: tab.id,
656
+ }));
657
+ restored = (0, appui_layout_react_1.removeTab)(restored, tab.id);
658
+ continue;
659
+ }
660
+ restored = (0, immer_1.default)(restored, (draft) => {
630
661
  draft.tabs[tab.id] = {
631
662
  ...tab,
632
- label: getWidgetLabel((_a = widgetDef === null || widgetDef === void 0 ? void 0 : widgetDef.label) !== null && _a !== void 0 ? _a : "undefined"),
633
- hideWithUiWhenFloating: widgetDef === null || widgetDef === void 0 ? void 0 : widgetDef.hideWithUiWhenFloating,
634
- iconSpec: widgetDef === null || widgetDef === void 0 ? void 0 : widgetDef.iconSpec,
635
- canPopout: widgetDef === null || widgetDef === void 0 ? void 0 : widgetDef.canPopout,
636
- isFloatingStateWindowResizable: widgetDef === null || widgetDef === void 0 ? void 0 : widgetDef.isFloatingStateWindowResizable,
663
+ label: getWidgetLabel(widgetDef.label),
664
+ hideWithUiWhenFloating: widgetDef.hideWithUiWhenFloating,
665
+ iconSpec: widgetDef.iconSpec,
666
+ canPopout: widgetDef.canPopout,
667
+ isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
668
+ allowedPanelTargets: widgetDef.allowedPanelTargets,
637
669
  };
638
- }
670
+ });
671
+ }
672
+ restored = (0, immer_1.default)(restored, (draft) => {
639
673
  // remove center panel section if one is found in left or right panels
640
674
  const oldLeftMiddleIndex = saved.panels.left.widgets.findIndex((value) => value === "leftMiddle");
641
675
  // istanbul ignore next
@@ -675,20 +709,6 @@ function restoreNineZoneState(frontstageDef, saved) {
675
709
  return restored;
676
710
  }
677
711
  exports.restoreNineZoneState = restoreNineZoneState;
678
- /**
679
- * Checks to see whether a widget id is one of our generated uuids
680
- * @param uuid the string value to test
681
- * @returns boolean
682
- */
683
- function isUUID(uuid) {
684
- const s = `${uuid}`;
685
- const result = s.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
686
- // istanbul ignore else
687
- if (result === null) {
688
- return false;
689
- }
690
- return true;
691
- }
692
712
  /** Prepares NineZoneState to be saved.
693
713
  * @note Removes toolSettings tab.
694
714
  * @note Removes tab labels and iconSpec.
@@ -703,33 +723,62 @@ function packNineZoneState(state) {
703
723
  for (const [, tab] of Object.entries(state.tabs)) {
704
724
  if (tab.id === appui_layout_react_1.toolSettingsTabId)
705
725
  continue;
706
- // istanbul ignore else
707
- if (isUUID(tab.id))
708
- continue;
709
726
  draft.tabs[tab.id] = {
710
727
  id: tab.id,
711
728
  preferredFloatingWidgetSize: tab.preferredFloatingWidgetSize,
712
- preferredPopoutWidgetSize: tab.preferredPopoutWidgetSize,
713
729
  allowedPanelTargets: tab.allowedPanelTargets,
714
730
  userSized: tab.userSized,
715
731
  };
716
732
  }
717
733
  });
718
- packed = (0, immer_1.default)(packed, (draft) => {
719
- for (const [, floatingWidget] of Object.entries(state.floatingWidgets.byId)) {
720
- const widgetId = floatingWidget.id;
721
- // istanbul ignore else
722
- if (isUUID(widgetId)) {
723
- const idIndex = draft.floatingWidgets.allIds.indexOf(widgetId);
724
- draft.floatingWidgets.allIds.splice(idIndex, 1);
725
- delete draft.floatingWidgets.byId[widgetId];
726
- delete draft.widgets[widgetId];
727
- }
728
- }
729
- });
730
734
  return packed;
731
735
  }
732
736
  exports.packNineZoneState = packNineZoneState;
737
+ // TODO: clean-up of saved widgets.
738
+ // istanbul ignore next
739
+ function packSavedWidgets(savedWidgets, frontstageDef) {
740
+ for (const widgetDef of frontstageDef.widgetDefs) {
741
+ const id = widgetDef.id;
742
+ const initialWidget = {
743
+ id,
744
+ };
745
+ const widget = (0, immer_1.default)(initialWidget, (draft) => {
746
+ if (widgetDef.tabLocation) {
747
+ draft.tabLocation = { ...widgetDef.tabLocation };
748
+ }
749
+ if (widgetDef.popoutBounds) {
750
+ draft.popoutBounds = widgetDef.popoutBounds.toProps();
751
+ }
752
+ });
753
+ if (widget === initialWidget)
754
+ continue;
755
+ savedWidgets = (0, immer_1.default)(savedWidgets, (draft) => {
756
+ draft.push(widget);
757
+ });
758
+ }
759
+ return savedWidgets;
760
+ }
761
+ // istanbul ignore next
762
+ function restoreSavedWidgets(savedWidgets, frontstage) {
763
+ let i = savedWidgets.length;
764
+ while (i--) {
765
+ const savedWidget = savedWidgets[i];
766
+ const widgetId = savedWidget.id;
767
+ const widgetDef = frontstage.findWidgetDef(widgetId);
768
+ if (!widgetDef)
769
+ continue;
770
+ if (savedWidget.tabLocation) {
771
+ widgetDef.tabLocation = { ...savedWidget.tabLocation };
772
+ }
773
+ if (savedWidget.popoutBounds) {
774
+ widgetDef.popoutBounds = core_react_1.Rectangle.create(savedWidget.popoutBounds);
775
+ }
776
+ savedWidgets = (0, immer_1.default)(savedWidgets, (draft) => {
777
+ draft.splice(i, 1);
778
+ });
779
+ }
780
+ return savedWidgets;
781
+ }
733
782
  /** @internal */
734
783
  function isPanelCollapsed(zoneStates, panelStates) {
735
784
  const openZone = zoneStates.find((zoneState) => zoneState === ZoneDef_1.ZoneState.Open);
@@ -737,121 +786,128 @@ function isPanelCollapsed(zoneStates, panelStates) {
737
786
  return !openZone && !openPanel;
738
787
  }
739
788
  exports.isPanelCollapsed = isPanelCollapsed;
740
- function addRemovedTab(nineZone, widgetDef) {
741
- var _a, _b;
742
- const newTab = (0, appui_layout_react_1.createTabState)(widgetDef.id, {
743
- label: getWidgetLabel(widgetDef.label),
744
- canPopout: widgetDef.canPopout,
745
- iconSpec: widgetDef.iconSpec,
746
- preferredPanelWidgetSize: widgetDef.preferredPanelSize,
747
- isFloatingStateWindowResizable: widgetDef.isFloatingStateWindowResizable,
748
- hideWithUiWhenFloating: !!widgetDef.hideWithUiWhenFloating,
749
- });
750
- nineZone.tabs[newTab.id] = newTab;
751
- if (widgetDef.tabLocation.widgetId in nineZone.widgets) {
752
- // Add to existing widget (by widget id).
753
- const widgetId = widgetDef.tabLocation.widgetId;
754
- const newTabWidget = nineZone.widgets[widgetId];
755
- newTabWidget.tabs.splice(widgetDef.tabLocation.tabIndex, 0, newTab.id);
789
+ function addHiddenWidget(state, widgetDef) {
790
+ const tabLocation = widgetDef.tabLocation || widgetDef.defaultTabLocation;
791
+ const tabId = widgetDef.id;
792
+ const { widgetId, tabIndex } = tabLocation;
793
+ if (widgetId in state.widgets) {
794
+ // Add to an existing widget (by widget id).
795
+ return (0, appui_layout_react_1.insertTabToWidget)(state, tabId, widgetId, tabIndex);
756
796
  }
757
- else if (widgetDef.tabLocation.floating) {
758
- const id = widgetDef.tabLocation.widgetId;
759
- if (id in nineZone.floatingWidgets.byId) {
760
- nineZone.floatingWidgets.allIds.push(id);
761
- nineZone.floatingWidgets.byId[id].hidden = false;
762
- (0, appui_layout_react_1.addWidgetTabToDraftFloatingPanel)(nineZone, (_a = widgetDef.floatingContainerId) !== null && _a !== void 0 ? _a : widgetDef.id, widgetDef.id, nineZone.floatingWidgets.byId[id].home, newTab);
763
- }
764
- else {
765
- const home = { side: widgetDef.tabLocation.side, widgetId: widgetDef.floatingContainerId, widgetIndex: 0 };
766
- (0, appui_layout_react_1.addWidgetTabToDraftFloatingPanel)(nineZone, (_b = widgetDef.floatingContainerId) !== null && _b !== void 0 ? _b : widgetDef.id, widgetDef.id, home, newTab);
767
- }
797
+ else if (tabLocation.floatingWidget) {
798
+ const floatingWidget = tabLocation.floatingWidget;
799
+ (0, core_bentley_1.assert)(widgetId === floatingWidget.id);
800
+ // Add to a new floating widget.
801
+ const nzBounds = core_react_1.Rectangle.createFromSize(state.size);
802
+ const bounds = core_react_1.Rectangle.create(floatingWidget.bounds).containIn(nzBounds);
803
+ return (0, appui_layout_react_1.addFloatingWidget)(state, floatingWidget.id, [tabId], {
804
+ ...floatingWidget,
805
+ bounds: bounds.toProps(),
806
+ });
768
807
  }
769
- else {
770
- const newTabPanel = nineZone.panels[widgetDef.tabLocation.side];
771
- if (newTabPanel.maxWidgetCount === newTabPanel.widgets.length) {
772
- // Add to existing panel widget.
773
- const widgetIndex = Math.min(newTabPanel.maxWidgetCount - 1, widgetDef.tabLocation.widgetIndex);
774
- const newTabWidgetId = newTabPanel.widgets[widgetIndex];
775
- const newTabWidget = nineZone.widgets[newTabWidgetId];
776
- newTabWidget.tabs.splice(widgetDef.tabLocation.tabIndex, 0, newTab.id);
777
- }
778
- else {
779
- // Create a new panel widget.
780
- const newWidget = (0, appui_layout_react_1.createWidgetState)((0, appui_layout_react_1.getUniqueId)(), [newTab.id]);
781
- nineZone.widgets[newWidget.id] = (0, immer_1.castDraft)(newWidget);
782
- newTabPanel.widgets.splice(widgetDef.tabLocation.widgetIndex, 0, newWidget.id);
783
- }
808
+ // Add to a panel section.
809
+ const panel = state.panels[tabLocation.side];
810
+ // Add to existing panel section.
811
+ if (panel.widgets.length >= panel.maxWidgetCount) {
812
+ const sectionIndex = Math.min(panel.maxWidgetCount - 1, tabLocation.widgetIndex);
813
+ const sectionId = panel.widgets[sectionIndex];
814
+ return (0, appui_layout_react_1.insertTabToWidget)(state, tabId, sectionId, tabLocation.tabIndex);
784
815
  }
816
+ // Create a new panel section.
817
+ const newSectionId = (0, appui_layout_react_1.getUniqueId)();
818
+ return (0, appui_layout_react_1.insertPanelWidget)(state, panel.side, newSectionId, [tabId], tabLocation.widgetIndex);
785
819
  }
786
820
  /** @internal */
787
- exports.setWidgetState = (0, immer_1.default)((nineZone, widgetDef, state) => {
821
+ function setWidgetState(state, widgetDef, widgetState) {
788
822
  var _a, _b;
789
- if (state === appui_abstract_1.WidgetState.Open) {
823
+ if (widgetState === appui_abstract_1.WidgetState.Hidden) {
824
+ return hideWidget(state, widgetDef);
825
+ }
826
+ else if (widgetState === appui_abstract_1.WidgetState.Open) {
790
827
  const id = widgetDef.id;
791
- let location = (0, appui_layout_react_1.findTab)(nineZone, id);
828
+ let location = (0, appui_layout_react_1.getTabLocation)(state, id);
792
829
  if (!location) {
793
- addRemovedTab(nineZone, widgetDef);
794
- location = (0, appui_layout_react_1.findTab)(nineZone, id);
795
- (0, core_bentley_1.assert)(!!location);
830
+ state = addHiddenWidget(state, widgetDef);
831
+ location = (0, appui_layout_react_1.getTabLocation)(state, id);
796
832
  }
797
- if (!!widgetDef.tabLocation.floating) {
798
- nineZone.floatingWidgets.byId[(_a = widgetDef.floatingContainerId) !== null && _a !== void 0 ? _a : widgetDef.id].hidden = false;
799
- }
800
- const widget = nineZone.widgets[location.widgetId];
801
- widget.minimized = false;
802
- widget.activeTabId = id;
803
- // ensure panel containing widget is not collapsed
804
- // istanbul ignore else
805
- if ("side" in location) {
806
- const panel = nineZone.panels[location.side];
807
- panel.collapsed && (panel.collapsed = false);
808
- // istanbul ignore next
809
- if (undefined === panel.size || 0 === panel.size) {
810
- panel.size = (_b = panel.minSize) !== null && _b !== void 0 ? _b : 200;
833
+ return (0, immer_1.default)(state, (draft) => {
834
+ var _a;
835
+ (0, core_bentley_1.assert)(!!location);
836
+ const widget = draft.widgets[location.widgetId];
837
+ widget.minimized = false;
838
+ widget.activeTabId = id;
839
+ if ((0, appui_layout_react_1.isFloatingTabLocation)(location)) {
840
+ const floatingWidget = draft.floatingWidgets.byId[location.floatingWidgetId];
841
+ floatingWidget.hidden = false;
842
+ // istanbul ignore else
811
843
  }
812
- }
844
+ else if ((0, appui_layout_react_1.isPanelTabLocation)(location)) {
845
+ const panel = draft.panels[location.side];
846
+ panel.collapsed = false;
847
+ if (undefined === panel.size || 0 === panel.size) {
848
+ // istanbul ignore next
849
+ panel.size = (_a = panel.minSize) !== null && _a !== void 0 ? _a : 200;
850
+ }
851
+ }
852
+ });
813
853
  }
814
- else if (state === appui_abstract_1.WidgetState.Closed) {
854
+ else if (widgetState === appui_abstract_1.WidgetState.Closed) {
815
855
  const id = widgetDef.id;
816
- let location = (0, appui_layout_react_1.findTab)(nineZone, id);
856
+ let location = (0, appui_layout_react_1.getTabLocation)(state, id);
817
857
  if (!location) {
818
- addRemovedTab(nineZone, widgetDef);
819
- location = (0, appui_layout_react_1.findTab)(nineZone, id);
820
- (0, core_bentley_1.assert)(!!location);
821
- }
822
- if ((0, appui_layout_react_1.isFloatingLocation)(location)) {
823
- const widget = nineZone.widgets[location.widgetId];
824
- if (id !== widget.activeTabId)
825
- return;
826
- widget.minimized = true;
858
+ state = addHiddenWidget(state, widgetDef);
859
+ location = (0, appui_layout_react_1.getTabLocation)(state, id);
827
860
  }
861
+ // TODO: should change activeTabId of a widget with multiple tabs.
862
+ return (0, immer_1.default)(state, (draft) => {
863
+ (0, core_bentley_1.assert)(!!location);
864
+ const widget = draft.widgets[location.widgetId];
865
+ if ((0, appui_layout_react_1.isFloatingTabLocation)(location)) {
866
+ if (id === widget.activeTabId) {
867
+ widget.minimized = true;
868
+ }
869
+ }
870
+ });
828
871
  }
829
- else if (state === appui_abstract_1.WidgetState.Hidden) {
830
- hideWidget(nineZone, widgetDef);
872
+ else if (widgetState === appui_abstract_1.WidgetState.Floating) {
873
+ const id = widgetDef.id;
874
+ let location = (0, appui_layout_react_1.getTabLocation)(state, id);
875
+ if (!location) {
876
+ state = addHiddenWidget(state, widgetDef);
877
+ location = (0, appui_layout_react_1.getTabLocation)(state, id);
878
+ }
879
+ (0, core_bentley_1.assert)(!!location);
880
+ if ((0, appui_layout_react_1.isFloatingTabLocation)(location))
881
+ return state;
882
+ // Widget is not floating.
883
+ state = (0, appui_layout_react_1.removeTabFromWidget)(state, id);
884
+ const bounds = (_b = (_a = widgetDef.tabLocation) === null || _a === void 0 ? void 0 : _a.floatingWidget) === null || _b === void 0 ? void 0 : _b.bounds;
885
+ state = (0, appui_layout_react_1.addFloatingWidget)(state, (0, appui_layout_react_1.getUniqueId)(), [id], { bounds });
831
886
  }
832
- });
887
+ return state;
888
+ }
889
+ exports.setWidgetState = setWidgetState;
833
890
  /** Stores widget location and hides it in the UI. */
834
891
  function hideWidget(state, widgetDef) {
835
- const location = (0, appui_layout_react_1.findTab)(state, widgetDef.id);
892
+ const location = (0, appui_layout_react_1.getTabLocation)(state, widgetDef.id);
836
893
  if (!location)
837
- return;
838
- if ((0, appui_layout_react_1.isFloatingLocation)(location)) {
839
- const widget = state.floatingWidgets.byId[location.widgetId];
894
+ return state;
895
+ // istanbul ignore else
896
+ if ((0, appui_layout_react_1.isFloatingTabLocation)(location)) {
897
+ const floatingWidget = state.floatingWidgets.byId[location.widgetId];
840
898
  widgetDef.setFloatingContainerId(location.floatingWidgetId);
841
899
  widgetDef.tabLocation = {
842
- side: widget.home.side,
843
- tabIndex: widget.home.widgetIndex,
844
- widgetId: widgetDef.id,
845
- widgetIndex: widget.home.widgetIndex,
846
- floating: true,
900
+ side: floatingWidget.home.side,
901
+ tabIndex: floatingWidget.home.widgetIndex,
902
+ widgetId: floatingWidget.id,
903
+ widgetIndex: floatingWidget.home.widgetIndex,
904
+ floatingWidget,
847
905
  };
848
906
  }
849
- else
850
- // istanbul ignore else
851
- if (!(0, appui_layout_react_1.isPopoutLocation)(location)) {
907
+ else if (!(0, appui_layout_react_1.isPopoutTabLocation)(location)) {
852
908
  const widgetId = location.widgetId;
853
- const side = "side" in location ? location.side : "left";
854
- const widgetIndex = "side" in location ? state.panels[side].widgets.indexOf(widgetId) : 0;
909
+ const side = (0, appui_layout_react_1.isPanelTabLocation)(location) ? location.side : "left";
910
+ const widgetIndex = (0, appui_layout_react_1.isPanelTabLocation)(location) ? state.panels[side].widgets.indexOf(widgetId) : 0;
855
911
  const tabIndex = state.widgets[location.widgetId].tabs.indexOf(widgetDef.id);
856
912
  widgetDef.tabLocation = {
857
913
  side,
@@ -860,50 +916,56 @@ function hideWidget(state, widgetDef) {
860
916
  widgetIndex,
861
917
  };
862
918
  }
863
- (0, appui_layout_react_1.removeTab)(state, widgetDef.id);
919
+ return (0, appui_layout_react_1.removeTabFromWidget)(state, widgetDef.id);
864
920
  }
865
921
  /** @internal */
866
- exports.showWidget = (0, immer_1.default)((nineZone, id) => {
867
- const location = (0, appui_layout_react_1.findTab)(nineZone, id);
922
+ function showWidget(state, id) {
923
+ const location = (0, appui_layout_react_1.getTabLocation)(state, id);
868
924
  if (!location)
869
- return;
870
- const widget = nineZone.widgets[location.widgetId];
871
- if ("side" in location) {
872
- const panel = nineZone.panels[location.side];
873
- panel.collapsed = false;
874
- widget.minimized = false;
925
+ return state;
926
+ state = (0, immer_1.default)(state, (draft) => {
927
+ const widget = draft.widgets[location.widgetId];
875
928
  widget.activeTabId = id;
876
- return;
929
+ widget.minimized = false;
930
+ if ((0, appui_layout_react_1.isPanelTabLocation)(location)) {
931
+ const panel = draft.panels[location.side];
932
+ panel.collapsed = false;
933
+ }
934
+ });
935
+ if ((0, appui_layout_react_1.isFloatingTabLocation)(location)) {
936
+ state = (0, appui_layout_react_1.floatingWidgetBringToFront)(state, location.floatingWidgetId);
877
937
  }
878
- widget.activeTabId = id;
879
- widget.minimized = false;
880
- (0, appui_layout_react_1.isFloatingLocation)(location) && (0, appui_layout_react_1.floatingWidgetBringToFront)(nineZone, location.floatingWidgetId);
881
- });
938
+ return state;
939
+ }
940
+ exports.showWidget = showWidget;
882
941
  /** @internal */
883
- exports.expandWidget = (0, immer_1.default)((nineZone, id) => {
884
- const location = (0, appui_layout_react_1.findTab)(nineZone, id);
942
+ function expandWidget(state, id) {
943
+ const location = (0, appui_layout_react_1.getTabLocation)(state, id);
885
944
  if (!location)
886
- return;
887
- const widget = nineZone.widgets[location.widgetId];
888
- if ("side" in location) {
889
- const panel = nineZone.panels[location.side];
890
- panel.widgets.forEach((wId) => {
891
- const w = nineZone.widgets[wId];
892
- w.minimized = true;
893
- });
945
+ return state;
946
+ return (0, immer_1.default)(state, (draft) => {
947
+ const widget = draft.widgets[location.widgetId];
948
+ if ((0, appui_layout_react_1.isPanelTabLocation)(location)) {
949
+ const panel = draft.panels[location.side];
950
+ panel.widgets.forEach((wId) => {
951
+ const w = draft.widgets[wId];
952
+ w.minimized = true;
953
+ });
954
+ }
894
955
  widget.minimized = false;
895
- return;
896
- }
897
- widget.minimized = false;
898
- return;
899
- });
956
+ });
957
+ }
958
+ exports.expandWidget = expandWidget;
900
959
  /** @internal */
901
- exports.setWidgetLabel = (0, immer_1.default)((nineZone, id, label) => {
902
- if (!(id in nineZone.tabs))
903
- return;
904
- const tab = nineZone.tabs[id];
905
- tab.label = label;
906
- });
960
+ function setWidgetLabel(state, id, label) {
961
+ if (!(id in state.tabs))
962
+ return state;
963
+ return (0, immer_1.default)(state, (draft) => {
964
+ const tab = draft.tabs[id];
965
+ tab.label = label;
966
+ });
967
+ }
968
+ exports.setWidgetLabel = setWidgetLabel;
907
969
  /** @internal */
908
970
  function useSavedFrontstageState(frontstageDef) {
909
971
  const uiStateStorage = (0, useUiStateStorage_1.useUiStateStorageHandler)();
@@ -924,20 +986,23 @@ function useSavedFrontstageState(frontstageDef) {
924
986
  }
925
987
  const id = frontstageDef.id;
926
988
  const version = frontstageDef.version;
927
- const settingsResult = await uiStateStorageRef.current.getSetting(exports.FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id));
928
- if (isMountedRef.current) {
929
- if (isFrontstageStateSettingResult(settingsResult) &&
930
- settingsResult.setting.version >= version &&
931
- settingsResult.setting.stateVersion >= stateVersion) {
932
- const restored = restoreNineZoneState(frontstageDef, settingsResult.setting.nineZone);
989
+ const settingResult = await uiStateStorageRef.current.getSetting(exports.FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id));
990
+ if (!isMountedRef.current)
991
+ return;
992
+ if (isFrontstageStateSettingResult(settingResult)) {
993
+ const setting = settingResult.setting;
994
+ if (setting.version >= version && setting.stateVersion >= stateVersion) {
995
+ const restored = restoreNineZoneState(frontstageDef, setting.nineZone);
996
+ const savedWidgets = restoreSavedWidgets(setting.widgets, frontstageDef);
933
997
  let state = addMissingWidgets(frontstageDef, restored);
934
- state = removeHiddenWidgets(state, frontstageDef);
998
+ state = hideWidgets(state, frontstageDef);
935
999
  state = processPopoutWidgets(state, frontstageDef);
936
1000
  frontstageDef.nineZoneState = state;
1001
+ frontstageDef.savedWidgetDefs = savedWidgets;
937
1002
  return;
938
1003
  }
939
- frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
940
1004
  }
1005
+ frontstageDef.nineZoneState = initializeNineZoneState(frontstageDef);
941
1006
  }
942
1007
  fetchFrontstageState(); // eslint-disable-line @typescript-eslint/no-floating-promises
943
1008
  }, [frontstageDef]);
@@ -947,16 +1012,19 @@ exports.useSavedFrontstageState = useSavedFrontstageState;
947
1012
  function useSaveFrontstageSettings(frontstageDef) {
948
1013
  const nineZone = useNineZoneState(frontstageDef);
949
1014
  const uiSettingsStorage = (0, useUiStateStorage_1.useUiStateStorageHandler)();
950
- // eslint-disable-next-line react-hooks/exhaustive-deps
951
- const saveSetting = React.useCallback(debounce(async (id, version, state) => {
952
- const setting = {
953
- id,
954
- nineZone: packNineZoneState(state),
955
- stateVersion,
956
- version,
957
- };
958
- await uiSettingsStorage.saveSetting(exports.FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id), setting);
959
- }, 1000), [uiSettingsStorage]);
1015
+ const saveSetting = React.useMemo(() => {
1016
+ return debounce(async (frontstage, state, savedWidgets) => {
1017
+ const id = frontstage.id;
1018
+ const setting = {
1019
+ id,
1020
+ version: frontstage.version,
1021
+ stateVersion,
1022
+ nineZone: packNineZoneState(state),
1023
+ widgets: packSavedWidgets(savedWidgets, frontstage),
1024
+ };
1025
+ await uiSettingsStorage.saveSetting(exports.FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(id), setting);
1026
+ }, 1000);
1027
+ }, [uiSettingsStorage]);
960
1028
  React.useEffect(() => {
961
1029
  return () => {
962
1030
  saveSetting.cancel();
@@ -965,7 +1033,8 @@ function useSaveFrontstageSettings(frontstageDef) {
965
1033
  React.useEffect(() => {
966
1034
  if (!nineZone || nineZone.draggedTab)
967
1035
  return;
968
- saveSetting(frontstageDef.id, frontstageDef.version, nineZone);
1036
+ const savedWidgets = frontstageDef.savedWidgetDefs || [];
1037
+ saveSetting(frontstageDef, nineZone, savedWidgets);
969
1038
  }, [frontstageDef, nineZone, saveSetting]);
970
1039
  }
971
1040
  exports.useSaveFrontstageSettings = useSaveFrontstageSettings;
@@ -1004,7 +1073,7 @@ function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
1004
1073
  React.useEffect(() => {
1005
1074
  const listener = createListener(frontstageDef, ({ widgetDef, widgetState }) => {
1006
1075
  (0, core_bentley_1.assert)(!!frontstageDef.nineZoneState);
1007
- frontstageDef.nineZoneState = (0, exports.setWidgetState)(frontstageDef.nineZoneState, widgetDef, widgetState);
1076
+ frontstageDef.nineZoneState = setWidgetState(frontstageDef.nineZoneState, widgetDef, widgetState);
1008
1077
  });
1009
1078
  FrontstageManager_1.FrontstageManager.onWidgetStateChangedEvent.addListener(listener);
1010
1079
  return () => {
@@ -1014,7 +1083,7 @@ function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
1014
1083
  React.useEffect(() => {
1015
1084
  const listener = createListener(frontstageDef, ({ widgetDef }) => {
1016
1085
  (0, core_bentley_1.assert)(!!frontstageDef.nineZoneState);
1017
- frontstageDef.nineZoneState = (0, exports.showWidget)(frontstageDef.nineZoneState, widgetDef.id);
1086
+ frontstageDef.nineZoneState = showWidget(frontstageDef.nineZoneState, widgetDef.id);
1018
1087
  });
1019
1088
  FrontstageManager_1.FrontstageManager.onWidgetShowEvent.addListener(listener);
1020
1089
  return () => {
@@ -1024,8 +1093,8 @@ function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
1024
1093
  React.useEffect(() => {
1025
1094
  const listener = createListener(frontstageDef, ({ widgetDef }) => {
1026
1095
  (0, core_bentley_1.assert)(!!frontstageDef.nineZoneState);
1027
- let nineZoneState = (0, exports.showWidget)(frontstageDef.nineZoneState, widgetDef.id);
1028
- nineZoneState = (0, exports.expandWidget)(nineZoneState, widgetDef.id);
1096
+ let nineZoneState = showWidget(frontstageDef.nineZoneState, widgetDef.id);
1097
+ nineZoneState = expandWidget(nineZoneState, widgetDef.id);
1029
1098
  frontstageDef.nineZoneState = nineZoneState;
1030
1099
  });
1031
1100
  FrontstageManager_1.FrontstageManager.onWidgetExpandEvent.addListener(listener);
@@ -1054,7 +1123,7 @@ function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
1054
1123
  const listener = createListener(frontstageDef, ({ widgetDef }) => {
1055
1124
  (0, core_bentley_1.assert)(!!frontstageDef.nineZoneState);
1056
1125
  const label = widgetDef.label;
1057
- frontstageDef.nineZoneState = (0, exports.setWidgetLabel)(frontstageDef.nineZoneState, widgetDef.id, label);
1126
+ frontstageDef.nineZoneState = setWidgetLabel(frontstageDef.nineZoneState, widgetDef.id, label);
1058
1127
  });
1059
1128
  FrontstageManager_1.FrontstageManager.onWidgetLabelChangedEvent.addListener(listener);
1060
1129
  return () => {
@@ -1069,7 +1138,7 @@ function useFrontstageManager(frontstageDef, useToolAsToolSettingsLabel) {
1069
1138
  (0, core_bentley_1.assert)(!!frontstageDef.nineZoneState);
1070
1139
  const label = useToolAsToolSettingsLabel ?
1071
1140
  ((_a = core_frontend_1.IModelApp.tools.find(toolId)) === null || _a === void 0 ? void 0 : _a.flyover) || defaultLabel : defaultLabel;
1072
- frontstageDef.nineZoneState = (0, exports.setWidgetLabel)(frontstageDef.nineZoneState, appui_layout_react_1.toolSettingsTabId, label);
1141
+ frontstageDef.nineZoneState = setWidgetLabel(frontstageDef.nineZoneState, appui_layout_react_1.toolSettingsTabId, label);
1073
1142
  });
1074
1143
  // Whenever the frontstageDef or the useTool... changes, keep the label up to date.
1075
1144
  updateLabel();
@@ -1102,7 +1171,7 @@ function useItemsManager(frontstageDef) {
1102
1171
  return;
1103
1172
  state = addMissingWidgets(def, state);
1104
1173
  state = removeMissingWidgets(def, state);
1105
- state = removeHiddenWidgets(state, def); // TODO: should only apply to widgets provided by registered provider in onUiProviderRegisteredEvent.
1174
+ state = hideWidgets(state, def); // TODO: should only apply to widgets provided by registered provider in onUiProviderRegisteredEvent.
1106
1175
  def.nineZoneState = state;
1107
1176
  };
1108
1177
  React.useEffect(() => {
@@ -1116,48 +1185,8 @@ function useItemsManager(frontstageDef) {
1116
1185
  }, [frontstageDef]);
1117
1186
  }
1118
1187
  exports.useItemsManager = useItemsManager;
1119
- function tabShownInCurrentWidget(def, state) {
1120
- for (const [, widget] of Object.entries(state.widgets)) {
1121
- const foundTab = widget.tabs.find((tabId) => tabId === def.id);
1122
- // istanbul ignore else
1123
- if (foundTab)
1124
- return true;
1125
- }
1126
- return false;
1127
- }
1128
1188
  // istanbul ignore next
1129
1189
  function determineNewWidgets(defs, state) {
1130
- // if tab for widget.id is not found or the label does not match widget label (label is set to "undefined" when widgetDef is not initially available)
1131
- return (defs || []).filter((def) => !(def.id in state.tabs) || !tabShownInCurrentWidget(def, state));
1132
- }
1133
- /** @internal */
1134
- async function saveFrontstagePopoutWidgetSizeAndPosition(state, stageId, stageVersion, childWindowId, childWindow) {
1135
- const location = (0, appui_layout_react_1.findWidget)(state, childWindowId);
1136
- // istanbul ignore else
1137
- if (location) {
1138
- const adjustmentWidth = core_bentley_1.ProcessDetector.isElectronAppFrontend ? 16 : 0;
1139
- const adjustmentHeight = core_bentley_1.ProcessDetector.isElectronAppFrontend ? 39 : 0;
1140
- const newState = (0, immer_1.default)(state, (draft) => {
1141
- const widget = draft.widgets[childWindowId];
1142
- const tab = draft.tabs[widget.activeTabId];
1143
- tab.preferredPopoutWidgetSize = {
1144
- x: childWindow.screenX,
1145
- y: childWindow.screenY,
1146
- width: childWindow.innerWidth + adjustmentWidth,
1147
- height: childWindow.innerHeight + adjustmentHeight,
1148
- };
1149
- });
1150
- const setting = {
1151
- id: stageId,
1152
- nineZone: packNineZoneState(newState),
1153
- stateVersion,
1154
- version: stageVersion,
1155
- };
1156
- await UiFramework_1.UiFramework.getUiStateStorage().saveSetting(exports.FRONTSTAGE_SETTINGS_NAMESPACE, getFrontstageStateSettingName(stageId), setting);
1157
- return newState;
1158
- }
1159
- // istanbul ignore next
1160
- return state;
1190
+ return (defs || []).filter((def) => !(def.id in state.tabs));
1161
1191
  }
1162
- exports.saveFrontstagePopoutWidgetSizeAndPosition = saveFrontstagePopoutWidgetSizeAndPosition;
1163
1192
  //# sourceMappingURL=Frontstage.js.map