@tutti-os/workbench-surface 0.0.237 → 0.0.238

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.
package/dist/index.js CHANGED
@@ -1572,7 +1572,7 @@ function createWorkbenchController(initialState = {}, options = {}) {
1572
1572
  }
1573
1573
 
1574
1574
  // src/host/WorkbenchHost.tsx
1575
- import { useMemo as useMemo11 } from "react";
1575
+ import { useMemo as useMemo12 } from "react";
1576
1576
 
1577
1577
  // src/mission-control/WorkbenchMissionControlOverlay.tsx
1578
1578
  import {
@@ -2308,7 +2308,8 @@ function useWorkbenchMissionControlState({
2308
2308
  // src/react/WorkbenchSurface.tsx
2309
2309
  import {
2310
2310
  useCallback as useCallback8,
2311
- useEffect as useEffect5
2311
+ useEffect as useEffect5,
2312
+ useMemo as useMemo7
2312
2313
  } from "react";
2313
2314
 
2314
2315
  // src/react/WorkbenchDockFrame.tsx
@@ -2541,7 +2542,7 @@ function WorkbenchLockedSlotLayer() {
2541
2542
  }
2542
2543
 
2543
2544
  // src/react/WorkbenchNodeLayer.tsx
2544
- import { Fragment as Fragment3, memo, useMemo as useMemo5 } from "react";
2545
+ import { memo, useMemo as useMemo5, useSyncExternalStore as useSyncExternalStore2 } from "react";
2545
2546
  import { createPortal } from "react-dom";
2546
2547
 
2547
2548
  // src/react/WorkbenchWindowFrame.tsx
@@ -2923,9 +2924,27 @@ var defaultWindowChromeI18n = createWorkbenchWindowChromeI18nRuntime(
2923
2924
  })
2924
2925
  );
2925
2926
  var WorkbenchWindowPresentationVisibilityContext = createContext2(true);
2927
+ var noWorkbenchNodeIDs = /* @__PURE__ */ new Set();
2928
+ var defaultWorkbenchVisualOcclusionPresentation = {
2929
+ hiddenNodeIDs: noWorkbenchNodeIDs,
2930
+ nonOccludingNodeIDs: noWorkbenchNodeIDs,
2931
+ topLayerNodeIDs: []
2932
+ };
2933
+ var WorkbenchVisualOcclusionPresentationContext = createContext2(
2934
+ defaultWorkbenchVisualOcclusionPresentation
2935
+ );
2926
2936
  function useWorkbenchWindowPresentationVisibility() {
2927
2937
  return useContext2(WorkbenchWindowPresentationVisibilityContext);
2928
2938
  }
2939
+ function useWorkbenchVisualOcclusionPresentation() {
2940
+ return useContext2(WorkbenchVisualOcclusionPresentationContext);
2941
+ }
2942
+ function WorkbenchVisualOcclusionPresentationProvider({
2943
+ children,
2944
+ presentation
2945
+ }) {
2946
+ return /* @__PURE__ */ jsx7(WorkbenchVisualOcclusionPresentationContext.Provider, { value: presentation, children });
2947
+ }
2929
2948
  function resolveWorkbenchNodeLaunchSource(data) {
2930
2949
  if (data && typeof data === "object" && "launchSource" in data && typeof data.launchSource === "string" && data.launchSource.length > 0) {
2931
2950
  return data.launchSource;
@@ -2938,6 +2957,15 @@ function resolveWorkbenchNodeTypeId(data) {
2938
2957
  }
2939
2958
  return void 0;
2940
2959
  }
2960
+ function workbenchFramesEqual(left, right) {
2961
+ return left.x === right.x && left.y === right.y && left.width === right.width && left.height === right.height;
2962
+ }
2963
+ function isWorkbenchFrameTransitionProperty(propertyName) {
2964
+ return propertyName === "translate" || propertyName === "width" || propertyName === "height";
2965
+ }
2966
+ function shouldReduceWorkbenchMotion() {
2967
+ return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
2968
+ }
2941
2969
  function WorkbenchWindowFrame({
2942
2970
  children,
2943
2971
  edgeSnapEnabled = false,
@@ -2946,6 +2974,7 @@ function WorkbenchWindowFrame({
2946
2974
  interactive = true,
2947
2975
  minimizeNodeToAnchor: minimizeNodeToAnchorProp,
2948
2976
  node,
2977
+ nodePresentationTransitions,
2949
2978
  presentation = null,
2950
2979
  renderActions,
2951
2980
  renderHeader,
@@ -2954,6 +2983,7 @@ function WorkbenchWindowFrame({
2954
2983
  windowHeaderPresentation,
2955
2984
  windowChromeI18n
2956
2985
  }) {
2986
+ const shellRef = useRef3(null);
2957
2987
  const controller = useWorkbenchController();
2958
2988
  const baseZIndex = useWorkbenchSelector(
2959
2989
  (state) => selectWorkbenchNodeZIndex(state, node.id)
@@ -2992,6 +3022,86 @@ function WorkbenchWindowFrame({
2992
3022
  readGenieVisibility,
2993
3023
  readGenieVisibility
2994
3024
  );
3025
+ const launchSource = resolveWorkbenchNodeLaunchSource(node.data);
3026
+ const presentationMode = presentation?.mode ?? null;
3027
+ const previousFrameRef = useRef3(node.frame);
3028
+ useLayoutEffect3(() => {
3029
+ const previousFrame = previousFrameRef.current;
3030
+ previousFrameRef.current = node.frame;
3031
+ if (workbenchFramesEqual(previousFrame, node.frame)) {
3032
+ return;
3033
+ }
3034
+ nodePresentationTransitions.setActive(
3035
+ node.id,
3036
+ "frame",
3037
+ !hiddenMounted && !isGenieHidden && !isDragging && !isResizing && presentationMode === null
3038
+ );
3039
+ }, [
3040
+ hiddenMounted,
3041
+ isDragging,
3042
+ isGenieHidden,
3043
+ isResizing,
3044
+ node.frame.height,
3045
+ node.frame.width,
3046
+ node.frame.x,
3047
+ node.frame.y,
3048
+ node.id,
3049
+ nodePresentationTransitions,
3050
+ presentationMode
3051
+ ]);
3052
+ useLayoutEffect3(() => {
3053
+ const shell = shellRef.current;
3054
+ if (!shell) {
3055
+ return;
3056
+ }
3057
+ const activeFrameProperties = /* @__PURE__ */ new Set();
3058
+ const handleTransitionEvent = (event) => {
3059
+ if (event.target !== shell || !isWorkbenchFrameTransitionProperty(event.propertyName)) {
3060
+ return;
3061
+ }
3062
+ if (event.type === "transitionrun") {
3063
+ if (shell.dataset.windowDragState !== "dragging" && shell.dataset.windowResizeState !== "resizing" && shell.dataset.presentationMode === "default") {
3064
+ activeFrameProperties.add(event.propertyName);
3065
+ nodePresentationTransitions.setActive(node.id, "frame", true);
3066
+ }
3067
+ return;
3068
+ }
3069
+ activeFrameProperties.delete(event.propertyName);
3070
+ nodePresentationTransitions.setActive(
3071
+ node.id,
3072
+ "frame",
3073
+ activeFrameProperties.size > 0
3074
+ );
3075
+ };
3076
+ const handleAnimationEvent = (event) => {
3077
+ if (event.animationName !== "workbench-shell-enter" || !(event.target instanceof HTMLElement) || event.target.parentElement !== shell) {
3078
+ return;
3079
+ }
3080
+ nodePresentationTransitions.setActive(
3081
+ node.id,
3082
+ "onboarding-entry",
3083
+ event.type === "animationstart"
3084
+ );
3085
+ };
3086
+ shell.addEventListener("transitionrun", handleTransitionEvent);
3087
+ shell.addEventListener("transitionend", handleTransitionEvent);
3088
+ shell.addEventListener("transitioncancel", handleTransitionEvent);
3089
+ shell.addEventListener("animationstart", handleAnimationEvent);
3090
+ shell.addEventListener("animationend", handleAnimationEvent);
3091
+ shell.addEventListener("animationcancel", handleAnimationEvent);
3092
+ if (launchSource === "onboarding-auto" && !shouldReduceWorkbenchMotion()) {
3093
+ nodePresentationTransitions.setActive(node.id, "onboarding-entry", true);
3094
+ }
3095
+ return () => {
3096
+ shell.removeEventListener("transitionrun", handleTransitionEvent);
3097
+ shell.removeEventListener("transitionend", handleTransitionEvent);
3098
+ shell.removeEventListener("transitioncancel", handleTransitionEvent);
3099
+ shell.removeEventListener("animationstart", handleAnimationEvent);
3100
+ shell.removeEventListener("animationend", handleAnimationEvent);
3101
+ shell.removeEventListener("animationcancel", handleAnimationEvent);
3102
+ nodePresentationTransitions.clearNode(node.id);
3103
+ };
3104
+ }, [launchSource, node.id, nodePresentationTransitions]);
2995
3105
  const minimizeNodeToAnchorRef = useRef3(minimizeNodeToAnchorProp);
2996
3106
  useLayoutEffect3(() => {
2997
3107
  minimizeNodeToAnchorRef.current = minimizeNodeToAnchorProp;
@@ -3061,7 +3171,6 @@ function WorkbenchWindowFrame({
3061
3171
  const windowHeaderHeightPx = typeof windowHeaderPresentation?.heightPx === "number" && Number.isFinite(windowHeaderPresentation.heightPx) && windowHeaderPresentation.heightPx > 0 ? windowHeaderPresentation.heightPx : null;
3062
3172
  const shouldRenderCustomHeader = resolvedHeader.windowChromeMode === "custom-header";
3063
3173
  const resolvedFullscreenHeaderMode = "persistent";
3064
- const presentationMode = presentation?.mode ?? null;
3065
3174
  const presentationFrame = presentation?.frameByNodeId.get(node.id) ?? null;
3066
3175
  const isPresentationHidden = presentationMode === "mission-control" && !presentation?.visibleNodeIds.has(node.id);
3067
3176
  const isWindowPresentationVisible = !hiddenMounted && !isGenieHidden && presentationMode === null;
@@ -3083,12 +3192,13 @@ function WorkbenchWindowFrame({
3083
3192
  return /* @__PURE__ */ jsxs4(
3084
3193
  "section",
3085
3194
  {
3195
+ ref: shellRef,
3086
3196
  "aria-hidden": hiddenMounted || isPresentationHidden ? true : void 0,
3087
3197
  className: "workbench-window-shell",
3088
3198
  "data-focused": isFocused ? "true" : "false",
3089
3199
  "data-display-mode": node.displayMode,
3090
3200
  "data-genie-state": isGenieHidden ? "hidden" : "visible",
3091
- "data-launch-source": resolveWorkbenchNodeLaunchSource(node.data),
3201
+ "data-launch-source": launchSource,
3092
3202
  "data-minimized-mount": hiddenMounted ? "hidden" : "visible",
3093
3203
  "data-presentation-mode": presentationMode ?? "default",
3094
3204
  "data-presentation-visibility": isPresentationHidden ? "hidden" : "visible",
@@ -3276,6 +3386,7 @@ function WorkbenchNodeLayer({
3276
3386
  genie,
3277
3387
  edgeSnapEnabled = false,
3278
3388
  interactive = true,
3389
+ nodePresentationTransitions,
3279
3390
  presentation,
3280
3391
  renderNode,
3281
3392
  shouldKeepMinimizedNodeMounted,
@@ -3303,6 +3414,40 @@ function WorkbenchNodeLayer({
3303
3414
  const { defaultNodeIDs, dialogPopoverNodeIDs } = useWorkbenchSelector(
3304
3415
  selectNodeLayerNodeIDs
3305
3416
  );
3417
+ const genieHiddenNodeIDs = useSyncExternalStore2(
3418
+ genie.nodeVisibility.subscribeAll,
3419
+ genie.nodeVisibility.getHiddenNodeIDsSnapshot,
3420
+ genie.nodeVisibility.getHiddenNodeIDsSnapshot
3421
+ );
3422
+ const pendingMinimizedNodeID = genie.pendingMinimizedNode?.id ?? null;
3423
+ const visuallyHiddenNodeIDs = useMemo5(() => {
3424
+ if (pendingMinimizedNodeID === null || genieHiddenNodeIDs.has(pendingMinimizedNodeID)) {
3425
+ return genieHiddenNodeIDs;
3426
+ }
3427
+ return /* @__PURE__ */ new Set([...genieHiddenNodeIDs, pendingMinimizedNodeID]);
3428
+ }, [genieHiddenNodeIDs, pendingMinimizedNodeID]);
3429
+ const presentationTransitionNodeIDs = useSyncExternalStore2(
3430
+ nodePresentationTransitions.subscribe,
3431
+ nodePresentationTransitions.getSnapshot,
3432
+ nodePresentationTransitions.getSnapshot
3433
+ );
3434
+ const nonOccludingNodeIDs = useMemo5(() => {
3435
+ if (presentationTransitionNodeIDs.size === 0) {
3436
+ return visuallyHiddenNodeIDs;
3437
+ }
3438
+ return /* @__PURE__ */ new Set([
3439
+ ...visuallyHiddenNodeIDs,
3440
+ ...presentationTransitionNodeIDs
3441
+ ]);
3442
+ }, [presentationTransitionNodeIDs, visuallyHiddenNodeIDs]);
3443
+ const visualOcclusionPresentation = useMemo5(
3444
+ () => ({
3445
+ hiddenNodeIDs: visuallyHiddenNodeIDs,
3446
+ nonOccludingNodeIDs,
3447
+ topLayerNodeIDs: dialogPopoverNodeIDs
3448
+ }),
3449
+ [dialogPopoverNodeIDs, nonOccludingNodeIDs, visuallyHiddenNodeIDs]
3450
+ );
3306
3451
  const snapPreviewRect = useWorkbenchSelector(selectWorkbenchSnapPreviewRect);
3307
3452
  const presentationInteraction = interactive && presentation?.mode === "mission-control" ? presentation.interaction ?? null : null;
3308
3453
  const dialogPopoverLayer = dialogPopoverNodeIDs.length > 0 ? /* @__PURE__ */ jsx8(
@@ -3314,6 +3459,7 @@ function WorkbenchNodeLayer({
3314
3459
  genieNodeVisibility: genie.nodeVisibility,
3315
3460
  interactive,
3316
3461
  minimizeNodeToAnchor: genie.minimizeNodeToAnchor,
3462
+ nodePresentationTransitions,
3317
3463
  nodeIDs: dialogPopoverNodeIDs,
3318
3464
  presentation,
3319
3465
  renderNode,
@@ -3325,31 +3471,38 @@ function WorkbenchNodeLayer({
3325
3471
  windowChromeMode
3326
3472
  }
3327
3473
  ) : null;
3328
- return /* @__PURE__ */ jsxs5(Fragment3, { children: [
3329
- /* @__PURE__ */ jsx8(
3330
- MemoizedWorkbenchNodeLayerGroup,
3331
- {
3332
- className: "workbench-node-layer",
3333
- edgeSnapEnabled,
3334
- fullscreenHeaderMode: resolveFullscreenHeaderMode,
3335
- genieNodeVisibility: genie.nodeVisibility,
3336
- interactive,
3337
- minimizeNodeToAnchor: genie.minimizeNodeToAnchor,
3338
- nodeIDs: defaultNodeIDs,
3339
- onBackdropPress: presentationInteraction?.onBackdropPress,
3340
- presentation,
3341
- renderNode,
3342
- renderWindowActions,
3343
- renderWindowHeader,
3344
- resolveWindowHeaderPresentation,
3345
- resolveWindowZIndex,
3346
- snapPreviewRect,
3347
- windowChromeI18n,
3348
- windowChromeMode
3349
- }
3350
- ),
3351
- typeof document === "undefined" ? dialogPopoverLayer : dialogPopoverLayer ? createPortal(dialogPopoverLayer, document.body) : null
3352
- ] });
3474
+ return /* @__PURE__ */ jsxs5(
3475
+ WorkbenchVisualOcclusionPresentationProvider,
3476
+ {
3477
+ presentation: visualOcclusionPresentation,
3478
+ children: [
3479
+ /* @__PURE__ */ jsx8(
3480
+ MemoizedWorkbenchNodeLayerGroup,
3481
+ {
3482
+ className: "workbench-node-layer",
3483
+ edgeSnapEnabled,
3484
+ fullscreenHeaderMode: resolveFullscreenHeaderMode,
3485
+ genieNodeVisibility: genie.nodeVisibility,
3486
+ interactive,
3487
+ minimizeNodeToAnchor: genie.minimizeNodeToAnchor,
3488
+ nodePresentationTransitions,
3489
+ nodeIDs: defaultNodeIDs,
3490
+ onBackdropPress: presentationInteraction?.onBackdropPress,
3491
+ presentation,
3492
+ renderNode,
3493
+ renderWindowActions,
3494
+ renderWindowHeader,
3495
+ resolveWindowHeaderPresentation,
3496
+ resolveWindowZIndex,
3497
+ snapPreviewRect,
3498
+ windowChromeI18n,
3499
+ windowChromeMode
3500
+ }
3501
+ ),
3502
+ typeof document === "undefined" ? dialogPopoverLayer : dialogPopoverLayer ? createPortal(dialogPopoverLayer, document.body) : null
3503
+ ]
3504
+ }
3505
+ );
3353
3506
  }
3354
3507
  function WorkbenchNodeLayerGroup({
3355
3508
  className,
@@ -3358,6 +3511,7 @@ function WorkbenchNodeLayerGroup({
3358
3511
  genieNodeVisibility,
3359
3512
  interactive,
3360
3513
  minimizeNodeToAnchor,
3514
+ nodePresentationTransitions,
3361
3515
  nodeIDs,
3362
3516
  onBackdropPress,
3363
3517
  presentation,
@@ -3402,6 +3556,7 @@ function WorkbenchNodeLayerGroup({
3402
3556
  edgeSnapEnabled,
3403
3557
  interactive,
3404
3558
  minimizeNodeToAnchor,
3559
+ nodePresentationTransitions,
3405
3560
  nodeID,
3406
3561
  presentation,
3407
3562
  renderNode,
@@ -3427,6 +3582,7 @@ function WorkbenchNodeLayerItem({
3427
3582
  edgeSnapEnabled,
3428
3583
  interactive,
3429
3584
  minimizeNodeToAnchor,
3585
+ nodePresentationTransitions,
3430
3586
  nodeID,
3431
3587
  presentation,
3432
3588
  renderNode,
@@ -3466,6 +3622,7 @@ function WorkbenchNodeLayerItem({
3466
3622
  node,
3467
3623
  genieNodeVisibility,
3468
3624
  minimizeNodeToAnchor,
3625
+ nodePresentationTransitions,
3469
3626
  resolveWindowZIndex,
3470
3627
  fullscreenHeaderMode: fullscreenHeaderMode?.({
3471
3628
  controller,
@@ -4176,21 +4333,27 @@ function pruneWorkbenchGenieTextureCache(cache, limits) {
4176
4333
 
4177
4334
  // src/react/genieNodeVisibility.ts
4178
4335
  function createWorkbenchGenieNodeVisibilityStore() {
4179
- const hiddenNodeIDs = /* @__PURE__ */ new Set();
4336
+ let hiddenNodeIDs = /* @__PURE__ */ new Set();
4180
4337
  const hiddenTokenByNodeID = /* @__PURE__ */ new Map();
4181
4338
  const listenersByNodeID = /* @__PURE__ */ new Map();
4339
+ const allListeners = /* @__PURE__ */ new Set();
4182
4340
  const setHidden = (nodeID, hidden) => {
4183
4341
  if (hiddenNodeIDs.has(nodeID) === hidden) {
4184
4342
  return;
4185
4343
  }
4344
+ const nextHiddenNodeIDs = new Set(hiddenNodeIDs);
4186
4345
  if (hidden) {
4187
- hiddenNodeIDs.add(nodeID);
4346
+ nextHiddenNodeIDs.add(nodeID);
4188
4347
  } else {
4189
- hiddenNodeIDs.delete(nodeID);
4348
+ nextHiddenNodeIDs.delete(nodeID);
4190
4349
  }
4350
+ hiddenNodeIDs = nextHiddenNodeIDs;
4191
4351
  for (const listener of listenersByNodeID.get(nodeID) ?? []) {
4192
4352
  listener();
4193
4353
  }
4354
+ for (const listener of allListeners) {
4355
+ listener();
4356
+ }
4194
4357
  };
4195
4358
  const hide = (nodeID) => {
4196
4359
  const token = Symbol(nodeID);
@@ -4208,9 +4371,13 @@ function createWorkbenchGenieNodeVisibilityStore() {
4208
4371
  };
4209
4372
  return {
4210
4373
  dispose() {
4211
- hiddenNodeIDs.clear();
4374
+ hiddenNodeIDs = /* @__PURE__ */ new Set();
4212
4375
  hiddenTokenByNodeID.clear();
4213
4376
  listenersByNodeID.clear();
4377
+ allListeners.clear();
4378
+ },
4379
+ getHiddenNodeIDsSnapshot() {
4380
+ return hiddenNodeIDs;
4214
4381
  },
4215
4382
  getSnapshot(nodeID) {
4216
4383
  return hiddenNodeIDs.has(nodeID);
@@ -4223,6 +4390,12 @@ function createWorkbenchGenieNodeVisibilityStore() {
4223
4390
  show(nodeID);
4224
4391
  }
4225
4392
  },
4393
+ subscribeAll(listener) {
4394
+ allListeners.add(listener);
4395
+ return () => {
4396
+ allListeners.delete(listener);
4397
+ };
4398
+ },
4226
4399
  show,
4227
4400
  subscribe(nodeID, listener) {
4228
4401
  const listeners = listenersByNodeID.get(nodeID) ?? /* @__PURE__ */ new Set();
@@ -4353,7 +4526,7 @@ async function resolveNativeFirstGenieTexture({
4353
4526
  }
4354
4527
 
4355
4528
  // src/react/useWorkbenchGenieAnimation.tsx
4356
- import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
4529
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
4357
4530
  var genieDurationMs = 400;
4358
4531
  var previewCaptureRaceTimeoutMs = 120;
4359
4532
  var scaleMinimizeDurationMs = 220;
@@ -4817,6 +4990,7 @@ function useWorkbenchGenieAnimation({
4817
4990
  debugDiagnostics,
4818
4991
  dockPreviewCache,
4819
4992
  minimizeAnimation = "genie",
4993
+ nodePresentationTransitions,
4820
4994
  renderNodeGeniePreview,
4821
4995
  resolveDockAnchorKey,
4822
4996
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
@@ -5325,6 +5499,7 @@ function useWorkbenchGenieAnimation({
5325
5499
  return;
5326
5500
  }
5327
5501
  flushSync(() => {
5502
+ nodePresentationTransitions.setActive(nodeID, "scale-restore", true);
5328
5503
  showNodeForGenie(nodeID);
5329
5504
  });
5330
5505
  runScaleWindowAnimation({
@@ -5334,12 +5509,22 @@ function useWorkbenchGenieAnimation({
5334
5509
  onCancel: () => {
5335
5510
  flushSync(() => {
5336
5511
  showNodeForGenie(nodeID);
5512
+ nodePresentationTransitions.setActive(
5513
+ nodeID,
5514
+ "scale-restore",
5515
+ false
5516
+ );
5337
5517
  });
5338
5518
  clearMinimizedGenieTexture(nodeID);
5339
5519
  },
5340
5520
  onComplete: () => {
5341
5521
  flushSync(() => {
5342
5522
  showNodeForGenie(nodeID);
5523
+ nodePresentationTransitions.setActive(
5524
+ nodeID,
5525
+ "scale-restore",
5526
+ false
5527
+ );
5343
5528
  });
5344
5529
  clearMinimizedGenieTexture(nodeID);
5345
5530
  }
@@ -5404,6 +5589,7 @@ function useWorkbenchGenieAnimation({
5404
5589
  clearCanvas,
5405
5590
  clearMinimizedGenieTexture,
5406
5591
  minimizeAnimation,
5592
+ nodePresentationTransitions,
5407
5593
  readMinimizedGenieTexture,
5408
5594
  requestRenderedGeniePreviewTexture,
5409
5595
  resolveDockAnchorRect,
@@ -6072,7 +6258,7 @@ function useWorkbenchGenieAnimation({
6072
6258
  );
6073
6259
  const genieLayer = useMemo6(
6074
6260
  () => typeof document === "undefined" ? null : createPortal2(
6075
- /* @__PURE__ */ jsxs6(Fragment4, { children: [
6261
+ /* @__PURE__ */ jsxs6(Fragment3, { children: [
6076
6262
  /* @__PURE__ */ jsx9(
6077
6263
  "canvas",
6078
6264
  {
@@ -6131,6 +6317,71 @@ function useWorkbenchGenieAnimation({
6131
6317
  );
6132
6318
  }
6133
6319
 
6320
+ // src/react/nodePresentationTransitions.ts
6321
+ function createWorkbenchNodePresentationTransitionStore() {
6322
+ let activeNodeIDs = /* @__PURE__ */ new Set();
6323
+ const activeTransitionsByNodeID = /* @__PURE__ */ new Map();
6324
+ const listeners = /* @__PURE__ */ new Set();
6325
+ const publish = (nodeID, active) => {
6326
+ if (activeNodeIDs.has(nodeID) === active) {
6327
+ return;
6328
+ }
6329
+ const nextActiveNodeIDs = new Set(activeNodeIDs);
6330
+ if (active) {
6331
+ nextActiveNodeIDs.add(nodeID);
6332
+ } else {
6333
+ nextActiveNodeIDs.delete(nodeID);
6334
+ }
6335
+ activeNodeIDs = nextActiveNodeIDs;
6336
+ for (const listener of listeners) {
6337
+ listener();
6338
+ }
6339
+ };
6340
+ const clearNode = (nodeID) => {
6341
+ if (!activeTransitionsByNodeID.delete(nodeID)) {
6342
+ return;
6343
+ }
6344
+ publish(nodeID, false);
6345
+ };
6346
+ return {
6347
+ clearNode,
6348
+ dispose() {
6349
+ activeNodeIDs = /* @__PURE__ */ new Set();
6350
+ activeTransitionsByNodeID.clear();
6351
+ listeners.clear();
6352
+ },
6353
+ getSnapshot() {
6354
+ return activeNodeIDs;
6355
+ },
6356
+ setActive(nodeID, transition, active) {
6357
+ const activeTransitions = activeTransitionsByNodeID.get(nodeID) ?? /* @__PURE__ */ new Set();
6358
+ if (active) {
6359
+ if (activeTransitions.has(transition)) {
6360
+ return;
6361
+ }
6362
+ activeTransitions.add(transition);
6363
+ activeTransitionsByNodeID.set(nodeID, activeTransitions);
6364
+ publish(nodeID, true);
6365
+ return;
6366
+ }
6367
+ if (!activeTransitions.delete(transition)) {
6368
+ return;
6369
+ }
6370
+ if (activeTransitions.size > 0) {
6371
+ return;
6372
+ }
6373
+ activeTransitionsByNodeID.delete(nodeID);
6374
+ publish(nodeID, false);
6375
+ },
6376
+ subscribe(listener) {
6377
+ listeners.add(listener);
6378
+ return () => {
6379
+ listeners.delete(listener);
6380
+ };
6381
+ }
6382
+ };
6383
+ }
6384
+
6134
6385
  // src/react/WorkbenchSurface.tsx
6135
6386
  import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
6136
6387
  function WorkbenchSurface({
@@ -6251,6 +6502,10 @@ function WorkbenchSurfaceInner({
6251
6502
  [controller]
6252
6503
  );
6253
6504
  const ref = useWorkbenchSurfaceSize(onSizeChange);
6505
+ const nodePresentationTransitions = useMemo7(
6506
+ createWorkbenchNodePresentationTransitionStore,
6507
+ []
6508
+ );
6254
6509
  const genie = useWorkbenchGenieAnimation({
6255
6510
  captureNodePreviewImage,
6256
6511
  captureNodePreviewImages,
@@ -6258,11 +6513,16 @@ function WorkbenchSurfaceInner({
6258
6513
  debugDiagnostics,
6259
6514
  dockPreviewCache,
6260
6515
  minimizeAnimation,
6516
+ nodePresentationTransitions,
6261
6517
  renderNodeGeniePreview,
6262
6518
  resolveDockAnchorKey,
6263
6519
  resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
6264
6520
  shouldCaptureNodePreviewImage
6265
6521
  });
6522
+ useEffect5(
6523
+ () => () => nodePresentationTransitions.dispose(),
6524
+ [nodePresentationTransitions]
6525
+ );
6266
6526
  useWorkbenchShortcuts({
6267
6527
  enabled: (shortcutsEnabled ?? true) && interactive,
6268
6528
  windowManagementShortcutPreset: windowManagement?.shortcutPreset ?? null
@@ -6305,6 +6565,7 @@ function WorkbenchSurfaceInner({
6305
6565
  {
6306
6566
  genie,
6307
6567
  interactive,
6568
+ nodePresentationTransitions,
6308
6569
  presentation,
6309
6570
  renderNode,
6310
6571
  edgeSnapEnabled: windowManagement?.edgeSnapEnabled === true,
@@ -6509,7 +6770,7 @@ function resolveHostClosePreparer(contributions) {
6509
6770
  }
6510
6771
 
6511
6772
  // src/host/useWorkbenchHostRuntime.ts
6512
- import { useEffect as useEffect6, useMemo as useMemo8, useState as useState5 } from "react";
6773
+ import { useEffect as useEffect6, useMemo as useMemo9, useState as useState5 } from "react";
6513
6774
 
6514
6775
  // src/store/createDerivedSnapshotGetter.ts
6515
6776
  function createDerivedSnapshotGetter(input) {
@@ -7525,7 +7786,7 @@ function nullableRectsEqual(left, right) {
7525
7786
  }
7526
7787
 
7527
7788
  // src/host/externalState.ts
7528
- import { useCallback as useCallback9, useMemo as useMemo7, useSyncExternalStore as useSyncExternalStore2 } from "react";
7789
+ import { useCallback as useCallback9, useMemo as useMemo8, useSyncExternalStore as useSyncExternalStore3 } from "react";
7529
7790
  var noopSubscribe = () => () => {
7530
7791
  };
7531
7792
  function createWorkbenchHostExternalStateLookupInput(input) {
@@ -7539,14 +7800,14 @@ function createWorkbenchHostExternalStateLookupInput(input) {
7539
7800
  };
7540
7801
  }
7541
7802
  function useWorkbenchHostExternalState(input) {
7542
- const lookupInput = useMemo7(
7803
+ const lookupInput = useMemo8(
7543
7804
  () => createWorkbenchHostExternalStateLookupInput({
7544
7805
  node: input.node,
7545
7806
  workspaceId: input.workspaceId
7546
7807
  }),
7547
7808
  [input.node, input.workspaceId]
7548
7809
  );
7549
- const workspaceInput = useMemo7(
7810
+ const workspaceInput = useMemo8(
7550
7811
  () => ({ workspaceId: input.workspaceId }),
7551
7812
  [input.workspaceId]
7552
7813
  );
@@ -7570,12 +7831,12 @@ function useWorkbenchHostExternalState(input) {
7570
7831
  [input.externalStateSource, workspaceInput]
7571
7832
  );
7572
7833
  return {
7573
- externalNodeState: useSyncExternalStore2(
7834
+ externalNodeState: useSyncExternalStore3(
7574
7835
  subscribeNodeState,
7575
7836
  getNodeState,
7576
7837
  getNodeState
7577
7838
  ),
7578
- externalWorkspaceState: useSyncExternalStore2(
7839
+ externalWorkspaceState: useSyncExternalStore3(
7579
7840
  subscribeWorkspaceState,
7580
7841
  getWorkspaceState,
7581
7842
  getWorkspaceState
@@ -8663,7 +8924,7 @@ function useWorkbenchHostRuntime({
8663
8924
  workspaceId
8664
8925
  }) {
8665
8926
  const [, bumpHydrationRevision] = useState5(0);
8666
- const hostSession = useMemo8(() => {
8927
+ const hostSession = useMemo9(() => {
8667
8928
  logWorkbenchHostDebug("create-session", debugDiagnostics, {
8668
8929
  nodeTypeIDs: nodes.map((node) => node.typeId),
8669
8930
  projectedNodeCount: projectedNodes?.length ?? 0,
@@ -8688,32 +8949,32 @@ function useWorkbenchHostRuntime({
8688
8949
  snapshotRepository,
8689
8950
  workspaceId
8690
8951
  ]);
8691
- const hostI18n = useMemo8(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
8692
- const missionControlI18n = useMemo8(
8952
+ const hostI18n = useMemo9(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
8953
+ const missionControlI18n = useMemo9(
8693
8954
  () => createWorkbenchMissionControlI18nRuntime(i18n),
8694
8955
  [i18n]
8695
8956
  );
8696
- const windowChromeI18n = useMemo8(
8957
+ const windowChromeI18n = useMemo9(
8697
8958
  () => createWorkbenchWindowChromeI18nRuntime(i18n),
8698
8959
  [i18n]
8699
8960
  );
8700
- const nodeDefinitionByType = useMemo8(
8961
+ const nodeDefinitionByType = useMemo9(
8701
8962
  () => new Map(nodes.map((definition) => [definition.typeId, definition])),
8702
8963
  [nodes]
8703
8964
  );
8704
8965
  const isHydrating = hostSession.isHydrating?.() ?? false;
8705
- const missionControlAdapter = useMemo8(
8966
+ const missionControlAdapter = useMemo9(
8706
8967
  () => missionControlEnabled && !isHydrating ? createWorkbenchHostMissionControlAdapter({
8707
8968
  activateNode: hostSession.activateNode.bind(hostSession),
8708
8969
  controller: hostSession.controller
8709
8970
  }) : null,
8710
8971
  [hostSession.controller, isHydrating, missionControlEnabled]
8711
8972
  );
8712
- const chromeController = useMemo8(
8973
+ const chromeController = useMemo9(
8713
8974
  () => isHydrating ? createReadOnlyWorkbenchController(hostSession.controller) : hostSession.controller,
8714
8975
  [hostSession.controller, isHydrating]
8715
8976
  );
8716
- const chromeContext = useMemo8(
8977
+ const chromeContext = useMemo9(
8717
8978
  () => ({
8718
8979
  activateNode: hostSession.activateNode.bind(hostSession),
8719
8980
  controller: chromeController,
@@ -8802,14 +9063,14 @@ function logWorkbenchHostDebug(event, debugDiagnostics, payload) {
8802
9063
  }
8803
9064
 
8804
9065
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
8805
- import { Component, memo as memo3, useCallback as useCallback13, useMemo as useMemo10 } from "react";
9066
+ import { Component, memo as memo3, useCallback as useCallback13, useMemo as useMemo11 } from "react";
8806
9067
 
8807
9068
  // src/host/WorkbenchHostDock.tsx
8808
9069
  import {
8809
9070
  useCallback as useCallback12,
8810
9071
  useEffect as useEffect10,
8811
9072
  useLayoutEffect as useLayoutEffect7,
8812
- useMemo as useMemo9,
9073
+ useMemo as useMemo10,
8813
9074
  useRef as useRef9,
8814
9075
  useState as useState8
8815
9076
  } from "react";
@@ -10213,7 +10474,7 @@ function resolveDockPopupVerticalClampOffsetPx(input) {
10213
10474
  }
10214
10475
 
10215
10476
  // src/host/WorkbenchHostDockPopup.tsx
10216
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
10477
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
10217
10478
  var dockPopupCardWidthPx = 165;
10218
10479
  var dockPopupCardHeightPx = 103;
10219
10480
  var dockPopupPreviewInsetPx = 4;
@@ -10854,7 +11115,7 @@ function WorkbenchHostDockPopup({
10854
11115
  showAllWindowsLabel,
10855
11116
  showOpen: showOpen === true
10856
11117
  }
10857
- ) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
11118
+ ) : /* @__PURE__ */ jsxs8(Fragment4, { children: [
10858
11119
  /* @__PURE__ */ jsx11("div", { className: "mb-2.5 flex items-center justify-between", children: /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate text-sm font-semibold", children: label }) }),
10859
11120
  isMinimizedStack ? /* @__PURE__ */ jsx11(
10860
11121
  "div",
@@ -11002,7 +11263,7 @@ function WorkbenchHostDockContextMenu({
11002
11263
  "data-desktop-dock-context-menu": "true",
11003
11264
  role: "menu",
11004
11265
  children: [
11005
- hasOpenWindows ? /* @__PURE__ */ jsx11(Fragment5, { children: /* @__PURE__ */ jsx11("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx11(
11266
+ hasOpenWindows ? /* @__PURE__ */ jsx11(Fragment4, { children: /* @__PURE__ */ jsx11("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx11(
11006
11267
  WorkbenchHostDockContextMenuItem,
11007
11268
  {
11008
11269
  checked: !item.isMinimized,
@@ -11046,7 +11307,7 @@ function WorkbenchHostDockContextMenu({
11046
11307
  onSelect: onCreateNew
11047
11308
  }
11048
11309
  ) : null,
11049
- hasOpenWindows ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
11310
+ hasOpenWindows ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
11050
11311
  hasDockActionGroup ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
11051
11312
  canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx11(
11052
11313
  WorkbenchHostDockContextMenuItem,
@@ -11452,7 +11713,7 @@ function WorkbenchHostDock({
11452
11713
  onMissionControlRequestOpen,
11453
11714
  workspaceId
11454
11715
  }) {
11455
- const minimizedNodeIDs = useMemo9(
11716
+ const minimizedNodeIDs = useMemo10(
11456
11717
  () => new Set(context.minimizedNodes.map((node) => node.id)),
11457
11718
  [context.minimizedNodes]
11458
11719
  );
@@ -11640,14 +11901,14 @@ function WorkbenchHostDock({
11640
11901
  setDockStateRevision((revision) => revision + 1);
11641
11902
  });
11642
11903
  }, [dockStateSource]);
11643
- const renderedDockEntries = useMemo9(
11904
+ const renderedDockEntries = useMemo10(
11644
11905
  () => dockEntries.map((entry) => {
11645
11906
  const dynamicState = dockStateSource?.getEntryState(entry.id);
11646
11907
  return dynamicState ? { ...entry, ...dynamicState } : entry;
11647
11908
  }),
11648
11909
  [dockEntries, dockStateRevision, dockStateSource]
11649
11910
  );
11650
- const resolvedEntries = useMemo9(
11911
+ const resolvedEntries = useMemo10(
11651
11912
  () => resolveWorkbenchDockEntries({
11652
11913
  dockEntries: renderedDockEntries,
11653
11914
  minimizedNodeIds: minimizedNodeIDs,
@@ -11655,7 +11916,7 @@ function WorkbenchHostDock({
11655
11916
  }),
11656
11917
  [context.nodes, minimizedNodeIDs, renderedDockEntries]
11657
11918
  );
11658
- const minimizedDockSlots = useMemo9(
11919
+ const minimizedDockSlots = useMemo10(
11659
11920
  () => resolveWorkbenchMinimizedDockSlots({
11660
11921
  nodeDefinitions,
11661
11922
  nodes: context.minimizedNodes
@@ -11663,7 +11924,7 @@ function WorkbenchHostDock({
11663
11924
  [context.minimizedNodes, nodeDefinitions]
11664
11925
  );
11665
11926
  const { promotedNodeId, stackDispatching } = useMinimizedDockStackPromotion(minimizedDockSlots);
11666
- const dockItems = useMemo9(
11927
+ const dockItems = useMemo10(
11667
11928
  () => createWorkbenchHostDockItems({
11668
11929
  minimizedDockSlots,
11669
11930
  resolvedEntries
@@ -11674,7 +11935,7 @@ function WorkbenchHostDock({
11674
11935
  dockItems,
11675
11936
  (nodeId) => context.genie.shouldAnimateMinimizedDockEnter(nodeId)
11676
11937
  );
11677
- const presentDockItemKeys = useMemo9(
11938
+ const presentDockItemKeys = useMemo10(
11678
11939
  () => presentDockItems.map((item) => item.key).join("\n"),
11679
11940
  [presentDockItems]
11680
11941
  );
@@ -11683,7 +11944,7 @@ function WorkbenchHostDock({
11683
11944
  elementRefs: wallpaperToneElementRefs,
11684
11945
  itemKeys: presentDockItemKeys
11685
11946
  });
11686
- const dockWidth = useMemo9(
11947
+ const dockWidth = useMemo10(
11687
11948
  () => resolveWorkbenchHostDockItemsWidth(dockItems),
11688
11949
  [dockItems]
11689
11950
  );
@@ -14533,7 +14794,7 @@ function WorkbenchHostWindowActions({
14533
14794
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
14534
14795
  import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14535
14796
  function useWorkbenchHostSurfaceRenderers(input) {
14536
- const renderBottomChrome = useMemo10(() => {
14797
+ const renderBottomChrome = useMemo11(() => {
14537
14798
  const renderChrome = input.renderBottomChrome;
14538
14799
  return renderChrome ? () => /* @__PURE__ */ jsx14(
14539
14800
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -14561,7 +14822,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14561
14822
  input.renderBottomChrome,
14562
14823
  input.workspaceId
14563
14824
  ]);
14564
- const renderTopChrome = useMemo10(() => {
14825
+ const renderTopChrome = useMemo11(() => {
14565
14826
  const renderChrome = input.renderTopChrome;
14566
14827
  return renderChrome ? () => /* @__PURE__ */ jsx14(
14567
14828
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -14912,7 +15173,7 @@ function WorkbenchHostNodeRenderer(input) {
14912
15173
  isVisible,
14913
15174
  workspaceId: input.workspaceId
14914
15175
  });
14915
- const resetKey = useMemo10(
15176
+ const resetKey = useMemo11(
14916
15177
  () => [
14917
15178
  input.context.node.id,
14918
15179
  input.context.node.data.typeId,
@@ -15202,7 +15463,7 @@ function WorkbenchHost({
15202
15463
  windowManagement,
15203
15464
  workspaceId
15204
15465
  }) {
15205
- const hostRuntimeConfig = useMemo11(
15466
+ const hostRuntimeConfig = useMemo12(
15206
15467
  () => resolveWorkbenchHostRuntimeConfig({
15207
15468
  contributions,
15208
15469
  externalStateSource,
@@ -15218,7 +15479,7 @@ function WorkbenchHost({
15218
15479
  onNodeCloseRequest
15219
15480
  ]
15220
15481
  );
15221
- const hostDockEntries = useMemo11(
15482
+ const hostDockEntries = useMemo12(
15222
15483
  () => resolveWorkbenchHostDockEntries({
15223
15484
  contributions,
15224
15485
  dockEntryPresentationOverrides,
@@ -15393,21 +15654,43 @@ function WorkbenchDockComponentPreviewFrame({
15393
15654
  }
15394
15655
 
15395
15656
  // src/core/visualOcclusion.ts
15657
+ var noNodeIDs = /* @__PURE__ */ new Set();
15658
+ var defaultVisualOcclusionPresentation = {
15659
+ hiddenNodeIDs: noNodeIDs,
15660
+ nonOccludingNodeIDs: noNodeIDs,
15661
+ topLayerNodeIDs: []
15662
+ };
15396
15663
  var exposedNodeIDsByState = /* @__PURE__ */ new WeakMap();
15397
- function selectVisuallyExposedWorkbenchNodeIDs(state) {
15398
- const cached = exposedNodeIDsByState.get(state);
15399
- if (cached) {
15400
- return cached;
15664
+ var exposedNodeIDsByNodeStack = /* @__PURE__ */ new WeakMap();
15665
+ function selectVisuallyExposedWorkbenchNodeIDs(state, presentation = defaultVisualOcclusionPresentation) {
15666
+ const cachedByState = exposedNodeIDsByState.get(state);
15667
+ if (cachedByState?.presentation === presentation) {
15668
+ return cachedByState.exposedNodeIDs;
15669
+ }
15670
+ const cachedByGeometry = exposedNodeIDsByNodeStack.get(state.nodeStack);
15671
+ if (cachedByGeometry && cachedByGeometry.presentation === presentation && hasEquivalentVisualOcclusionGeometry(cachedByGeometry, state)) {
15672
+ cachedByGeometry.nodes = state.nodes;
15673
+ cachedByGeometry.surfaceSize = state.surfaceSize;
15674
+ exposedNodeIDsByState.set(state, {
15675
+ exposedNodeIDs: cachedByGeometry.exposedNodeIDs,
15676
+ presentation
15677
+ });
15678
+ return cachedByGeometry.exposedNodeIDs;
15401
15679
  }
15402
15680
  const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
15403
15681
  const stackedIDs = new Set(state.nodeStack);
15404
- const orderedNodes = [
15682
+ const stackOrderedNodes = [
15405
15683
  ...state.nodes.filter((node) => !stackedIDs.has(node.id)),
15406
15684
  ...state.nodeStack.flatMap((nodeID) => {
15407
15685
  const node = nodeByID.get(nodeID);
15408
15686
  return node ? [node] : [];
15409
15687
  })
15410
15688
  ];
15689
+ const topLayerNodeIDs = new Set(presentation.topLayerNodeIDs);
15690
+ const orderedNodes = topLayerNodeIDs.size === 0 ? stackOrderedNodes : [
15691
+ ...stackOrderedNodes.filter((node) => !topLayerNodeIDs.has(node.id)),
15692
+ ...stackOrderedNodes.filter((node) => topLayerNodeIDs.has(node.id))
15693
+ ];
15411
15694
  const surfaceFrame = {
15412
15695
  x: 0,
15413
15696
  y: 0,
@@ -15416,7 +15699,7 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15416
15699
  };
15417
15700
  const exposedNodeIDs = /* @__PURE__ */ new Set();
15418
15701
  orderedNodes.forEach((node, nodeIndex) => {
15419
- if (node.isMinimized) {
15702
+ if (node.isMinimized || presentation.hiddenNodeIDs.has(node.id)) {
15420
15703
  return;
15421
15704
  }
15422
15705
  const visibleFrame = intersectFrames(node.frame, surfaceFrame);
@@ -15426,7 +15709,7 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15426
15709
  let uncoveredFrames = [visibleFrame];
15427
15710
  for (let occluderIndex = nodeIndex + 1; occluderIndex < orderedNodes.length && uncoveredFrames.length > 0; occluderIndex += 1) {
15428
15711
  const occluder = orderedNodes[occluderIndex];
15429
- if (!occluder || occluder.isMinimized) {
15712
+ if (!occluder || occluder.isMinimized || presentation.hiddenNodeIDs.has(occluder.id) || presentation.nonOccludingNodeIDs.has(occluder.id)) {
15430
15713
  continue;
15431
15714
  }
15432
15715
  uncoveredFrames = uncoveredFrames.flatMap(
@@ -15437,11 +15720,20 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15437
15720
  exposedNodeIDs.add(node.id);
15438
15721
  }
15439
15722
  });
15440
- exposedNodeIDsByState.set(state, exposedNodeIDs);
15723
+ exposedNodeIDsByState.set(state, {
15724
+ exposedNodeIDs,
15725
+ presentation
15726
+ });
15727
+ exposedNodeIDsByNodeStack.set(state.nodeStack, {
15728
+ exposedNodeIDs,
15729
+ nodes: state.nodes,
15730
+ presentation,
15731
+ surfaceSize: state.surfaceSize
15732
+ });
15441
15733
  return exposedNodeIDs;
15442
15734
  }
15443
- function selectWorkbenchNodeIsVisuallyExposed(state, nodeID) {
15444
- return selectVisuallyExposedWorkbenchNodeIDs(state).has(nodeID);
15735
+ function selectWorkbenchNodeIsVisuallyExposed(state, nodeID, presentation) {
15736
+ return selectVisuallyExposedWorkbenchNodeIDs(state, presentation).has(nodeID);
15445
15737
  }
15446
15738
  function intersectFrames(left, right) {
15447
15739
  const x = Math.max(left.x, right.x);
@@ -15505,6 +15797,18 @@ function pushFrame(frames, frame) {
15505
15797
  frames.push(frame);
15506
15798
  }
15507
15799
  }
15800
+ function hasEquivalentVisualOcclusionGeometry(cached, state) {
15801
+ if (cached.surfaceSize.width !== state.surfaceSize.width || cached.surfaceSize.height !== state.surfaceSize.height || cached.nodes.length !== state.nodes.length) {
15802
+ return false;
15803
+ }
15804
+ if (cached.nodes === state.nodes) {
15805
+ return true;
15806
+ }
15807
+ return cached.nodes.every((cachedNode, index) => {
15808
+ const node = state.nodes[index];
15809
+ return node !== void 0 && cachedNode.id === node.id && cachedNode.isMinimized === node.isMinimized && cachedNode.frame.x === node.frame.x && cachedNode.frame.y === node.frame.y && cachedNode.frame.width === node.frame.width && cachedNode.frame.height === node.frame.height;
15810
+ });
15811
+ }
15508
15812
  export {
15509
15813
  WorkbenchDockComponentPreviewFrame,
15510
15814
  WorkbenchHost,
@@ -15534,6 +15838,7 @@ export {
15534
15838
  selectVisuallyExposedWorkbenchNodeIDs,
15535
15839
  selectWorkbenchNodeIsVisuallyExposed,
15536
15840
  useWorkbenchSelector,
15841
+ useWorkbenchVisualOcclusionPresentation,
15537
15842
  workbenchFocusInputActivationType,
15538
15843
  workbenchHostI18nResources,
15539
15844
  workbenchWindowChromeI18nNamespace,