@tutti-os/workbench-surface 0.0.237 → 0.0.239

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,16 +9063,16 @@ 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 useCallback14, useMemo as useMemo11 } from "react";
8806
9067
 
8807
9068
  // src/host/WorkbenchHostDock.tsx
8808
9069
  import {
8809
- useCallback as useCallback12,
8810
- useEffect as useEffect10,
8811
- useLayoutEffect as useLayoutEffect7,
8812
- useMemo as useMemo9,
8813
- useRef as useRef9,
8814
- useState as useState8
9070
+ useCallback as useCallback13,
9071
+ useEffect as useEffect12,
9072
+ useLayoutEffect as useLayoutEffect8,
9073
+ useMemo as useMemo10,
9074
+ useRef as useRef11,
9075
+ useState as useState10
8815
9076
  } from "react";
8816
9077
  import {
8817
9078
  ArrowLeftIcon,
@@ -10046,26 +10307,14 @@ function resolveWorkbenchMinimizedDockRestoreIntent(input) {
10046
10307
 
10047
10308
  // src/host/WorkbenchHostDockPopup.tsx
10048
10309
  import {
10049
- forwardRef,
10050
- useCallback as useCallback11,
10051
- useEffect as useEffect9,
10052
- useLayoutEffect as useLayoutEffect6,
10053
- useRef as useRef8,
10054
- useState as useState7
10310
+ useCallback as useCallback12,
10311
+ useEffect as useEffect11,
10312
+ useLayoutEffect as useLayoutEffect7,
10313
+ useRef as useRef10,
10314
+ useState as useState9
10055
10315
  } from "react";
10056
10316
  import { createPortal as createPortal3 } from "react-dom";
10057
- import {
10058
- Button as Button2,
10059
- CheckIcon,
10060
- CloseIcon,
10061
- FileCreateIcon,
10062
- MaximizeIcon,
10063
- MinimizeIcon,
10064
- OverviewLayoutIcon,
10065
- PinFilledIcon,
10066
- PinIcon,
10067
- cn
10068
- } from "@tutti-os/ui-system";
10317
+ import { FileCreateIcon as FileCreateIcon2, cn as cn2 } from "@tutti-os/ui-system";
10069
10318
 
10070
10319
  // src/host/minimizedStackScroll.ts
10071
10320
  var minimizedStackViewportMarginPx = 56;
@@ -10212,24 +10461,28 @@ function resolveDockPopupVerticalClampOffsetPx(input) {
10212
10461
  return 0;
10213
10462
  }
10214
10463
 
10215
- // src/host/WorkbenchHostDockPopup.tsx
10216
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
10217
- var dockPopupCardWidthPx = 165;
10218
- var dockPopupCardHeightPx = 103;
10219
- var dockPopupPreviewInsetPx = 4;
10220
- var workbenchHostDockPopupPreviewViewport = Object.freeze({
10221
- height: dockPopupCardHeightPx - dockPopupPreviewInsetPx * 2,
10222
- width: dockPopupCardWidthPx - dockPopupPreviewInsetPx * 2
10223
- });
10224
- var dockPopupGridGapPx = 8;
10225
- var dockPopupPanelPaddingInlinePx = 12;
10226
- var dockPopupPanelBorderInlinePx = 2;
10227
- var dockPopupPlacementGapPx = 14;
10464
+ // src/host/WorkbenchHostDockPopupPresentation.tsx
10465
+ import {
10466
+ forwardRef,
10467
+ useCallback as useCallback11,
10468
+ useEffect as useEffect9,
10469
+ useRef as useRef8,
10470
+ useState as useState7
10471
+ } from "react";
10472
+ import {
10473
+ Button as Button2,
10474
+ CheckIcon,
10475
+ CloseIcon,
10476
+ FileCreateIcon,
10477
+ MaximizeIcon,
10478
+ MinimizeIcon,
10479
+ OverviewLayoutIcon,
10480
+ PinFilledIcon,
10481
+ PinIcon,
10482
+ cn
10483
+ } from "@tutti-os/ui-system";
10484
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
10228
10485
  var dockPopupMinimizedStackLaunchDisappearMs = 0;
10229
- var dockPopupMinimizedStackPopupZIndex = 100300;
10230
- var dockPopupPreviewCacheMaxEntries = 64;
10231
- var dockPopupPreviewByMemoryKey = /* @__PURE__ */ new Map();
10232
- var pendingDockPopupPreviewCaptureKeys = /* @__PURE__ */ new Set();
10233
10486
  var popupCardMagnificationRange = 160;
10234
10487
  var popupCardMaxScale = 1.16;
10235
10488
  var popupCardMaxLiftPx = 10;
@@ -10268,317 +10521,418 @@ function resolvePopupFanCardStyle(index, count, placement) {
10268
10521
  "--desktop-dock-popup-fan-y": `${Math.round(arcY)}px`
10269
10522
  };
10270
10523
  }
10271
- function readDockPopupPreviewImage(memoryKey) {
10272
- return dockPopupPreviewByMemoryKey.get(memoryKey);
10273
- }
10274
- function writeDockPopupPreviewImage(memoryKey, preview, revision) {
10275
- dockPopupPreviewByMemoryKey.delete(memoryKey);
10276
- dockPopupPreviewByMemoryKey.set(memoryKey, { preview, revision });
10277
- while (dockPopupPreviewByMemoryKey.size > dockPopupPreviewCacheMaxEntries) {
10278
- const oldestMemoryKey = dockPopupPreviewByMemoryKey.keys().next().value;
10279
- if (typeof oldestMemoryKey !== "string") {
10280
- break;
10281
- }
10282
- dockPopupPreviewByMemoryKey.delete(oldestMemoryKey);
10283
- }
10284
- }
10285
- function WorkbenchHostDockPopup({
10286
- anchorRect,
10524
+ function WorkbenchHostDockContextMenu({
10525
+ canCreateNew,
10287
10526
  canEnterFullscreen,
10288
10527
  canShowAllWindows,
10289
- capturePreview,
10290
- debugDiagnostics,
10291
10528
  dockRetention,
10292
- dockPreviewCache,
10293
10529
  fullscreenLabel,
10294
10530
  hideLabel,
10295
10531
  items,
10296
- label,
10297
- labelMode,
10298
10532
  newWindowLabel,
10299
- closeWindowLabel,
10300
- onClose,
10301
- onCloseNode,
10302
10533
  onCreateNew,
10303
10534
  onEnterFullscreen,
10304
10535
  onHide,
10536
+ onQuit,
10305
10537
  onRunDockRetentionAction,
10306
10538
  onSelectNode,
10307
10539
  onShowAllWindows,
10308
- onQuit,
10309
- placement = "bottom",
10310
10540
  quitLabel,
10311
- resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
10312
10541
  showAllWindowsLabel,
10313
- showCreateNew,
10314
- showCreateNewInContextMenu,
10315
- showOpen,
10316
- variant
10542
+ showOpen
10317
10543
  }) {
10318
- const resolvedShowCreateNewInContextMenu = showCreateNewInContextMenu ?? showCreateNew;
10319
- const resolvedLabelMode = labelMode ?? "hover-overlay";
10320
- const resolvedVariant = variant ?? "default";
10321
- const isMinimizedStack = resolvedVariant === "minimized-stack";
10322
- const isContextMenu = resolvedVariant === "context-menu";
10323
- const hasCapturePreview = Boolean(capturePreview);
10324
- const createCardCount = showCreateNew === false ? 0 : 1;
10325
- const cardElementsRef = useRef8(/* @__PURE__ */ new Map());
10326
- const cardRefCallbacksRef = useRef8(
10327
- /* @__PURE__ */ new Map()
10328
- );
10329
- const popupRootRef = useRef8(null);
10330
- const minimizedStackViewportRef = useRef8(null);
10331
- const [pointer, setPointer] = useState7(null);
10332
- const [minimizedStackScrollOffset, setMinimizedStackScrollOffset] = useState7(0);
10333
- const [verticalClampOffsetPx, setVerticalClampOffsetPx] = useState7(0);
10334
- const [capturedPreviewByMemoryKey, setCapturedPreviewByMemoryKey] = useState7({});
10335
- const capturedPreviewByMemoryKeyRef = useRef8(capturedPreviewByMemoryKey);
10336
- const capturePreviewRef = useRef8(capturePreview);
10337
- const debugDiagnosticsRef = useRef8(debugDiagnostics);
10338
- const dockPreviewCacheRef = useRef8(dockPreviewCache);
10339
- const resolveDockPreviewCacheKeyRef = useRef8(resolveDockPreviewCacheKey2);
10340
- capturedPreviewByMemoryKeyRef.current = capturedPreviewByMemoryKey;
10341
- capturePreviewRef.current = capturePreview;
10342
- debugDiagnosticsRef.current = debugDiagnostics;
10343
- dockPreviewCacheRef.current = dockPreviewCache;
10344
- resolveDockPreviewCacheKeyRef.current = resolveDockPreviewCacheKey2;
10345
- const columnCount = isContextMenu ? 1 : Math.min(Math.max(items.length + createCardCount, 1), 3);
10346
- const popupWidthPx = isContextMenu ? 268 : columnCount * dockPopupCardWidthPx + Math.max(0, columnCount - 1) * dockPopupGridGapPx + dockPopupPanelPaddingInlinePx * 2 + dockPopupPanelBorderInlinePx;
10347
- const popupCenterY = anchorRect.top + anchorRect.height / 2;
10348
- const isLeftMinimizedStack = placement === "left" && isMinimizedStack;
10349
- const minimizedStackTrackHeightPx = resolveMinimizedStackTrackHeightPx(
10350
- items.length
10351
- );
10352
- const minimizedStackViewportHeightPx = isMinimizedStack ? resolveMinimizedStackViewportHeightPx({
10353
- anchorCenterY: popupCenterY,
10354
- placement,
10355
- trackHeightPx: minimizedStackTrackHeightPx
10356
- }) : minimizedStackTrackHeightPx;
10357
- const minimizedStackTrackTranslateXPx = isMinimizedStack ? resolveMinimizedStackTrackTranslateXPx({
10358
- itemCount: items.length,
10359
- placement,
10360
- scrollOffset: minimizedStackScrollOffset,
10361
- trackHeightPx: minimizedStackTrackHeightPx,
10362
- viewportHeightPx: minimizedStackViewportHeightPx
10363
- }) : 0;
10364
- const minimizedStackLeftGutterPx = isLeftMinimizedStack ? resolveMinimizedStackLeftGutterPx({
10365
- itemCount: items.length,
10366
- placement,
10367
- scrollOffset: minimizedStackScrollOffset,
10368
- trackHeightPx: minimizedStackTrackHeightPx,
10369
- viewportHeightPx: minimizedStackViewportHeightPx,
10370
- trackTranslateXPx: minimizedStackTrackTranslateXPx
10371
- }) : 0;
10372
- const minimizedStackPanelWidthPx = isLeftMinimizedStack ? resolveMinimizedStackPanelWidthPx(items.length, placement, {
10373
- leftGutterPx: minimizedStackLeftGutterPx
10374
- }) : null;
10375
- const popupStyle = {
10376
- "--desktop-dock-popup-columns": String(columnCount),
10377
- "--desktop-dock-popup-width": minimizedStackPanelWidthPx != null ? `${minimizedStackPanelWidthPx}px` : `${popupWidthPx}px`,
10378
- ...minimizedStackPanelWidthPx != null ? {
10379
- "--desktop-dock-minimized-stack-width": `${minimizedStackPanelWidthPx}px`,
10380
- minWidth: minimizedStackPanelWidthPx,
10381
- width: minimizedStackPanelWidthPx
10382
- } : {},
10383
- left: isLeftMinimizedStack ? resolveMinimizedStackPopupLeftPx({
10384
- anchorLeft: anchorRect.left,
10385
- anchorWidth: anchorRect.width,
10386
- dockRightPx: anchorRect.dockRight,
10387
- leftGutterPx: minimizedStackLeftGutterPx
10388
- }) : placement === "left" ? anchorRect.left + anchorRect.width + dockPopupPlacementGapPx : anchorRect.left + anchorRect.width / 2,
10389
- top: isLeftMinimizedStack ? resolveMinimizedStackPopupTopPx({ anchorTop: anchorRect.top }) : placement === "left" ? popupCenterY : anchorRect.top - dockPopupPlacementGapPx,
10390
- ...isLeftMinimizedStack ? { zIndex: dockPopupMinimizedStackPopupZIndex } : {},
10391
- ...isMinimizedStack ? {} : { "--desktop-dock-popup-clamp-offset": `${verticalClampOffsetPx}px` }
10392
- };
10393
- const minimizedStackMaxScrollOffset = Math.max(
10394
- 0,
10395
- minimizedStackTrackHeightPx - minimizedStackViewportHeightPx
10544
+ const hasOpenWindows = items.length > 0;
10545
+ const hasNewWindowCommand = hasOpenWindows && canCreateNew;
10546
+ const hasOpenCommand = !hasOpenWindows;
10547
+ const hasDockActionGroup = Boolean(dockRetention) || hasNewWindowCommand || hasOpenCommand;
10548
+ const hasWindowActionGroup = hasOpenWindows;
10549
+ return /* @__PURE__ */ jsxs8(
10550
+ "div",
10551
+ {
10552
+ className: "flex min-w-0 flex-col gap-1",
10553
+ "data-desktop-dock-context-menu": "true",
10554
+ role: "menu",
10555
+ children: [
10556
+ hasOpenWindows ? /* @__PURE__ */ jsx11("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx11(
10557
+ WorkbenchHostDockContextMenuItem,
10558
+ {
10559
+ checked: !item.isMinimized,
10560
+ label: item.title?.trim() || item.node.title,
10561
+ onSelect: () => onSelectNode(item.node.id)
10562
+ },
10563
+ item.node.id
10564
+ )) }) : null,
10565
+ hasOpenWindows && (hasDockActionGroup || hasWindowActionGroup) ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
10566
+ dockRetention ? /* @__PURE__ */ jsx11(
10567
+ WorkbenchHostDockContextMenuItem,
10568
+ {
10569
+ checked: dockRetention.checked,
10570
+ checkedIcon: /* @__PURE__ */ jsx11(
10571
+ PinFilledIcon,
10572
+ {
10573
+ "aria-hidden": "true",
10574
+ className: "size-4 text-[var(--tutti-purple)]"
10575
+ }
10576
+ ),
10577
+ disabled: dockRetention.disabled,
10578
+ icon: /* @__PURE__ */ jsx11(PinIcon, { "aria-hidden": "true", className: "size-4" }),
10579
+ label: dockRetention.pendingLabel ?? dockRetention.label,
10580
+ onSelect: onRunDockRetentionAction
10581
+ }
10582
+ ) : null,
10583
+ hasNewWindowCommand ? /* @__PURE__ */ jsx11(
10584
+ WorkbenchHostDockContextMenuItem,
10585
+ {
10586
+ icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
10587
+ label: newWindowLabel,
10588
+ onSelect: onCreateNew
10589
+ }
10590
+ ) : null,
10591
+ hasOpenCommand ? /* @__PURE__ */ jsx11(
10592
+ WorkbenchHostDockContextMenuItem,
10593
+ {
10594
+ disabled: !showOpen,
10595
+ icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
10596
+ label: newWindowLabel,
10597
+ onSelect: onCreateNew
10598
+ }
10599
+ ) : null,
10600
+ hasOpenWindows ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
10601
+ hasDockActionGroup ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
10602
+ canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx11(
10603
+ WorkbenchHostDockContextMenuItem,
10604
+ {
10605
+ icon: /* @__PURE__ */ jsx11(OverviewLayoutIcon, { "aria-hidden": "true", className: "size-4" }),
10606
+ label: showAllWindowsLabel,
10607
+ onSelect: onShowAllWindows
10608
+ }
10609
+ ) : null,
10610
+ /* @__PURE__ */ jsx11(
10611
+ WorkbenchHostDockContextMenuItem,
10612
+ {
10613
+ disabled: !canEnterFullscreen || !onEnterFullscreen,
10614
+ icon: /* @__PURE__ */ jsx11(MaximizeIcon, { "aria-hidden": "true", className: "size-4" }),
10615
+ label: fullscreenLabel,
10616
+ onSelect: onEnterFullscreen
10617
+ }
10618
+ ),
10619
+ /* @__PURE__ */ jsx11(
10620
+ WorkbenchHostDockContextMenuItem,
10621
+ {
10622
+ disabled: !onHide,
10623
+ icon: /* @__PURE__ */ jsx11(MinimizeIcon, { "aria-hidden": "true", className: "size-4" }),
10624
+ label: hideLabel,
10625
+ onSelect: onHide
10626
+ }
10627
+ ),
10628
+ /* @__PURE__ */ jsx11(
10629
+ WorkbenchHostDockContextMenuItem,
10630
+ {
10631
+ disabled: !onQuit,
10632
+ icon: /* @__PURE__ */ jsx11(CloseIcon, { "aria-hidden": "true", className: "size-4" }),
10633
+ label: quitLabel,
10634
+ onSelect: onQuit
10635
+ }
10636
+ )
10637
+ ] }) : null
10638
+ ]
10639
+ }
10396
10640
  );
10397
- const initialMinimizedStackScrollOffset = resolveInitialMinimizedStackScrollOffset({
10398
- maxScrollOffset: minimizedStackMaxScrollOffset
10399
- });
10400
- const panelStyle = {
10401
- "--desktop-dock-popup-columns": String(columnCount),
10402
- "--desktop-dock-popup-item-count": String(Math.max(1, items.length)),
10403
- ...isMinimizedStack ? {
10404
- height: minimizedStackViewportHeightPx,
10405
- minHeight: minimizedStackViewportHeightPx,
10406
- ...isLeftMinimizedStack && minimizedStackPanelWidthPx != null ? {
10407
- width: minimizedStackPanelWidthPx,
10408
- minWidth: minimizedStackPanelWidthPx,
10409
- "--desktop-dock-minimized-stack-left-gutter": `${minimizedStackLeftGutterPx}px`
10410
- } : {}
10411
- } : {}
10412
- };
10413
- const popupDiagnosticKey = items.map((item) => item.node.id).join("|");
10414
- useEffect9(() => {
10415
- logWorkbenchDockPopupDebug("dock.popup.rendered", debugDiagnostics, {
10416
- hasCapturePreview: Boolean(capturePreview),
10417
- itemCount: popupDiagnosticKey ? popupDiagnosticKey.split("|").length : 0,
10418
- nodeIds: popupDiagnosticKey ? popupDiagnosticKey.split("|") : [],
10419
- placement,
10420
- variant: resolvedVariant
10421
- });
10422
- }, [
10423
- capturePreview,
10424
- debugDiagnostics,
10425
- placement,
10426
- popupDiagnosticKey,
10427
- resolvedVariant
10428
- ]);
10429
- useLayoutEffect6(() => {
10430
- const rootElement = popupRootRef.current;
10431
- const panelElement = rootElement?.querySelector(
10432
- "[data-desktop-dock-popup-panel]"
10433
- ) ?? null;
10434
- logWorkbenchDockPopupDebug("dock.popup.layout", debugDiagnostics, {
10435
- panelRect: panelElement ? rectToDiagnostic(panelElement) : null,
10436
- rootRect: rootElement ? rectToDiagnostic(rootElement) : null,
10437
- rootStyle: rootElement ? styleToDiagnostic(rootElement) : null,
10438
- viewportHeight: window.innerHeight,
10439
- viewportWidth: window.innerWidth
10440
- });
10441
- }, [debugDiagnostics, popupDiagnosticKey]);
10442
- useLayoutEffect6(() => {
10443
- if (isMinimizedStack || typeof window === "undefined") {
10641
+ }
10642
+ function WorkbenchHostDockContextMenuItem({
10643
+ checked,
10644
+ checkedIcon,
10645
+ disabled,
10646
+ icon,
10647
+ label,
10648
+ onSelect
10649
+ }) {
10650
+ return /* @__PURE__ */ jsxs8(
10651
+ "button",
10652
+ {
10653
+ className: cn(
10654
+ "flex h-8 w-full min-w-0 items-center gap-2 rounded-md px-2 text-left text-sm text-[var(--text-primary)] transition-colors",
10655
+ disabled ? "cursor-default opacity-45" : "hover:bg-transparency-hover focus-visible:bg-transparency-hover focus-visible:outline-none"
10656
+ ),
10657
+ disabled,
10658
+ role: "menuitem",
10659
+ type: "button",
10660
+ onClick: () => {
10661
+ if (disabled || !onSelect) {
10662
+ return;
10663
+ }
10664
+ onSelect();
10665
+ },
10666
+ children: [
10667
+ /* @__PURE__ */ jsx11("span", { className: "flex size-4 shrink-0 items-center justify-center text-[var(--text-secondary)]", children: checked && checkedIcon ? checkedIcon : checked ? /* @__PURE__ */ jsx11(
10668
+ CheckIcon,
10669
+ {
10670
+ "aria-hidden": "true",
10671
+ className: "size-4 text-[var(--tutti-purple)]"
10672
+ }
10673
+ ) : icon ?? null }),
10674
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: label })
10675
+ ]
10676
+ }
10677
+ );
10678
+ }
10679
+ function WorkbenchHostDockContextMenuSeparator() {
10680
+ return /* @__PURE__ */ jsx11(
10681
+ "div",
10682
+ {
10683
+ "aria-hidden": "true",
10684
+ className: "mx-2 my-1 h-px bg-[var(--border-1)]",
10685
+ role: "separator"
10686
+ }
10687
+ );
10688
+ }
10689
+ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2({
10690
+ closeWindowLabel,
10691
+ item,
10692
+ labelMode,
10693
+ onCloseNode,
10694
+ onSelectNode,
10695
+ previewState,
10696
+ style,
10697
+ variant
10698
+ }, ref) {
10699
+ const title = item.title?.trim() || item.node.title;
10700
+ const isMinimizedStack = variant === "minimized-stack";
10701
+ const [isLaunching, setIsLaunching] = useState7(false);
10702
+ const launchTimerRef = useRef8(null);
10703
+ useEffect9(
10704
+ () => () => {
10705
+ if (launchTimerRef.current !== null) {
10706
+ clearTimeout(launchTimerRef.current);
10707
+ }
10708
+ },
10709
+ []
10710
+ );
10711
+ const handleSelect = useCallback11(() => {
10712
+ if (!isMinimizedStack) {
10713
+ onSelectNode(item.node.id);
10444
10714
  return;
10445
10715
  }
10446
- const rootElement = popupRootRef.current;
10447
- const panelElement = rootElement?.querySelector(
10448
- "[data-desktop-dock-popup-panel]"
10449
- );
10450
- if (!panelElement) {
10716
+ if (launchTimerRef.current !== null) {
10451
10717
  return;
10452
10718
  }
10453
- const measureAndClamp = () => {
10454
- const panelHeightPx = panelElement.offsetHeight;
10455
- const naturalTopPx = placement === "left" ? popupCenterY - panelHeightPx / 2 : anchorRect.top - dockPopupPlacementGapPx - panelHeightPx;
10456
- const naturalBottomPx = placement === "left" ? popupCenterY + panelHeightPx / 2 : anchorRect.top - dockPopupPlacementGapPx;
10457
- const offsetPx = resolveDockPopupVerticalClampOffsetPx({
10458
- naturalBottomPx,
10459
- naturalTopPx,
10460
- viewportHeightPx: window.innerHeight
10461
- });
10462
- setVerticalClampOffsetPx(
10463
- (current) => current === offsetPx ? current : offsetPx
10464
- );
10465
- };
10466
- measureAndClamp();
10467
- const resizeObserver = new ResizeObserver(measureAndClamp);
10468
- resizeObserver.observe(panelElement);
10469
- window.addEventListener("resize", measureAndClamp);
10470
- return () => {
10471
- resizeObserver.disconnect();
10472
- window.removeEventListener("resize", measureAndClamp);
10473
- };
10474
- }, [
10475
- anchorRect.top,
10476
- isMinimizedStack,
10477
- placement,
10478
- popupCenterY,
10479
- popupDiagnosticKey
10480
- ]);
10481
- const registerCard = useCallback11((nodeId) => {
10482
- const existing = cardRefCallbacksRef.current.get(nodeId);
10483
- if (existing) {
10484
- return existing;
10485
- }
10486
- const callback = (element) => {
10487
- if (element) {
10488
- cardElementsRef.current.set(nodeId, element);
10489
- } else {
10490
- cardElementsRef.current.delete(nodeId);
10719
+ setIsLaunching(true);
10720
+ launchTimerRef.current = setTimeout(() => {
10721
+ launchTimerRef.current = null;
10722
+ onSelectNode(item.node.id);
10723
+ }, dockPopupMinimizedStackLaunchDisappearMs);
10724
+ }, [isMinimizedStack, item.node.id, onSelectNode]);
10725
+ const handleSelectKeyDown = useCallback11(
10726
+ (event) => {
10727
+ if (event.key !== "Enter" && event.key !== " ") {
10728
+ return;
10491
10729
  }
10492
- };
10493
- cardRefCallbacksRef.current.set(nodeId, callback);
10494
- return callback;
10495
- }, []);
10496
- useEffect9(() => {
10497
- if (!isLeftMinimizedStack) {
10498
- return;
10730
+ event.preventDefault();
10731
+ handleSelect();
10732
+ },
10733
+ [handleSelect]
10734
+ );
10735
+ const hasReadyPreview = previewState.status === "ready";
10736
+ return /* @__PURE__ */ jsxs8(
10737
+ "div",
10738
+ {
10739
+ ref,
10740
+ className: cn(
10741
+ "group/dock-popup-card relative flex h-[103px] w-[165px] min-w-0 flex-col overflow-hidden rounded-[8px] border border-[var(--border-1)] bg-background-fronted text-left text-[var(--text-primary)] transition-[border-color,color] duration-150",
10742
+ item.isMinimized && "text-[var(--text-secondary)]"
10743
+ ),
10744
+ "data-active": item.isFocused ? "true" : void 0,
10745
+ "data-desktop-dock-popup-card": "true",
10746
+ "data-fan-card": isMinimizedStack ? "true" : void 0,
10747
+ "data-launching": isLaunching ? "true" : void 0,
10748
+ "data-minimized": item.isMinimized ? "true" : void 0,
10749
+ style,
10750
+ children: [
10751
+ /* @__PURE__ */ jsxs8(
10752
+ "div",
10753
+ {
10754
+ "aria-label": title,
10755
+ "data-active": item.isFocused ? "true" : void 0,
10756
+ className: cn(
10757
+ "relative flex min-h-0 min-w-0 flex-1 cursor-pointer flex-col overflow-hidden rounded-md bg-transparent text-inherit",
10758
+ hasReadyPreview ? "p-0" : "p-1"
10759
+ ),
10760
+ role: "button",
10761
+ tabIndex: 0,
10762
+ onClick: handleSelect,
10763
+ onKeyDown: handleSelectKeyDown,
10764
+ children: [
10765
+ /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardPreview, { previewState }),
10766
+ labelMode === "hover-overlay" && item.title?.trim() ? /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardLabel, { title: item.title }) : null
10767
+ ]
10768
+ }
10769
+ ),
10770
+ /* @__PURE__ */ jsx11(
10771
+ Button2,
10772
+ {
10773
+ "aria-label": closeWindowLabel(title),
10774
+ className: "absolute top-1.5 right-1.5 z-[2] rounded-full bg-[var(--background-fronted)] opacity-0 transition-[background-color,opacity] duration-150 hover:bg-[var(--background-fronted)] focus-visible:bg-[var(--background-fronted)] group-hover/dock-popup-card:opacity-100 group-focus-within/dock-popup-card:opacity-100 focus-visible:opacity-100",
10775
+ size: "icon-sm",
10776
+ title: closeWindowLabel(title),
10777
+ type: "button",
10778
+ variant: "ghost",
10779
+ onClick: (event) => {
10780
+ event.preventDefault();
10781
+ event.stopPropagation();
10782
+ onCloseNode(item.node.id);
10783
+ },
10784
+ children: /* @__PURE__ */ jsx11(CloseIcon, { className: "size-3.5" })
10785
+ }
10786
+ ),
10787
+ item.isFocused ? /* @__PURE__ */ jsx11(
10788
+ "span",
10789
+ {
10790
+ "aria-hidden": "true",
10791
+ className: "pointer-events-none absolute inset-0 z-[3] rounded-md shadow-[inset_0_0_0_2px_var(--border-focus)]",
10792
+ "data-desktop-dock-popup-card-active-overlay": "true"
10793
+ }
10794
+ ) : null,
10795
+ isMinimizedStack ? /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__fan-title-tip", title, children: title }) : null
10796
+ ]
10499
10797
  }
10500
- document.body.setAttribute(
10501
- "data-desktop-dock-minimized-stack-open",
10502
- "true"
10503
- );
10504
- return () => {
10505
- document.body.removeAttribute("data-desktop-dock-minimized-stack-open");
10506
- };
10507
- }, [isLeftMinimizedStack]);
10508
- useEffect9(() => {
10509
- const handlePointerDown = (event) => {
10510
- if (!(event.target instanceof Element)) {
10511
- onClose();
10512
- return;
10798
+ );
10799
+ });
10800
+ function WorkbenchHostDockPopupCardPreview({
10801
+ previewState
10802
+ }) {
10803
+ if (previewState.status === "loading") {
10804
+ return /* @__PURE__ */ jsxs8(
10805
+ "span",
10806
+ {
10807
+ className: "flex min-h-0 min-w-0 flex-1 flex-col justify-center gap-[7px] rounded-md border border-[var(--border-1)] bg-transparency-block px-3 py-[11px]",
10808
+ "aria-hidden": "true",
10809
+ "data-preview-state": previewState.status,
10810
+ children: [
10811
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[72%] rounded-full bg-transparency-hover" }),
10812
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[58%] rounded-full bg-transparency-hover" }),
10813
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[34%] rounded-full bg-transparency-hover" })
10814
+ ]
10513
10815
  }
10514
- if (event.target.closest("[data-desktop-dock-slot]") || event.target.closest("[data-desktop-dock-popup-card]") || event.target.closest(
10515
- '.desktop-dock-popup-root:not([data-popup-variant="minimized-stack"])'
10516
- )) {
10517
- return;
10816
+ );
10817
+ }
10818
+ if (previewState.status === "fallback") {
10819
+ return /* @__PURE__ */ jsx11(
10820
+ "span",
10821
+ {
10822
+ className: "flex min-h-0 min-w-0 flex-1 rounded-md border border-[var(--border-1)] bg-transparency-block",
10823
+ "aria-hidden": "true",
10824
+ "data-preview-state": previewState.status
10518
10825
  }
10519
- onClose();
10520
- };
10521
- const handleKeyDown = (event) => {
10522
- if (event.key === "Escape") {
10523
- onClose();
10826
+ );
10827
+ }
10828
+ const preview = previewState.preview;
10829
+ if (preview.kind === "component") {
10830
+ return /* @__PURE__ */ jsx11(
10831
+ "span",
10832
+ {
10833
+ className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
10834
+ "aria-hidden": "true",
10835
+ "data-preview-kind": preview.kind,
10836
+ "data-preview-state": previewState.status,
10837
+ children: preview.element
10524
10838
  }
10525
- };
10526
- window.addEventListener("pointerdown", handlePointerDown, true);
10527
- window.addEventListener("keydown", handleKeyDown);
10528
- return () => {
10529
- window.removeEventListener("pointerdown", handlePointerDown, true);
10530
- window.removeEventListener("keydown", handleKeyDown);
10531
- };
10532
- }, [onClose]);
10533
- const previewCaptureKey = items.map((item) => {
10534
- const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10535
- item.node,
10536
- resolveDockPreviewCacheKey2?.(item.node) ?? null
10537
10839
  );
10538
- return [
10539
- previewMemoryKey,
10540
- item.isMinimized ? "minimized" : "visible",
10541
- previewCacheToken(item.preview),
10542
- item.previewRevision ?? ""
10543
- ].join(":");
10544
- }).join("|");
10545
- useEffect9(() => {
10546
- if (!isMinimizedStack) {
10547
- return;
10548
- }
10549
- setMinimizedStackScrollOffset(initialMinimizedStackScrollOffset);
10550
- }, [initialMinimizedStackScrollOffset, isMinimizedStack, items.length]);
10551
- useEffect9(() => {
10552
- if (!isMinimizedStack) {
10553
- return;
10840
+ }
10841
+ return /* @__PURE__ */ jsx11(
10842
+ "span",
10843
+ {
10844
+ className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
10845
+ "aria-hidden": "true",
10846
+ "data-preview-kind": preview.kind,
10847
+ "data-preview-state": previewState.status,
10848
+ children: /* @__PURE__ */ jsx11(
10849
+ "img",
10850
+ {
10851
+ alt: "",
10852
+ className: "block h-full max-h-full w-full max-w-full object-contain object-center",
10853
+ draggable: false,
10854
+ src: preview.src
10855
+ }
10856
+ )
10554
10857
  }
10555
- const viewport = minimizedStackViewportRef.current;
10556
- if (!viewport) {
10557
- return;
10858
+ );
10859
+ }
10860
+ function WorkbenchHostDockPopupCardLabel({ title }) {
10861
+ return /* @__PURE__ */ jsx11(
10862
+ "span",
10863
+ {
10864
+ className: "pointer-events-none absolute inset-x-0 bottom-0 z-[1] flex h-[30px] items-end px-[10px] pb-0.5 text-[var(--white-stationary)] opacity-0 transition-opacity duration-150 [text-shadow:0_1px_2px_rgb(0_0_0_/_20%)] group-hover/dock-popup-card:opacity-100 group-focus-within/dock-popup-card:opacity-100",
10865
+ style: {
10866
+ background: "linear-gradient(180deg, transparent 0%, color-mix(in srgb, hsl(var(--card)) 28%, transparent) 18%, color-mix(in srgb, hsl(var(--card)) 82%, transparent) 56%, color-mix(in srgb, hsl(var(--card)) 98%, transparent) 100%)"
10867
+ },
10868
+ title,
10869
+ children: /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__title-viewport block min-w-0 flex-1 overflow-hidden whitespace-nowrap", children: /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__title-marquee inline-block max-w-full overflow-hidden text-[12px] font-semibold leading-5 text-ellipsis whitespace-nowrap", children: title }) })
10558
10870
  }
10559
- const handleWheel = (event) => {
10560
- event.preventDefault();
10561
- event.stopPropagation();
10562
- setMinimizedStackScrollOffset(
10563
- (current) => Math.min(
10564
- minimizedStackMaxScrollOffset,
10565
- Math.max(0, current + event.deltaY)
10566
- )
10567
- );
10871
+ );
10872
+ }
10873
+
10874
+ // src/host/useWorkbenchHostDockPopupPreviewCapture.ts
10875
+ import { useEffect as useEffect10, useLayoutEffect as useLayoutEffect6, useRef as useRef9, useState as useState8 } from "react";
10876
+ var dockPopupPreviewCacheMaxEntries = 64;
10877
+ var dockPopupPreviewByMemoryKey = /* @__PURE__ */ new Map();
10878
+ var pendingDockPopupPreviewCaptureKeys = /* @__PURE__ */ new Set();
10879
+ function useWorkbenchHostDockPopupPreviewCapture(input) {
10880
+ const {
10881
+ capturePreview,
10882
+ debugDiagnostics,
10883
+ dockPreviewCache,
10884
+ isContextMenu,
10885
+ items,
10886
+ resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
10887
+ } = input;
10888
+ const hasCapturePreview = Boolean(capturePreview);
10889
+ const [capturedPreviewByMemoryKey, setCapturedPreviewByMemoryKey] = useState8({});
10890
+ const capturedPreviewByMemoryKeyRef = useRef9(capturedPreviewByMemoryKey);
10891
+ const capturePreviewRef = useRef9(capturePreview);
10892
+ const debugDiagnosticsRef = useRef9(debugDiagnostics);
10893
+ const dockPreviewCacheRef = useRef9(dockPreviewCache);
10894
+ const resolveDockPreviewCacheKeyRef = useRef9(resolveDockPreviewCacheKey2);
10895
+ const isMountedRef = useRef9(false);
10896
+ const isContextMenuRef = useRef9(isContextMenu);
10897
+ const activePreviewCaptureItemStateKeysRef = useRef9(
10898
+ /* @__PURE__ */ new Set()
10899
+ );
10900
+ capturedPreviewByMemoryKeyRef.current = capturedPreviewByMemoryKey;
10901
+ capturePreviewRef.current = capturePreview;
10902
+ debugDiagnosticsRef.current = debugDiagnostics;
10903
+ dockPreviewCacheRef.current = dockPreviewCache;
10904
+ resolveDockPreviewCacheKeyRef.current = resolveDockPreviewCacheKey2;
10905
+ const previewCaptureItemStateKeys = items.map(
10906
+ (item) => resolveDockPopupPreviewItemStateKey(
10907
+ item,
10908
+ resolveDockPreviewCacheKey2?.(item.node) ?? null
10909
+ )
10910
+ );
10911
+ const previewCaptureKey = previewCaptureItemStateKeys.join("|");
10912
+ useLayoutEffect6(() => {
10913
+ isContextMenuRef.current = isContextMenu;
10914
+ activePreviewCaptureItemStateKeysRef.current = new Set(
10915
+ previewCaptureItemStateKeys
10916
+ );
10917
+ });
10918
+ useEffect10(() => {
10919
+ isMountedRef.current = true;
10920
+ return () => {
10921
+ isMountedRef.current = false;
10568
10922
  };
10569
- viewport.addEventListener("wheel", handleWheel, { passive: false });
10570
- return () => viewport.removeEventListener("wheel", handleWheel);
10571
- }, [isMinimizedStack, minimizedStackMaxScrollOffset]);
10572
- useEffect9(() => {
10923
+ }, []);
10924
+ useEffect10(() => {
10573
10925
  if (!capturePreviewRef.current || isContextMenu) {
10574
10926
  return;
10575
10927
  }
10576
- let cancelled = false;
10928
+ const captureItemStateIsCurrent = (itemStateKey) => isMountedRef.current && !isContextMenuRef.current && activePreviewCaptureItemStateKeysRef.current.has(itemStateKey);
10929
+ let captureEffectActive = true;
10930
+ const ownedCaptureKeys = /* @__PURE__ */ new Set();
10577
10931
  const startedCaptureKeys = /* @__PURE__ */ new Set();
10578
10932
  const missingItems = items.filter((item) => {
10579
10933
  const revision = item.previewRevision;
10580
10934
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10581
- item.node,
10935
+ item,
10582
10936
  resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null
10583
10937
  );
10584
10938
  const pendingCaptureKey = resolveDockPopupPreviewCaptureKey(
@@ -10587,25 +10941,22 @@ function WorkbenchHostDockPopup({
10587
10941
  );
10588
10942
  const capturedPreview = capturedPreviewByMemoryKeyRef.current[previewMemoryKey] ?? readDockPopupPreviewImage(previewMemoryKey);
10589
10943
  const hasCapturedPreview = capturedPreview !== void 0 && capturedPreview.revision === revision;
10590
- const shouldCaptureMissingPreview = !item.preview && !hasCapturedPreview;
10591
- return shouldCaptureMissingPreview && !pendingDockPopupPreviewCaptureKeys.has(pendingCaptureKey);
10944
+ return !item.preview && !hasCapturedPreview && !pendingDockPopupPreviewCaptureKeys.has(pendingCaptureKey);
10592
10945
  });
10593
10946
  if (missingItems.length === 0) {
10594
10947
  logWorkbenchDockPopupDebug(
10595
10948
  "dock.popup.preview_capture.batch",
10596
- debugDiagnostics,
10949
+ debugDiagnosticsRef.current,
10597
10950
  {
10598
10951
  itemCount: items.length,
10599
10952
  missingNodeIds: []
10600
10953
  }
10601
10954
  );
10602
- return () => {
10603
- cancelled = true;
10604
- };
10955
+ return;
10605
10956
  }
10606
10957
  logWorkbenchDockPopupDebug(
10607
10958
  "dock.popup.preview_capture.batch",
10608
- debugDiagnostics,
10959
+ debugDiagnosticsRef.current,
10609
10960
  {
10610
10961
  itemCount: items.length,
10611
10962
  missingNodeIds: missingItems.map((item) => item.node.id)
@@ -10613,30 +10964,40 @@ function WorkbenchHostDockPopup({
10613
10964
  );
10614
10965
  for (const item of missingItems) {
10615
10966
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10616
- item.node,
10967
+ item,
10617
10968
  resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null
10618
10969
  );
10619
- pendingDockPopupPreviewCaptureKeys.add(
10620
- resolveDockPopupPreviewCaptureKey(
10621
- previewMemoryKey,
10622
- item.previewRevision
10623
- )
10624
- );
10970
+ const pendingCaptureKey = resolveDockPopupPreviewCaptureKey(
10971
+ previewMemoryKey,
10972
+ item.previewRevision
10973
+ );
10974
+ pendingDockPopupPreviewCaptureKeys.add(pendingCaptureKey);
10975
+ ownedCaptureKeys.add(pendingCaptureKey);
10625
10976
  }
10626
10977
  void (async () => {
10627
10978
  for (const item of missingItems) {
10628
- if (cancelled) {
10979
+ if (!captureEffectActive) {
10629
10980
  break;
10630
10981
  }
10631
10982
  const revision = item.previewRevision;
10983
+ const resolvedCacheKey = resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null;
10632
10984
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10633
- item.node,
10634
- resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null
10985
+ item,
10986
+ resolvedCacheKey
10635
10987
  );
10636
10988
  const pendingCaptureKey = resolveDockPopupPreviewCaptureKey(
10637
10989
  previewMemoryKey,
10638
10990
  revision
10639
10991
  );
10992
+ const itemStateKey = resolveDockPopupPreviewItemStateKey(
10993
+ item,
10994
+ resolvedCacheKey
10995
+ );
10996
+ if (!captureItemStateIsCurrent(itemStateKey)) {
10997
+ pendingDockPopupPreviewCaptureKeys.delete(pendingCaptureKey);
10998
+ ownedCaptureKeys.delete(pendingCaptureKey);
10999
+ continue;
11000
+ }
10640
11001
  startedCaptureKeys.add(pendingCaptureKey);
10641
11002
  try {
10642
11003
  logWorkbenchDockPopupDebug(
@@ -10649,7 +11010,7 @@ function WorkbenchHostDockPopup({
10649
11010
  }
10650
11011
  );
10651
11012
  const cacheKey = resolveDockPopupPreviewCacheKey(
10652
- resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null,
11013
+ resolvedCacheKey,
10653
11014
  revision
10654
11015
  );
10655
11016
  if (item.isMinimized && cacheKey) {
@@ -10657,8 +11018,8 @@ function WorkbenchHostDockPopup({
10657
11018
  dockPreviewCacheRef.current,
10658
11019
  cacheKey
10659
11020
  );
10660
- if (cancelled) {
10661
- break;
11021
+ if (!captureItemStateIsCurrent(itemStateKey)) {
11022
+ continue;
10662
11023
  }
10663
11024
  if (minimizedPersistedPreview) {
10664
11025
  const persistedPreview = {
@@ -10684,16 +11045,18 @@ function WorkbenchHostDockPopup({
10684
11045
  continue;
10685
11046
  }
10686
11047
  }
11048
+ const providedPreview = await Promise.resolve(
11049
+ capturePreviewRef.current?.(item) ?? null
11050
+ ).catch(() => null);
11051
+ if (!captureItemStateIsCurrent(itemStateKey)) {
11052
+ continue;
11053
+ }
10687
11054
  const preview = normalizeDockPopupPreviewContentResult(
10688
- item.isMinimized ? await capturePreviewRef.current?.(item) ?? await captureWorkbenchNodePreviewImage(item.node.id, {
10689
- bypassCache: false
10690
- }) : await Promise.resolve(
10691
- capturePreviewRef.current?.(item) ?? null
10692
- ).catch(() => null),
11055
+ providedPreview,
10693
11056
  revision
10694
11057
  );
10695
- if (cancelled) {
10696
- break;
11058
+ if (!captureItemStateIsCurrent(itemStateKey)) {
11059
+ continue;
10697
11060
  }
10698
11061
  logWorkbenchDockPopupDebug(
10699
11062
  "dock.popup.preview_capture.resolved",
@@ -10726,45 +11089,52 @@ function WorkbenchHostDockPopup({
10726
11089
  dockPreviewCacheRef.current,
10727
11090
  cacheKey
10728
11091
  ) : null;
10729
- if (cancelled) {
10730
- break;
11092
+ if (!captureItemStateIsCurrent(itemStateKey)) {
11093
+ continue;
10731
11094
  }
10732
11095
  if (fallbackPersistedPreview) {
10733
11096
  writeCachedWorkbenchNodePreviewImage(
10734
11097
  item.node.id,
10735
11098
  fallbackPersistedPreview
10736
11099
  );
10737
- }
10738
- if (fallbackPersistedPreview || item.isMinimized) {
10739
- const fallbackPreview = fallbackPersistedPreview ? { kind: "image", src: fallbackPersistedPreview } : null;
11100
+ const fallbackPreview2 = {
11101
+ kind: "image",
11102
+ src: fallbackPersistedPreview
11103
+ };
10740
11104
  writeDockPopupPreviewImage(
10741
11105
  previewMemoryKey,
10742
- fallbackPreview,
11106
+ fallbackPreview2,
10743
11107
  revision
10744
11108
  );
10745
11109
  }
10746
- if (!cancelled) {
10747
- const fallbackPreview = fallbackPersistedPreview ? { kind: "image", src: fallbackPersistedPreview } : null;
10748
- setCapturedPreviewByMemoryKey((current) => ({
10749
- ...current,
10750
- [previewMemoryKey]: { preview: fallbackPreview, revision }
10751
- }));
10752
- }
11110
+ const fallbackPreview = fallbackPersistedPreview ? { kind: "image", src: fallbackPersistedPreview } : null;
11111
+ setCapturedPreviewByMemoryKey((current) => ({
11112
+ ...current,
11113
+ [previewMemoryKey]: { preview: fallbackPreview, revision }
11114
+ }));
10753
11115
  } finally {
10754
11116
  pendingDockPopupPreviewCaptureKeys.delete(pendingCaptureKey);
11117
+ ownedCaptureKeys.delete(pendingCaptureKey);
10755
11118
  }
10756
11119
  }
10757
11120
  })().catch(() => {
10758
- for (const item of missingItems) {
11121
+ for (const captureKey of ownedCaptureKeys) {
11122
+ pendingDockPopupPreviewCaptureKeys.delete(captureKey);
11123
+ }
11124
+ ownedCaptureKeys.clear();
11125
+ const currentItems = missingItems.filter(
11126
+ (item) => captureItemStateIsCurrent(
11127
+ resolveDockPopupPreviewItemStateKey(
11128
+ item,
11129
+ resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null
11130
+ )
11131
+ )
11132
+ );
11133
+ for (const item of currentItems) {
10759
11134
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10760
- item.node,
11135
+ item,
10761
11136
  resolveDockPreviewCacheKey2?.(item.node) ?? null
10762
11137
  );
10763
- writeDockPopupPreviewImage(
10764
- previewMemoryKey,
10765
- null,
10766
- item.previewRevision
10767
- );
10768
11138
  pendingDockPopupPreviewCaptureKeys.delete(
10769
11139
  resolveDockPopupPreviewCaptureKey(
10770
11140
  previewMemoryKey,
@@ -10772,13 +11142,13 @@ function WorkbenchHostDockPopup({
10772
11142
  )
10773
11143
  );
10774
11144
  }
10775
- if (!cancelled) {
11145
+ if (currentItems.length > 0) {
10776
11146
  setCapturedPreviewByMemoryKey((current) => ({
10777
11147
  ...current,
10778
11148
  ...Object.fromEntries(
10779
- missingItems.map((item) => {
11149
+ currentItems.map((item) => {
10780
11150
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10781
- item.node,
11151
+ item,
10782
11152
  resolveDockPreviewCacheKey2?.(item.node) ?? null
10783
11153
  );
10784
11154
  return [
@@ -10791,349 +11161,56 @@ function WorkbenchHostDockPopup({
10791
11161
  }
10792
11162
  });
10793
11163
  return () => {
10794
- cancelled = true;
10795
- for (const item of missingItems) {
10796
- const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10797
- item.node,
10798
- resolveDockPreviewCacheKeyRef.current?.(item.node) ?? null
10799
- );
10800
- const pendingCaptureKey = resolveDockPopupPreviewCaptureKey(
10801
- previewMemoryKey,
10802
- item.previewRevision
10803
- );
10804
- if (!startedCaptureKeys.has(pendingCaptureKey)) {
10805
- pendingDockPopupPreviewCaptureKeys.delete(pendingCaptureKey);
11164
+ captureEffectActive = false;
11165
+ for (const captureKey of ownedCaptureKeys) {
11166
+ if (!startedCaptureKeys.has(captureKey)) {
11167
+ pendingDockPopupPreviewCaptureKeys.delete(captureKey);
11168
+ ownedCaptureKeys.delete(captureKey);
10806
11169
  }
10807
11170
  }
10808
11171
  };
10809
11172
  }, [hasCapturePreview, isContextMenu, previewCaptureKey]);
10810
- const content = /* @__PURE__ */ jsx11(
10811
- "div",
10812
- {
10813
- ref: popupRootRef,
10814
- className: "desktop-dock-popup-root",
10815
- "data-dock-placement": placement,
10816
- "data-desktop-dock-popup-root": "true",
10817
- "data-popup-variant": resolvedVariant,
10818
- style: popupStyle,
10819
- children: /* @__PURE__ */ jsx11(
10820
- "div",
10821
- {
10822
- "aria-label": label,
10823
- className: cn(
10824
- "desktop-dock-popup relative origin-bottom rounded-lg border border-[var(--border-1)] bg-background-fronted text-[var(--text-primary)] shadow-panel motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:slide-in-from-bottom-2 motion-safe:duration-[175ms] motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none",
10825
- isContextMenu ? "p-1" : "p-3",
10826
- isLeftMinimizedStack ? "w-full min-w-0 max-w-none" : "w-[min(var(--desktop-dock-popup-width,366px),calc(100vw-32px))]"
10827
- ),
10828
- "data-desktop-dock-popup-panel": "true",
10829
- "data-popup-variant": resolvedVariant,
10830
- onPointerDown: (event) => event.stopPropagation(),
10831
- onPointerMove: isMinimizedStack ? (event) => setPointer({ x: event.clientX, y: event.clientY }) : void 0,
10832
- onPointerLeave: isMinimizedStack ? () => setPointer(null) : void 0,
10833
- role: "dialog",
10834
- style: panelStyle,
10835
- children: isContextMenu ? /* @__PURE__ */ jsx11(
10836
- WorkbenchHostDockContextMenu,
10837
- {
10838
- canCreateNew: resolvedShowCreateNewInContextMenu !== false,
10839
- canEnterFullscreen: canEnterFullscreen === true,
10840
- canShowAllWindows: canShowAllWindows === true,
10841
- dockRetention,
10842
- fullscreenLabel,
10843
- hideLabel,
10844
- items,
10845
- newWindowLabel,
10846
- onCreateNew,
10847
- onEnterFullscreen,
10848
- onHide,
10849
- onQuit,
10850
- onRunDockRetentionAction,
10851
- onSelectNode,
10852
- onShowAllWindows,
10853
- quitLabel,
10854
- showAllWindowsLabel,
10855
- showOpen: showOpen === true
10856
- }
10857
- ) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
10858
- /* @__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
- isMinimizedStack ? /* @__PURE__ */ jsx11(
10860
- "div",
10861
- {
10862
- ref: minimizedStackViewportRef,
10863
- className: "desktop-dock-popup__minimized-stack-viewport",
10864
- style: {
10865
- height: minimizedStackViewportHeightPx,
10866
- ...isLeftMinimizedStack ? { paddingLeft: minimizedStackLeftGutterPx } : {}
10867
- },
10868
- children: /* @__PURE__ */ jsx11(
10869
- "div",
10870
- {
10871
- className: "desktop-dock-popup__minimized-stack-track",
10872
- style: {
10873
- minHeight: minimizedStackTrackHeightPx,
10874
- transform: `translate(${minimizedStackTrackTranslateXPx}px, ${-minimizedStackScrollOffset}px)`
10875
- },
10876
- children: items.map((item, index) => {
10877
- const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10878
- item.node,
10879
- resolveDockPreviewCacheKey2?.(item.node) ?? null
10880
- );
10881
- const capturedPreview = capturedPreviewByMemoryKey[previewMemoryKey] !== void 0 ? capturedPreviewByMemoryKey[previewMemoryKey] : readDockPopupPreviewImage(previewMemoryKey);
10882
- const previewState = resolveDockPopupItemPreviewState(
10883
- item,
10884
- capturedPreview,
10885
- Boolean(capturePreview)
10886
- );
10887
- return /* @__PURE__ */ jsx11(
10888
- WorkbenchHostDockPopupCard,
10889
- {
10890
- ref: registerCard(item.node.id),
10891
- closeWindowLabel,
10892
- item,
10893
- labelMode: resolvedLabelMode,
10894
- onCloseNode,
10895
- onSelectNode,
10896
- previewState,
10897
- style: {
10898
- ...resolvePopupFanCardStyle(
10899
- index,
10900
- items.length,
10901
- placement
10902
- ),
10903
- ...resolvePopupCardMagnificationStyle(
10904
- pointer,
10905
- cardElementsRef.current.get(item.node.id) ?? null
10906
- )
10907
- },
10908
- variant: resolvedVariant
10909
- },
10910
- item.node.id
10911
- );
10912
- })
10913
- }
10914
- )
10915
- }
10916
- ) : /* @__PURE__ */ jsxs8("div", { className: "grid max-h-[min(52vh,420px)] grid-cols-[repeat(var(--desktop-dock-popup-columns,2),165px)] gap-2 overflow-auto overscroll-contain", children: [
10917
- items.map((item) => {
10918
- const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
10919
- item.node,
10920
- resolveDockPreviewCacheKey2?.(item.node) ?? null
10921
- );
10922
- const capturedPreview = capturedPreviewByMemoryKey[previewMemoryKey] !== void 0 ? capturedPreviewByMemoryKey[previewMemoryKey] : readDockPopupPreviewImage(previewMemoryKey);
10923
- const previewState = resolveDockPopupItemPreviewState(
10924
- item,
10925
- capturedPreview,
10926
- Boolean(capturePreview)
10927
- );
10928
- return /* @__PURE__ */ jsx11(
10929
- WorkbenchHostDockPopupCard,
10930
- {
10931
- ref: registerCard(item.node.id),
10932
- closeWindowLabel,
10933
- item,
10934
- labelMode: resolvedLabelMode,
10935
- onCloseNode,
10936
- onSelectNode,
10937
- previewState,
10938
- variant: resolvedVariant
10939
- },
10940
- item.node.id
10941
- );
10942
- }),
10943
- showCreateNew !== false ? /* @__PURE__ */ jsxs8(
10944
- "button",
10945
- {
10946
- className: "flex h-[103px] w-[165px] min-w-0 flex-col items-center justify-center gap-2 rounded-[8px] border border-dashed border-[var(--border-1)] bg-transparency-block text-center text-[var(--text-secondary)] transition-colors hover:bg-transparency-hover hover:text-[var(--text-primary)]",
10947
- type: "button",
10948
- onClick: onCreateNew,
10949
- children: [
10950
- /* @__PURE__ */ jsx11(
10951
- FileCreateIcon,
10952
- {
10953
- "aria-hidden": "true",
10954
- className: "text-[var(--text-primary)]",
10955
- size: 28
10956
- }
10957
- ),
10958
- /* @__PURE__ */ jsx11("span", { className: "text-xs font-semibold text-[var(--text-primary)]", children: newWindowLabel })
10959
- ]
10960
- }
10961
- ) : null
10962
- ] })
10963
- ] })
10964
- }
10965
- )
11173
+ return {
11174
+ previewStateFor(item) {
11175
+ const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
11176
+ item,
11177
+ resolveDockPreviewCacheKey2?.(item.node) ?? null
11178
+ );
11179
+ const capturedPreview = capturedPreviewByMemoryKey[previewMemoryKey] ?? readDockPopupPreviewImage(previewMemoryKey);
11180
+ return resolveDockPopupItemPreviewState(
11181
+ item,
11182
+ capturedPreview,
11183
+ hasCapturePreview
11184
+ );
10966
11185
  }
10967
- );
10968
- if (typeof document === "undefined" || !document.body) {
10969
- return content;
11186
+ };
11187
+ }
11188
+ function logWorkbenchDockPopupDebug(event, debugDiagnostics, details) {
11189
+ if (!debugDiagnostics?.log) {
11190
+ return;
10970
11191
  }
10971
- return createPortal3(content, document.body);
11192
+ void Promise.resolve(
11193
+ debugDiagnostics.log({
11194
+ details,
11195
+ event,
11196
+ level: "info",
11197
+ source: "workbench-dock"
11198
+ })
11199
+ ).catch(() => void 0);
10972
11200
  }
10973
- function WorkbenchHostDockContextMenu({
10974
- canCreateNew,
10975
- canEnterFullscreen,
10976
- canShowAllWindows,
10977
- dockRetention,
10978
- fullscreenLabel,
10979
- hideLabel,
10980
- items,
10981
- newWindowLabel,
10982
- onCreateNew,
10983
- onEnterFullscreen,
10984
- onHide,
10985
- onQuit,
10986
- onRunDockRetentionAction,
10987
- onSelectNode,
10988
- onShowAllWindows,
10989
- quitLabel,
10990
- showAllWindowsLabel,
10991
- showOpen
10992
- }) {
10993
- const hasOpenWindows = items.length > 0;
10994
- const hasNewWindowCommand = hasOpenWindows && canCreateNew;
10995
- const hasOpenCommand = !hasOpenWindows;
10996
- const hasDockActionGroup = Boolean(dockRetention) || hasNewWindowCommand || hasOpenCommand;
10997
- const hasWindowActionGroup = hasOpenWindows;
10998
- return /* @__PURE__ */ jsxs8(
10999
- "div",
11000
- {
11001
- className: "flex min-w-0 flex-col gap-1",
11002
- "data-desktop-dock-context-menu": "true",
11003
- role: "menu",
11004
- 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(
11006
- WorkbenchHostDockContextMenuItem,
11007
- {
11008
- checked: !item.isMinimized,
11009
- label: item.title?.trim() || item.node.title,
11010
- onSelect: () => onSelectNode(item.node.id)
11011
- },
11012
- item.node.id
11013
- )) }) }) : null,
11014
- hasOpenWindows && (hasDockActionGroup || hasWindowActionGroup) ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
11015
- dockRetention ? /* @__PURE__ */ jsx11(
11016
- WorkbenchHostDockContextMenuItem,
11017
- {
11018
- checked: dockRetention.checked,
11019
- checkedIcon: /* @__PURE__ */ jsx11(
11020
- PinFilledIcon,
11021
- {
11022
- "aria-hidden": "true",
11023
- className: "size-4 text-[var(--tutti-purple)]"
11024
- }
11025
- ),
11026
- disabled: dockRetention.disabled,
11027
- icon: /* @__PURE__ */ jsx11(PinIcon, { "aria-hidden": "true", className: "size-4" }),
11028
- label: dockRetention.pendingLabel ?? dockRetention.label,
11029
- onSelect: onRunDockRetentionAction
11030
- }
11031
- ) : null,
11032
- hasNewWindowCommand ? /* @__PURE__ */ jsx11(
11033
- WorkbenchHostDockContextMenuItem,
11034
- {
11035
- icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
11036
- label: newWindowLabel,
11037
- onSelect: onCreateNew
11038
- }
11039
- ) : null,
11040
- hasOpenCommand ? /* @__PURE__ */ jsx11(
11041
- WorkbenchHostDockContextMenuItem,
11042
- {
11043
- disabled: !showOpen,
11044
- icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
11045
- label: newWindowLabel,
11046
- onSelect: onCreateNew
11047
- }
11048
- ) : null,
11049
- hasOpenWindows ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
11050
- hasDockActionGroup ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
11051
- canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx11(
11052
- WorkbenchHostDockContextMenuItem,
11053
- {
11054
- icon: /* @__PURE__ */ jsx11(OverviewLayoutIcon, { "aria-hidden": "true", className: "size-4" }),
11055
- label: showAllWindowsLabel,
11056
- onSelect: onShowAllWindows
11057
- }
11058
- ) : null,
11059
- /* @__PURE__ */ jsx11(
11060
- WorkbenchHostDockContextMenuItem,
11061
- {
11062
- disabled: !canEnterFullscreen || !onEnterFullscreen,
11063
- icon: /* @__PURE__ */ jsx11(MaximizeIcon, { "aria-hidden": "true", className: "size-4" }),
11064
- label: fullscreenLabel,
11065
- onSelect: onEnterFullscreen
11066
- }
11067
- ),
11068
- /* @__PURE__ */ jsx11(
11069
- WorkbenchHostDockContextMenuItem,
11070
- {
11071
- disabled: !onHide,
11072
- icon: /* @__PURE__ */ jsx11(MinimizeIcon, { "aria-hidden": "true", className: "size-4" }),
11073
- label: hideLabel,
11074
- onSelect: onHide
11075
- }
11076
- ),
11077
- /* @__PURE__ */ jsx11(
11078
- WorkbenchHostDockContextMenuItem,
11079
- {
11080
- disabled: !onQuit,
11081
- icon: /* @__PURE__ */ jsx11(CloseIcon, { "aria-hidden": "true", className: "size-4" }),
11082
- label: quitLabel,
11083
- onSelect: onQuit
11084
- }
11085
- )
11086
- ] }) : null
11087
- ]
11088
- }
11089
- );
11090
- }
11091
- function WorkbenchHostDockContextMenuItem({
11092
- checked,
11093
- checkedIcon,
11094
- disabled,
11095
- icon,
11096
- label,
11097
- onSelect
11098
- }) {
11099
- return /* @__PURE__ */ jsxs8(
11100
- "button",
11101
- {
11102
- className: cn(
11103
- "flex h-8 w-full min-w-0 items-center gap-2 rounded-md px-2 text-left text-sm text-[var(--text-primary)] transition-colors",
11104
- disabled ? "cursor-default opacity-45" : "hover:bg-transparency-hover focus-visible:bg-transparency-hover focus-visible:outline-none"
11105
- ),
11106
- disabled,
11107
- role: "menuitem",
11108
- type: "button",
11109
- onClick: () => {
11110
- if (disabled || !onSelect) {
11111
- return;
11112
- }
11113
- onSelect();
11114
- },
11115
- children: [
11116
- /* @__PURE__ */ jsx11("span", { className: "flex size-4 shrink-0 items-center justify-center text-[var(--text-secondary)]", children: checked && checkedIcon ? checkedIcon : checked ? /* @__PURE__ */ jsx11(
11117
- CheckIcon,
11118
- {
11119
- "aria-hidden": "true",
11120
- className: "size-4 text-[var(--tutti-purple)]"
11121
- }
11122
- ) : icon ?? null }),
11123
- /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: label })
11124
- ]
11125
- }
11126
- );
11201
+ function readDockPopupPreviewImage(memoryKey) {
11202
+ return dockPopupPreviewByMemoryKey.get(memoryKey);
11127
11203
  }
11128
- function WorkbenchHostDockContextMenuSeparator() {
11129
- return /* @__PURE__ */ jsx11(
11130
- "div",
11131
- {
11132
- "aria-hidden": "true",
11133
- className: "mx-2 my-1 h-px bg-[var(--border-1)]",
11134
- role: "separator"
11204
+ function writeDockPopupPreviewImage(memoryKey, preview, revision) {
11205
+ dockPopupPreviewByMemoryKey.delete(memoryKey);
11206
+ dockPopupPreviewByMemoryKey.set(memoryKey, { preview, revision });
11207
+ while (dockPopupPreviewByMemoryKey.size > dockPopupPreviewCacheMaxEntries) {
11208
+ const oldestMemoryKey = dockPopupPreviewByMemoryKey.keys().next().value;
11209
+ if (typeof oldestMemoryKey !== "string") {
11210
+ break;
11135
11211
  }
11136
- );
11212
+ dockPopupPreviewByMemoryKey.delete(oldestMemoryKey);
11213
+ }
11137
11214
  }
11138
11215
  function readPersistedDockPreview(dockPreviewCache, cacheKey) {
11139
11216
  if (!cacheKey) {
@@ -11144,9 +11221,9 @@ function readPersistedDockPreview(dockPreviewCache, cacheKey) {
11144
11221
  function resolveDockPopupPreviewCacheKey(cacheKey, revision) {
11145
11222
  return cacheKey ? { ...cacheKey, revision } : null;
11146
11223
  }
11147
- function resolveDockPopupPreviewMemoryKey(node, cacheKey) {
11224
+ function resolveDockPopupPreviewMemoryKey(item, cacheKey) {
11148
11225
  if (!cacheKey) {
11149
- return `node:${node.id}`;
11226
+ return `node:${item.node.id}`;
11150
11227
  }
11151
11228
  return `cache:${JSON.stringify({
11152
11229
  instanceId: cacheKey.instanceId,
@@ -11159,6 +11236,14 @@ function resolveDockPopupPreviewMemoryKey(node, cacheKey) {
11159
11236
  function resolveDockPopupPreviewCaptureKey(memoryKey, revision) {
11160
11237
  return `${memoryKey}\0${revision ?? ""}`;
11161
11238
  }
11239
+ function resolveDockPopupPreviewItemStateKey(item, cacheKey) {
11240
+ return [
11241
+ resolveDockPopupPreviewMemoryKey(item, cacheKey),
11242
+ item.isMinimized ? "minimized" : "visible",
11243
+ previewCacheToken(item.preview),
11244
+ item.previewRevision ?? ""
11245
+ ].join(":");
11246
+ }
11162
11247
  function normalizeDockPopupPreviewContentResult(preview, revision) {
11163
11248
  if (!preview) {
11164
11249
  return null;
@@ -11195,18 +11280,436 @@ function previewCacheToken(preview) {
11195
11280
  return `image:${preview.revision ?? ""}:${preview.src}`;
11196
11281
  }
11197
11282
  }
11198
- function logWorkbenchDockPopupDebug(event, debugDiagnostics, details) {
11199
- if (!debugDiagnostics?.log) {
11200
- return;
11283
+
11284
+ // src/host/WorkbenchHostDockPopup.tsx
11285
+ import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
11286
+ var dockPopupCardWidthPx = 165;
11287
+ var dockPopupCardHeightPx = 103;
11288
+ var dockPopupPreviewInsetPx = 4;
11289
+ var workbenchHostDockPopupPreviewViewport = Object.freeze({
11290
+ height: dockPopupCardHeightPx - dockPopupPreviewInsetPx * 2,
11291
+ width: dockPopupCardWidthPx - dockPopupPreviewInsetPx * 2
11292
+ });
11293
+ var dockPopupGridGapPx = 8;
11294
+ var dockPopupPanelPaddingInlinePx = 12;
11295
+ var dockPopupPanelBorderInlinePx = 2;
11296
+ var dockPopupPlacementGapPx = 14;
11297
+ var dockPopupMinimizedStackPopupZIndex = 100300;
11298
+ function WorkbenchHostDockPopup({
11299
+ anchorRect,
11300
+ canEnterFullscreen,
11301
+ canShowAllWindows,
11302
+ capturePreview,
11303
+ debugDiagnostics,
11304
+ dockRetention,
11305
+ dockPreviewCache,
11306
+ fullscreenLabel,
11307
+ hideLabel,
11308
+ items,
11309
+ label,
11310
+ labelMode,
11311
+ newWindowLabel,
11312
+ closeWindowLabel,
11313
+ onClose,
11314
+ onCloseNode,
11315
+ onCreateNew,
11316
+ onEnterFullscreen,
11317
+ onHide,
11318
+ onRunDockRetentionAction,
11319
+ onSelectNode,
11320
+ onShowAllWindows,
11321
+ onQuit,
11322
+ placement = "bottom",
11323
+ quitLabel,
11324
+ resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2,
11325
+ showAllWindowsLabel,
11326
+ showCreateNew,
11327
+ showCreateNewInContextMenu,
11328
+ showOpen,
11329
+ variant
11330
+ }) {
11331
+ const resolvedShowCreateNewInContextMenu = showCreateNewInContextMenu ?? showCreateNew;
11332
+ const resolvedLabelMode = labelMode ?? "hover-overlay";
11333
+ const resolvedVariant = variant ?? "default";
11334
+ const isMinimizedStack = resolvedVariant === "minimized-stack";
11335
+ const isContextMenu = resolvedVariant === "context-menu";
11336
+ const createCardCount = showCreateNew === false ? 0 : 1;
11337
+ const cardElementsRef = useRef10(/* @__PURE__ */ new Map());
11338
+ const cardRefCallbacksRef = useRef10(
11339
+ /* @__PURE__ */ new Map()
11340
+ );
11341
+ const popupRootRef = useRef10(null);
11342
+ const minimizedStackViewportRef = useRef10(null);
11343
+ const [pointer, setPointer] = useState9(null);
11344
+ const [minimizedStackScrollOffset, setMinimizedStackScrollOffset] = useState9(0);
11345
+ const [verticalClampOffsetPx, setVerticalClampOffsetPx] = useState9(0);
11346
+ const { previewStateFor } = useWorkbenchHostDockPopupPreviewCapture({
11347
+ capturePreview,
11348
+ debugDiagnostics,
11349
+ dockPreviewCache,
11350
+ isContextMenu,
11351
+ items,
11352
+ resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
11353
+ });
11354
+ const columnCount = isContextMenu ? 1 : Math.min(Math.max(items.length + createCardCount, 1), 3);
11355
+ const popupWidthPx = isContextMenu ? 268 : columnCount * dockPopupCardWidthPx + Math.max(0, columnCount - 1) * dockPopupGridGapPx + dockPopupPanelPaddingInlinePx * 2 + dockPopupPanelBorderInlinePx;
11356
+ const popupCenterY = anchorRect.top + anchorRect.height / 2;
11357
+ const isLeftMinimizedStack = placement === "left" && isMinimizedStack;
11358
+ const minimizedStackTrackHeightPx = resolveMinimizedStackTrackHeightPx(
11359
+ items.length
11360
+ );
11361
+ const minimizedStackViewportHeightPx = isMinimizedStack ? resolveMinimizedStackViewportHeightPx({
11362
+ anchorCenterY: popupCenterY,
11363
+ placement,
11364
+ trackHeightPx: minimizedStackTrackHeightPx
11365
+ }) : minimizedStackTrackHeightPx;
11366
+ const minimizedStackTrackTranslateXPx = isMinimizedStack ? resolveMinimizedStackTrackTranslateXPx({
11367
+ itemCount: items.length,
11368
+ placement,
11369
+ scrollOffset: minimizedStackScrollOffset,
11370
+ trackHeightPx: minimizedStackTrackHeightPx,
11371
+ viewportHeightPx: minimizedStackViewportHeightPx
11372
+ }) : 0;
11373
+ const minimizedStackLeftGutterPx = isLeftMinimizedStack ? resolveMinimizedStackLeftGutterPx({
11374
+ itemCount: items.length,
11375
+ placement,
11376
+ scrollOffset: minimizedStackScrollOffset,
11377
+ trackHeightPx: minimizedStackTrackHeightPx,
11378
+ viewportHeightPx: minimizedStackViewportHeightPx,
11379
+ trackTranslateXPx: minimizedStackTrackTranslateXPx
11380
+ }) : 0;
11381
+ const minimizedStackPanelWidthPx = isLeftMinimizedStack ? resolveMinimizedStackPanelWidthPx(items.length, placement, {
11382
+ leftGutterPx: minimizedStackLeftGutterPx
11383
+ }) : null;
11384
+ const popupStyle = {
11385
+ "--desktop-dock-popup-columns": String(columnCount),
11386
+ "--desktop-dock-popup-width": minimizedStackPanelWidthPx != null ? `${minimizedStackPanelWidthPx}px` : `${popupWidthPx}px`,
11387
+ ...minimizedStackPanelWidthPx != null ? {
11388
+ "--desktop-dock-minimized-stack-width": `${minimizedStackPanelWidthPx}px`,
11389
+ minWidth: minimizedStackPanelWidthPx,
11390
+ width: minimizedStackPanelWidthPx
11391
+ } : {},
11392
+ left: isLeftMinimizedStack ? resolveMinimizedStackPopupLeftPx({
11393
+ anchorLeft: anchorRect.left,
11394
+ anchorWidth: anchorRect.width,
11395
+ dockRightPx: anchorRect.dockRight,
11396
+ leftGutterPx: minimizedStackLeftGutterPx
11397
+ }) : placement === "left" ? anchorRect.left + anchorRect.width + dockPopupPlacementGapPx : anchorRect.left + anchorRect.width / 2,
11398
+ top: isLeftMinimizedStack ? resolveMinimizedStackPopupTopPx({ anchorTop: anchorRect.top }) : placement === "left" ? popupCenterY : anchorRect.top - dockPopupPlacementGapPx,
11399
+ ...isLeftMinimizedStack ? { zIndex: dockPopupMinimizedStackPopupZIndex } : {},
11400
+ ...isMinimizedStack ? {} : { "--desktop-dock-popup-clamp-offset": `${verticalClampOffsetPx}px` }
11401
+ };
11402
+ const minimizedStackMaxScrollOffset = Math.max(
11403
+ 0,
11404
+ minimizedStackTrackHeightPx - minimizedStackViewportHeightPx
11405
+ );
11406
+ const initialMinimizedStackScrollOffset = resolveInitialMinimizedStackScrollOffset({
11407
+ maxScrollOffset: minimizedStackMaxScrollOffset
11408
+ });
11409
+ const panelStyle = {
11410
+ "--desktop-dock-popup-columns": String(columnCount),
11411
+ "--desktop-dock-popup-item-count": String(Math.max(1, items.length)),
11412
+ ...isMinimizedStack ? {
11413
+ height: minimizedStackViewportHeightPx,
11414
+ minHeight: minimizedStackViewportHeightPx,
11415
+ ...isLeftMinimizedStack && minimizedStackPanelWidthPx != null ? {
11416
+ width: minimizedStackPanelWidthPx,
11417
+ minWidth: minimizedStackPanelWidthPx,
11418
+ "--desktop-dock-minimized-stack-left-gutter": `${minimizedStackLeftGutterPx}px`
11419
+ } : {}
11420
+ } : {}
11421
+ };
11422
+ const popupDiagnosticKey = items.map((item) => item.node.id).join("|");
11423
+ useEffect11(() => {
11424
+ logWorkbenchDockPopupDebug("dock.popup.rendered", debugDiagnostics, {
11425
+ hasCapturePreview: Boolean(capturePreview),
11426
+ itemCount: popupDiagnosticKey ? popupDiagnosticKey.split("|").length : 0,
11427
+ nodeIds: popupDiagnosticKey ? popupDiagnosticKey.split("|") : [],
11428
+ placement,
11429
+ variant: resolvedVariant
11430
+ });
11431
+ }, [
11432
+ capturePreview,
11433
+ debugDiagnostics,
11434
+ placement,
11435
+ popupDiagnosticKey,
11436
+ resolvedVariant
11437
+ ]);
11438
+ useLayoutEffect7(() => {
11439
+ const rootElement = popupRootRef.current;
11440
+ const panelElement = rootElement?.querySelector(
11441
+ "[data-desktop-dock-popup-panel]"
11442
+ ) ?? null;
11443
+ logWorkbenchDockPopupDebug("dock.popup.layout", debugDiagnostics, {
11444
+ panelRect: panelElement ? rectToDiagnostic(panelElement) : null,
11445
+ rootRect: rootElement ? rectToDiagnostic(rootElement) : null,
11446
+ rootStyle: rootElement ? styleToDiagnostic(rootElement) : null,
11447
+ viewportHeight: window.innerHeight,
11448
+ viewportWidth: window.innerWidth
11449
+ });
11450
+ }, [debugDiagnostics, popupDiagnosticKey]);
11451
+ useLayoutEffect7(() => {
11452
+ if (isMinimizedStack || typeof window === "undefined") {
11453
+ return;
11454
+ }
11455
+ const rootElement = popupRootRef.current;
11456
+ const panelElement = rootElement?.querySelector(
11457
+ "[data-desktop-dock-popup-panel]"
11458
+ );
11459
+ if (!panelElement) {
11460
+ return;
11461
+ }
11462
+ const measureAndClamp = () => {
11463
+ const panelHeightPx = panelElement.offsetHeight;
11464
+ const naturalTopPx = placement === "left" ? popupCenterY - panelHeightPx / 2 : anchorRect.top - dockPopupPlacementGapPx - panelHeightPx;
11465
+ const naturalBottomPx = placement === "left" ? popupCenterY + panelHeightPx / 2 : anchorRect.top - dockPopupPlacementGapPx;
11466
+ const offsetPx = resolveDockPopupVerticalClampOffsetPx({
11467
+ naturalBottomPx,
11468
+ naturalTopPx,
11469
+ viewportHeightPx: window.innerHeight
11470
+ });
11471
+ setVerticalClampOffsetPx(
11472
+ (current) => current === offsetPx ? current : offsetPx
11473
+ );
11474
+ };
11475
+ measureAndClamp();
11476
+ const resizeObserver = new ResizeObserver(measureAndClamp);
11477
+ resizeObserver.observe(panelElement);
11478
+ window.addEventListener("resize", measureAndClamp);
11479
+ return () => {
11480
+ resizeObserver.disconnect();
11481
+ window.removeEventListener("resize", measureAndClamp);
11482
+ };
11483
+ }, [
11484
+ anchorRect.top,
11485
+ isMinimizedStack,
11486
+ placement,
11487
+ popupCenterY,
11488
+ popupDiagnosticKey
11489
+ ]);
11490
+ const registerCard = useCallback12((nodeId) => {
11491
+ const existing = cardRefCallbacksRef.current.get(nodeId);
11492
+ if (existing) {
11493
+ return existing;
11494
+ }
11495
+ const callback = (element) => {
11496
+ if (element) {
11497
+ cardElementsRef.current.set(nodeId, element);
11498
+ } else {
11499
+ cardElementsRef.current.delete(nodeId);
11500
+ }
11501
+ };
11502
+ cardRefCallbacksRef.current.set(nodeId, callback);
11503
+ return callback;
11504
+ }, []);
11505
+ useEffect11(() => {
11506
+ if (!isLeftMinimizedStack) {
11507
+ return;
11508
+ }
11509
+ document.body.setAttribute(
11510
+ "data-desktop-dock-minimized-stack-open",
11511
+ "true"
11512
+ );
11513
+ return () => {
11514
+ document.body.removeAttribute("data-desktop-dock-minimized-stack-open");
11515
+ };
11516
+ }, [isLeftMinimizedStack]);
11517
+ useEffect11(() => {
11518
+ const handlePointerDown = (event) => {
11519
+ if (!(event.target instanceof Element)) {
11520
+ onClose();
11521
+ return;
11522
+ }
11523
+ if (event.target.closest("[data-desktop-dock-slot]") || event.target.closest("[data-desktop-dock-popup-card]") || event.target.closest(
11524
+ '.desktop-dock-popup-root:not([data-popup-variant="minimized-stack"])'
11525
+ )) {
11526
+ return;
11527
+ }
11528
+ onClose();
11529
+ };
11530
+ const handleKeyDown = (event) => {
11531
+ if (event.key === "Escape") {
11532
+ onClose();
11533
+ }
11534
+ };
11535
+ window.addEventListener("pointerdown", handlePointerDown, true);
11536
+ window.addEventListener("keydown", handleKeyDown);
11537
+ return () => {
11538
+ window.removeEventListener("pointerdown", handlePointerDown, true);
11539
+ window.removeEventListener("keydown", handleKeyDown);
11540
+ };
11541
+ }, [onClose]);
11542
+ useEffect11(() => {
11543
+ if (!isMinimizedStack) {
11544
+ return;
11545
+ }
11546
+ setMinimizedStackScrollOffset(initialMinimizedStackScrollOffset);
11547
+ }, [initialMinimizedStackScrollOffset, isMinimizedStack, items.length]);
11548
+ useEffect11(() => {
11549
+ if (!isMinimizedStack) {
11550
+ return;
11551
+ }
11552
+ const viewport = minimizedStackViewportRef.current;
11553
+ if (!viewport) {
11554
+ return;
11555
+ }
11556
+ const handleWheel = (event) => {
11557
+ event.preventDefault();
11558
+ event.stopPropagation();
11559
+ setMinimizedStackScrollOffset(
11560
+ (current) => Math.min(
11561
+ minimizedStackMaxScrollOffset,
11562
+ Math.max(0, current + event.deltaY)
11563
+ )
11564
+ );
11565
+ };
11566
+ viewport.addEventListener("wheel", handleWheel, { passive: false });
11567
+ return () => viewport.removeEventListener("wheel", handleWheel);
11568
+ }, [isMinimizedStack, minimizedStackMaxScrollOffset]);
11569
+ const content = /* @__PURE__ */ jsx12(
11570
+ "div",
11571
+ {
11572
+ ref: popupRootRef,
11573
+ className: "desktop-dock-popup-root",
11574
+ "data-dock-placement": placement,
11575
+ "data-desktop-dock-popup-root": "true",
11576
+ "data-popup-variant": resolvedVariant,
11577
+ style: popupStyle,
11578
+ children: /* @__PURE__ */ jsx12(
11579
+ "div",
11580
+ {
11581
+ "aria-label": label,
11582
+ className: cn2(
11583
+ "desktop-dock-popup relative origin-bottom rounded-lg border border-[var(--border-1)] bg-background-fronted text-[var(--text-primary)] shadow-panel motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-95 motion-safe:slide-in-from-bottom-2 motion-safe:duration-[175ms] motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none",
11584
+ isContextMenu ? "p-1" : "p-3",
11585
+ isLeftMinimizedStack ? "w-full min-w-0 max-w-none" : "w-[min(var(--desktop-dock-popup-width,366px),calc(100vw-32px))]"
11586
+ ),
11587
+ "data-desktop-dock-popup-panel": "true",
11588
+ "data-popup-variant": resolvedVariant,
11589
+ onPointerDown: (event) => event.stopPropagation(),
11590
+ onPointerMove: isMinimizedStack ? (event) => setPointer({ x: event.clientX, y: event.clientY }) : void 0,
11591
+ onPointerLeave: isMinimizedStack ? () => setPointer(null) : void 0,
11592
+ role: "dialog",
11593
+ style: panelStyle,
11594
+ children: isContextMenu ? /* @__PURE__ */ jsx12(
11595
+ WorkbenchHostDockContextMenu,
11596
+ {
11597
+ canCreateNew: resolvedShowCreateNewInContextMenu !== false,
11598
+ canEnterFullscreen: canEnterFullscreen === true,
11599
+ canShowAllWindows: canShowAllWindows === true,
11600
+ dockRetention,
11601
+ fullscreenLabel,
11602
+ hideLabel,
11603
+ items,
11604
+ newWindowLabel,
11605
+ onCreateNew,
11606
+ onEnterFullscreen,
11607
+ onHide,
11608
+ onQuit,
11609
+ onRunDockRetentionAction,
11610
+ onSelectNode,
11611
+ onShowAllWindows,
11612
+ quitLabel,
11613
+ showAllWindowsLabel,
11614
+ showOpen: showOpen === true
11615
+ }
11616
+ ) : /* @__PURE__ */ jsxs9(Fragment5, { children: [
11617
+ /* @__PURE__ */ jsx12("div", { className: "mb-2.5 flex items-center justify-between", children: /* @__PURE__ */ jsx12("span", { className: "min-w-0 truncate text-sm font-semibold", children: label }) }),
11618
+ isMinimizedStack ? /* @__PURE__ */ jsx12(
11619
+ "div",
11620
+ {
11621
+ ref: minimizedStackViewportRef,
11622
+ className: "desktop-dock-popup__minimized-stack-viewport",
11623
+ style: {
11624
+ height: minimizedStackViewportHeightPx,
11625
+ ...isLeftMinimizedStack ? { paddingLeft: minimizedStackLeftGutterPx } : {}
11626
+ },
11627
+ children: /* @__PURE__ */ jsx12(
11628
+ "div",
11629
+ {
11630
+ className: "desktop-dock-popup__minimized-stack-track",
11631
+ style: {
11632
+ minHeight: minimizedStackTrackHeightPx,
11633
+ transform: `translate(${minimizedStackTrackTranslateXPx}px, ${-minimizedStackScrollOffset}px)`
11634
+ },
11635
+ children: items.map((item, index) => {
11636
+ const previewState = previewStateFor(item);
11637
+ return /* @__PURE__ */ jsx12(
11638
+ WorkbenchHostDockPopupCard,
11639
+ {
11640
+ ref: registerCard(item.node.id),
11641
+ closeWindowLabel,
11642
+ item,
11643
+ labelMode: resolvedLabelMode,
11644
+ onCloseNode,
11645
+ onSelectNode,
11646
+ previewState,
11647
+ style: {
11648
+ ...resolvePopupFanCardStyle(
11649
+ index,
11650
+ items.length,
11651
+ placement
11652
+ ),
11653
+ ...resolvePopupCardMagnificationStyle(
11654
+ pointer,
11655
+ cardElementsRef.current.get(item.node.id) ?? null
11656
+ )
11657
+ },
11658
+ variant: resolvedVariant
11659
+ },
11660
+ item.node.id
11661
+ );
11662
+ })
11663
+ }
11664
+ )
11665
+ }
11666
+ ) : /* @__PURE__ */ jsxs9("div", { className: "grid max-h-[min(52vh,420px)] grid-cols-[repeat(var(--desktop-dock-popup-columns,2),165px)] gap-2 overflow-auto overscroll-contain", children: [
11667
+ items.map((item) => {
11668
+ const previewState = previewStateFor(item);
11669
+ return /* @__PURE__ */ jsx12(
11670
+ WorkbenchHostDockPopupCard,
11671
+ {
11672
+ ref: registerCard(item.node.id),
11673
+ closeWindowLabel,
11674
+ item,
11675
+ labelMode: resolvedLabelMode,
11676
+ onCloseNode,
11677
+ onSelectNode,
11678
+ previewState,
11679
+ variant: resolvedVariant
11680
+ },
11681
+ item.node.id
11682
+ );
11683
+ }),
11684
+ showCreateNew !== false ? /* @__PURE__ */ jsxs9(
11685
+ "button",
11686
+ {
11687
+ className: "flex h-[103px] w-[165px] min-w-0 flex-col items-center justify-center gap-2 rounded-[8px] border border-dashed border-[var(--border-1)] bg-transparency-block text-center text-[var(--text-secondary)] transition-colors hover:bg-transparency-hover hover:text-[var(--text-primary)]",
11688
+ type: "button",
11689
+ onClick: onCreateNew,
11690
+ children: [
11691
+ /* @__PURE__ */ jsx12(
11692
+ FileCreateIcon2,
11693
+ {
11694
+ "aria-hidden": "true",
11695
+ className: "text-[var(--text-primary)]",
11696
+ size: 28
11697
+ }
11698
+ ),
11699
+ /* @__PURE__ */ jsx12("span", { className: "text-xs font-semibold text-[var(--text-primary)]", children: newWindowLabel })
11700
+ ]
11701
+ }
11702
+ ) : null
11703
+ ] })
11704
+ ] })
11705
+ }
11706
+ )
11707
+ }
11708
+ );
11709
+ if (typeof document === "undefined" || !document.body) {
11710
+ return content;
11201
11711
  }
11202
- void Promise.resolve(
11203
- debugDiagnostics.log({
11204
- details,
11205
- event,
11206
- level: "info",
11207
- source: "workbench-dock"
11208
- })
11209
- ).catch(() => void 0);
11712
+ return createPortal3(content, document.body);
11210
11713
  }
11211
11714
  function rectToDiagnostic(element) {
11212
11715
  const rect = element.getBoundingClientRect();
@@ -11231,183 +11734,9 @@ function styleToDiagnostic(element) {
11231
11734
  zIndex: style.zIndex
11232
11735
  };
11233
11736
  }
11234
- var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2({
11235
- closeWindowLabel,
11236
- item,
11237
- labelMode,
11238
- onCloseNode,
11239
- onSelectNode,
11240
- previewState,
11241
- style,
11242
- variant
11243
- }, ref) {
11244
- const title = item.title?.trim() || item.node.title;
11245
- const isMinimizedStack = variant === "minimized-stack";
11246
- const [isLaunching, setIsLaunching] = useState7(false);
11247
- const launchTimerRef = useRef8(null);
11248
- useEffect9(
11249
- () => () => {
11250
- if (launchTimerRef.current !== null) {
11251
- clearTimeout(launchTimerRef.current);
11252
- }
11253
- },
11254
- []
11255
- );
11256
- const handleSelect = useCallback11(() => {
11257
- if (!isMinimizedStack) {
11258
- onSelectNode(item.node.id);
11259
- return;
11260
- }
11261
- if (launchTimerRef.current !== null) {
11262
- return;
11263
- }
11264
- setIsLaunching(true);
11265
- launchTimerRef.current = setTimeout(() => {
11266
- launchTimerRef.current = null;
11267
- onSelectNode(item.node.id);
11268
- }, dockPopupMinimizedStackLaunchDisappearMs);
11269
- }, [isMinimizedStack, item.node.id, onSelectNode]);
11270
- const handleSelectKeyDown = useCallback11(
11271
- (event) => {
11272
- if (event.key !== "Enter" && event.key !== " ") {
11273
- return;
11274
- }
11275
- event.preventDefault();
11276
- handleSelect();
11277
- },
11278
- [handleSelect]
11279
- );
11280
- const hasReadyPreview = previewState.status === "ready";
11281
- return /* @__PURE__ */ jsxs8(
11282
- "div",
11283
- {
11284
- ref,
11285
- className: cn(
11286
- "group/dock-popup-card relative flex h-[103px] w-[165px] min-w-0 flex-col overflow-hidden rounded-[8px] border border-[var(--border-1)] bg-background-fronted text-left text-[var(--text-primary)] transition-[border-color,color] duration-150",
11287
- item.isMinimized && "text-[var(--text-secondary)]"
11288
- ),
11289
- "data-active": item.isFocused ? "true" : void 0,
11290
- "data-desktop-dock-popup-card": "true",
11291
- "data-fan-card": isMinimizedStack ? "true" : void 0,
11292
- "data-launching": isLaunching ? "true" : void 0,
11293
- "data-minimized": item.isMinimized ? "true" : void 0,
11294
- style,
11295
- children: [
11296
- /* @__PURE__ */ jsxs8(
11297
- "div",
11298
- {
11299
- "aria-label": title,
11300
- "data-active": item.isFocused ? "true" : void 0,
11301
- className: cn(
11302
- "relative flex min-h-0 min-w-0 flex-1 cursor-pointer flex-col overflow-hidden rounded-md bg-transparent text-inherit",
11303
- hasReadyPreview ? "p-0" : "p-1"
11304
- ),
11305
- role: "button",
11306
- tabIndex: 0,
11307
- onClick: handleSelect,
11308
- onKeyDown: handleSelectKeyDown,
11309
- children: [
11310
- /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardPreview, { previewState }),
11311
- labelMode === "hover-overlay" && item.title?.trim() ? /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardLabel, { title: item.title }) : null
11312
- ]
11313
- }
11314
- ),
11315
- /* @__PURE__ */ jsx11(
11316
- Button2,
11317
- {
11318
- "aria-label": closeWindowLabel(title),
11319
- className: "absolute top-1.5 right-1.5 z-[2] rounded-full bg-[var(--background-fronted)] opacity-0 transition-[background-color,opacity] duration-150 hover:bg-[var(--background-fronted)] focus-visible:bg-[var(--background-fronted)] group-hover/dock-popup-card:opacity-100 group-focus-within/dock-popup-card:opacity-100 focus-visible:opacity-100",
11320
- size: "icon-sm",
11321
- title: closeWindowLabel(title),
11322
- type: "button",
11323
- variant: "ghost",
11324
- onClick: (event) => {
11325
- event.preventDefault();
11326
- event.stopPropagation();
11327
- onCloseNode(item.node.id);
11328
- },
11329
- children: /* @__PURE__ */ jsx11(CloseIcon, { className: "size-3.5" })
11330
- }
11331
- ),
11332
- item.isFocused ? /* @__PURE__ */ jsx11(
11333
- "span",
11334
- {
11335
- "aria-hidden": "true",
11336
- className: "pointer-events-none absolute inset-0 z-[3] rounded-md shadow-[inset_0_0_0_2px_var(--border-focus)]",
11337
- "data-desktop-dock-popup-card-active-overlay": "true"
11338
- }
11339
- ) : null,
11340
- isMinimizedStack ? /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__fan-title-tip", title, children: title }) : null
11341
- ]
11342
- }
11343
- );
11344
- });
11345
- function WorkbenchHostDockPopupCardPreview({
11346
- previewState
11347
- }) {
11348
- if (previewState.status !== "ready") {
11349
- return /* @__PURE__ */ jsxs8(
11350
- "span",
11351
- {
11352
- className: "flex min-h-0 min-w-0 flex-1 flex-col justify-center gap-[7px] rounded-md border border-[var(--border-1)] bg-transparency-block px-3 py-[11px]",
11353
- "aria-hidden": "true",
11354
- "data-preview-state": previewState.status,
11355
- children: [
11356
- /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[72%] rounded-full bg-transparency-hover" }),
11357
- /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[58%] rounded-full bg-transparency-hover" }),
11358
- /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[34%] rounded-full bg-transparency-hover" })
11359
- ]
11360
- }
11361
- );
11362
- }
11363
- const preview = previewState.preview;
11364
- if (preview.kind === "component") {
11365
- return /* @__PURE__ */ jsx11(
11366
- "span",
11367
- {
11368
- className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
11369
- "aria-hidden": "true",
11370
- "data-preview-kind": preview.kind,
11371
- "data-preview-state": previewState.status,
11372
- children: preview.element
11373
- }
11374
- );
11375
- }
11376
- return /* @__PURE__ */ jsx11(
11377
- "span",
11378
- {
11379
- className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
11380
- "aria-hidden": "true",
11381
- "data-preview-kind": preview.kind,
11382
- "data-preview-state": previewState.status,
11383
- children: /* @__PURE__ */ jsx11(
11384
- "img",
11385
- {
11386
- alt: "",
11387
- className: "block h-full max-h-full w-full max-w-full object-contain object-center",
11388
- draggable: false,
11389
- src: preview.src
11390
- }
11391
- )
11392
- }
11393
- );
11394
- }
11395
- function WorkbenchHostDockPopupCardLabel({ title }) {
11396
- return /* @__PURE__ */ jsx11(
11397
- "span",
11398
- {
11399
- className: "pointer-events-none absolute inset-x-0 bottom-0 z-[1] flex h-[30px] items-end px-[10px] pb-0.5 text-[var(--white-stationary)] opacity-0 transition-opacity duration-150 [text-shadow:0_1px_2px_rgb(0_0_0_/_20%)] group-hover/dock-popup-card:opacity-100 group-focus-within/dock-popup-card:opacity-100",
11400
- style: {
11401
- background: "linear-gradient(180deg, transparent 0%, color-mix(in srgb, hsl(var(--card)) 28%, transparent) 18%, color-mix(in srgb, hsl(var(--card)) 82%, transparent) 56%, color-mix(in srgb, hsl(var(--card)) 98%, transparent) 100%)"
11402
- },
11403
- title,
11404
- children: /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__title-viewport block min-w-0 flex-1 overflow-hidden whitespace-nowrap", children: /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__title-marquee inline-block max-w-full overflow-hidden text-[12px] font-semibold leading-5 text-ellipsis whitespace-nowrap", children: title }) })
11405
- }
11406
- );
11407
- }
11408
11737
 
11409
11738
  // src/host/WorkbenchHostDock.tsx
11410
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
11739
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
11411
11740
  var minimizedDockPreviewViewport = {
11412
11741
  height: 34.2,
11413
11742
  width: 46.8
@@ -11452,73 +11781,73 @@ function WorkbenchHostDock({
11452
11781
  onMissionControlRequestOpen,
11453
11782
  workspaceId
11454
11783
  }) {
11455
- const minimizedNodeIDs = useMemo9(
11784
+ const minimizedNodeIDs = useMemo10(
11456
11785
  () => new Set(context.minimizedNodes.map((node) => node.id)),
11457
11786
  [context.minimizedNodes]
11458
11787
  );
11459
- const dockPlateRef = useRef9(null);
11460
- const dockMeasureRef = useRef9(null);
11461
- const dockItemsRef = useRef9(null);
11462
- const hoverPanelRef = useRef9(null);
11463
- const hoverPanelCloseTimerRef = useRef9(
11788
+ const dockPlateRef = useRef11(null);
11789
+ const dockMeasureRef = useRef11(null);
11790
+ const dockItemsRef = useRef11(null);
11791
+ const hoverPanelRef = useRef11(null);
11792
+ const hoverPanelCloseTimerRef = useRef11(
11464
11793
  null
11465
11794
  );
11466
- const hoverPanelOpenTimerRef = useRef9(
11795
+ const hoverPanelOpenTimerRef = useRef11(
11467
11796
  null
11468
11797
  );
11469
- const labelTooltipOpenTimerRef = useRef9(
11798
+ const labelTooltipOpenTimerRef = useRef11(
11470
11799
  null
11471
11800
  );
11472
- const hoverPanelScheduledPointRef = useRef9(null);
11473
- const labelTooltipScheduledPointRef = useRef9(null);
11474
- const hoverPanelRestTargetRef = useRef9(null);
11475
- const activeHoverPanelRef = useRef9(
11801
+ const hoverPanelScheduledPointRef = useRef11(null);
11802
+ const labelTooltipScheduledPointRef = useRef11(null);
11803
+ const hoverPanelRestTargetRef = useRef11(null);
11804
+ const activeHoverPanelRef = useRef11(
11476
11805
  null
11477
11806
  );
11478
- const activeLabelTooltipRef = useRef9(null);
11479
- const pendingDockStateRefreshRef = useRef9(false);
11480
- const slotRefs = useRef9(/* @__PURE__ */ new Map());
11481
- const wallpaperToneElementRefs = useRef9(/* @__PURE__ */ new Map());
11482
- const dockSlotRefCallbacksRef = useRef9(
11807
+ const activeLabelTooltipRef = useRef11(null);
11808
+ const pendingDockStateRefreshRef = useRef11(false);
11809
+ const slotRefs = useRef11(/* @__PURE__ */ new Map());
11810
+ const wallpaperToneElementRefs = useRef11(/* @__PURE__ */ new Map());
11811
+ const dockSlotRefCallbacksRef = useRef11(
11483
11812
  /* @__PURE__ */ new Map()
11484
11813
  );
11485
- const previousAttentionTokenByEntryId = useRef9(/* @__PURE__ */ new Map());
11486
- const dockEntryClickThrottleUntilRef = useRef9(/* @__PURE__ */ new Map());
11487
- const attentionTimeouts = useRef9(
11814
+ const previousAttentionTokenByEntryId = useRef11(/* @__PURE__ */ new Map());
11815
+ const dockEntryClickThrottleUntilRef = useRef11(/* @__PURE__ */ new Map());
11816
+ const attentionTimeouts = useRef11(
11488
11817
  /* @__PURE__ */ new Map()
11489
11818
  );
11490
- const [activeAttentionEntryIds, setActiveAttentionEntryIds] = useState8(/* @__PURE__ */ new Set());
11491
- const [activePopup, setActivePopup] = useState8(null);
11492
- const [activeHoverPanel, setActiveHoverPanel] = useState8(null);
11493
- const [activeLabelTooltip, setActiveLabelTooltip] = useState8(null);
11494
- const [activeMinimizedStackPopup, setActiveMinimizedStackPopup] = useState8(null);
11495
- const [pendingActionKeys, setPendingActionKeys] = useState8(
11819
+ const [activeAttentionEntryIds, setActiveAttentionEntryIds] = useState10(/* @__PURE__ */ new Set());
11820
+ const [activePopup, setActivePopup] = useState10(null);
11821
+ const [activeHoverPanel, setActiveHoverPanel] = useState10(null);
11822
+ const [activeLabelTooltip, setActiveLabelTooltip] = useState10(null);
11823
+ const [activeMinimizedStackPopup, setActiveMinimizedStackPopup] = useState10(null);
11824
+ const [pendingActionKeys, setPendingActionKeys] = useState10(
11496
11825
  () => /* @__PURE__ */ new Set()
11497
11826
  );
11498
- const [dockFrameSize, setDockFrameSize] = useState8(null);
11827
+ const [dockFrameSize, setDockFrameSize] = useState10(null);
11499
11828
  const { triggerDockBounce } = useDockBounce(slotRefs);
11500
- const [dockScrollState, setDockScrollState] = useState8(() => ({
11829
+ const [dockScrollState, setDockScrollState] = useState10(() => ({
11501
11830
  canScrollBackward: false,
11502
11831
  canScrollForward: false,
11503
11832
  hasOverflow: false
11504
11833
  }));
11505
- const [dockStateRevision, setDockStateRevision] = useState8(0);
11506
- const [externalStateRevision, setExternalStateRevision] = useState8(0);
11834
+ const [dockStateRevision, setDockStateRevision] = useState10(0);
11835
+ const [externalStateRevision, setExternalStateRevision] = useState10(0);
11507
11836
  const [
11508
11837
  collapsingMinimizedLaunchAnchorKeys,
11509
11838
  setCollapsingMinimizedLaunchAnchorKeys
11510
- ] = useState8(() => /* @__PURE__ */ new Set());
11511
- const collapsingMinimizedLaunchTimerRef = useRef9(
11839
+ ] = useState10(() => /* @__PURE__ */ new Set());
11840
+ const collapsingMinimizedLaunchTimerRef = useRef11(
11512
11841
  /* @__PURE__ */ new Map()
11513
11842
  );
11514
- const clearHoverPanelCloseTimer = useCallback12(() => {
11843
+ const clearHoverPanelCloseTimer = useCallback13(() => {
11515
11844
  if (hoverPanelCloseTimerRef.current === null) {
11516
11845
  return;
11517
11846
  }
11518
11847
  clearTimeout(hoverPanelCloseTimerRef.current);
11519
11848
  hoverPanelCloseTimerRef.current = null;
11520
11849
  }, []);
11521
- const clearHoverPanelOpenTimer = useCallback12(() => {
11850
+ const clearHoverPanelOpenTimer = useCallback13(() => {
11522
11851
  if (hoverPanelOpenTimerRef.current === null) {
11523
11852
  return;
11524
11853
  }
@@ -11526,7 +11855,7 @@ function WorkbenchHostDock({
11526
11855
  hoverPanelOpenTimerRef.current = null;
11527
11856
  hoverPanelScheduledPointRef.current = null;
11528
11857
  }, []);
11529
- const clearLabelTooltipOpenTimer = useCallback12(() => {
11858
+ const clearLabelTooltipOpenTimer = useCallback13(() => {
11530
11859
  if (labelTooltipOpenTimerRef.current === null) {
11531
11860
  return;
11532
11861
  }
@@ -11534,7 +11863,7 @@ function WorkbenchHostDock({
11534
11863
  labelTooltipOpenTimerRef.current = null;
11535
11864
  labelTooltipScheduledPointRef.current = null;
11536
11865
  }, []);
11537
- useEffect10(
11866
+ useEffect12(
11538
11867
  () => () => {
11539
11868
  clearHoverPanelCloseTimer();
11540
11869
  clearHoverPanelOpenTimer();
@@ -11550,7 +11879,7 @@ function WorkbenchHostDock({
11550
11879
  clearLabelTooltipOpenTimer
11551
11880
  ]
11552
11881
  );
11553
- const clearCollapsingMinimizedLaunch = useCallback12((anchorKey) => {
11882
+ const clearCollapsingMinimizedLaunch = useCallback13((anchorKey) => {
11554
11883
  const timer = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
11555
11884
  if (timer) {
11556
11885
  clearTimeout(timer);
@@ -11569,7 +11898,7 @@ function WorkbenchHostDock({
11569
11898
  return next;
11570
11899
  });
11571
11900
  }, []);
11572
- const scheduleCollapsingMinimizedLaunchClear = useCallback12(
11901
+ const scheduleCollapsingMinimizedLaunchClear = useCallback13(
11573
11902
  (anchorKey) => {
11574
11903
  const existing = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
11575
11904
  if (existing) {
@@ -11584,7 +11913,7 @@ function WorkbenchHostDock({
11584
11913
  },
11585
11914
  [clearCollapsingMinimizedLaunch]
11586
11915
  );
11587
- useLayoutEffect7(() => {
11916
+ useLayoutEffect8(() => {
11588
11917
  const element = dockMeasureRef.current;
11589
11918
  if (!element || typeof window === "undefined") {
11590
11919
  return void 0;
@@ -11621,14 +11950,14 @@ function WorkbenchHostDock({
11621
11950
  window.removeEventListener("resize", scheduleUpdate);
11622
11951
  };
11623
11952
  }, [dockPlacement]);
11624
- const flushPendingDockStateRefresh = useCallback12(() => {
11953
+ const flushPendingDockStateRefresh = useCallback13(() => {
11625
11954
  if (!pendingDockStateRefreshRef.current) {
11626
11955
  return;
11627
11956
  }
11628
11957
  pendingDockStateRefreshRef.current = false;
11629
11958
  setDockStateRevision((revision) => revision + 1);
11630
11959
  }, []);
11631
- useEffect10(() => {
11960
+ useEffect12(() => {
11632
11961
  if (!dockStateSource) {
11633
11962
  return void 0;
11634
11963
  }
@@ -11640,14 +11969,14 @@ function WorkbenchHostDock({
11640
11969
  setDockStateRevision((revision) => revision + 1);
11641
11970
  });
11642
11971
  }, [dockStateSource]);
11643
- const renderedDockEntries = useMemo9(
11972
+ const renderedDockEntries = useMemo10(
11644
11973
  () => dockEntries.map((entry) => {
11645
11974
  const dynamicState = dockStateSource?.getEntryState(entry.id);
11646
11975
  return dynamicState ? { ...entry, ...dynamicState } : entry;
11647
11976
  }),
11648
11977
  [dockEntries, dockStateRevision, dockStateSource]
11649
11978
  );
11650
- const resolvedEntries = useMemo9(
11979
+ const resolvedEntries = useMemo10(
11651
11980
  () => resolveWorkbenchDockEntries({
11652
11981
  dockEntries: renderedDockEntries,
11653
11982
  minimizedNodeIds: minimizedNodeIDs,
@@ -11655,7 +11984,7 @@ function WorkbenchHostDock({
11655
11984
  }),
11656
11985
  [context.nodes, minimizedNodeIDs, renderedDockEntries]
11657
11986
  );
11658
- const minimizedDockSlots = useMemo9(
11987
+ const minimizedDockSlots = useMemo10(
11659
11988
  () => resolveWorkbenchMinimizedDockSlots({
11660
11989
  nodeDefinitions,
11661
11990
  nodes: context.minimizedNodes
@@ -11663,7 +11992,7 @@ function WorkbenchHostDock({
11663
11992
  [context.minimizedNodes, nodeDefinitions]
11664
11993
  );
11665
11994
  const { promotedNodeId, stackDispatching } = useMinimizedDockStackPromotion(minimizedDockSlots);
11666
- const dockItems = useMemo9(
11995
+ const dockItems = useMemo10(
11667
11996
  () => createWorkbenchHostDockItems({
11668
11997
  minimizedDockSlots,
11669
11998
  resolvedEntries
@@ -11674,7 +12003,7 @@ function WorkbenchHostDock({
11674
12003
  dockItems,
11675
12004
  (nodeId) => context.genie.shouldAnimateMinimizedDockEnter(nodeId)
11676
12005
  );
11677
- const presentDockItemKeys = useMemo9(
12006
+ const presentDockItemKeys = useMemo10(
11678
12007
  () => presentDockItems.map((item) => item.key).join("\n"),
11679
12008
  [presentDockItems]
11680
12009
  );
@@ -11683,7 +12012,7 @@ function WorkbenchHostDock({
11683
12012
  elementRefs: wallpaperToneElementRefs,
11684
12013
  itemKeys: presentDockItemKeys
11685
12014
  });
11686
- const dockWidth = useMemo9(
12015
+ const dockWidth = useMemo10(
11687
12016
  () => resolveWorkbenchHostDockItemsWidth(dockItems),
11688
12017
  [dockItems]
11689
12018
  );
@@ -11700,10 +12029,10 @@ function WorkbenchHostDock({
11700
12029
  dockViewportRef: dockItemsRef,
11701
12030
  slotRefs
11702
12031
  });
11703
- const clearSlotMagnificationRef = useRef9(() => {
12032
+ const clearSlotMagnificationRef = useRef11(() => {
11704
12033
  return;
11705
12034
  });
11706
- const registerDockAnchorRef = useRef9(
12035
+ const registerDockAnchorRef = useRef11(
11707
12036
  (anchorKey, element) => {
11708
12037
  context.genie.registerDockAnchor(anchorKey, element);
11709
12038
  }
@@ -11714,7 +12043,7 @@ function WorkbenchHostDock({
11714
12043
  registerDockAnchorRef.current = (anchorKey, element) => {
11715
12044
  context.genie.registerDockAnchor(anchorKey, element);
11716
12045
  };
11717
- const registerWallpaperToneElement = useCallback12(
12046
+ const registerWallpaperToneElement = useCallback13(
11718
12047
  (key) => (element) => {
11719
12048
  if (element) {
11720
12049
  wallpaperToneElementRefs.current.set(key, element);
@@ -11724,7 +12053,7 @@ function WorkbenchHostDock({
11724
12053
  },
11725
12054
  []
11726
12055
  );
11727
- const setDockHoverPanelOpen = useCallback12((open) => {
12056
+ const setDockHoverPanelOpen = useCallback13((open) => {
11728
12057
  if (open) {
11729
12058
  dockMeasureRef.current?.setAttribute(
11730
12059
  "data-dock-hover-panel-open",
@@ -11734,13 +12063,13 @@ function WorkbenchHostDock({
11734
12063
  }
11735
12064
  dockMeasureRef.current?.removeAttribute("data-dock-hover-panel-open");
11736
12065
  }, []);
11737
- useEffect10(() => {
12066
+ useEffect12(() => {
11738
12067
  activeHoverPanelRef.current = activeHoverPanel;
11739
12068
  }, [activeHoverPanel]);
11740
- useEffect10(() => {
12069
+ useEffect12(() => {
11741
12070
  activeLabelTooltipRef.current = activeLabelTooltip;
11742
12071
  }, [activeLabelTooltip]);
11743
- const closeLabelTooltipImmediate = useCallback12(
12072
+ const closeLabelTooltipImmediate = useCallback13(
11744
12073
  (targetKey) => {
11745
12074
  clearLabelTooltipOpenTimer();
11746
12075
  if (targetKey !== void 0 && activeLabelTooltipRef.current?.key !== targetKey) {
@@ -11754,7 +12083,7 @@ function WorkbenchHostDock({
11754
12083
  },
11755
12084
  [clearLabelTooltipOpenTimer]
11756
12085
  );
11757
- const closeHoverPanelImmediate = useCallback12(
12086
+ const closeHoverPanelImmediate = useCallback13(
11758
12087
  (entryId) => {
11759
12088
  clearHoverPanelOpenTimer();
11760
12089
  clearHoverPanelCloseTimer();
@@ -11777,7 +12106,7 @@ function WorkbenchHostDock({
11777
12106
  setDockHoverPanelOpen
11778
12107
  ]
11779
12108
  );
11780
- const scheduleHoverPanelClose = useCallback12(
12109
+ const scheduleHoverPanelClose = useCallback13(
11781
12110
  (entryId) => {
11782
12111
  clearHoverPanelOpenTimer();
11783
12112
  clearHoverPanelCloseTimer();
@@ -11794,7 +12123,7 @@ function WorkbenchHostDock({
11794
12123
  handleDockPointerLeave
11795
12124
  ]
11796
12125
  );
11797
- const showHoverPanel = useCallback12(
12126
+ const showHoverPanel = useCallback13(
11798
12127
  (entryId, anchorKey, anchorElement) => {
11799
12128
  const dockElement = dockMeasureRef.current;
11800
12129
  if (!dockElement) {
@@ -11820,7 +12149,7 @@ function WorkbenchHostDock({
11820
12149
  },
11821
12150
  [clearHoverPanelCloseTimer, pauseDockMagnification, setDockHoverPanelOpen]
11822
12151
  );
11823
- const scheduleHoverPanelAfterRest = useCallback12(
12152
+ const scheduleHoverPanelAfterRest = useCallback13(
11824
12153
  (entryId, anchorKey) => {
11825
12154
  hoverPanelRestTargetRef.current = { anchorKey, entryId };
11826
12155
  clearHoverPanelOpenTimer();
@@ -11841,7 +12170,7 @@ function WorkbenchHostDock({
11841
12170
  },
11842
12171
  [clearHoverPanelOpenTimer, showHoverPanel]
11843
12172
  );
11844
- const showLabelTooltip = useCallback12(
12173
+ const showLabelTooltip = useCallback13(
11845
12174
  (target, anchorKey, anchorElement) => {
11846
12175
  const dockElement = dockMeasureRef.current;
11847
12176
  if (!dockElement) {
@@ -11866,7 +12195,7 @@ function WorkbenchHostDock({
11866
12195
  },
11867
12196
  [clearLabelTooltipOpenTimer]
11868
12197
  );
11869
- const scheduleLabelTooltipAfterRest = useCallback12(
12198
+ const scheduleLabelTooltipAfterRest = useCallback13(
11870
12199
  (target, anchorKey) => {
11871
12200
  clearLabelTooltipOpenTimer();
11872
12201
  labelTooltipScheduledPointRef.current = null;
@@ -11882,7 +12211,7 @@ function WorkbenchHostDock({
11882
12211
  },
11883
12212
  [clearLabelTooltipOpenTimer, showLabelTooltip]
11884
12213
  );
11885
- const resolveHoverPanelTargetAtPoint = useCallback12(
12214
+ const resolveHoverPanelTargetAtPoint = useCallback13(
11886
12215
  (clientX, clientY) => {
11887
12216
  for (const [anchorKey, slotElement] of slotRefs.current) {
11888
12217
  const entryId = slotElement.dataset.dockHoverPanelEntryId;
@@ -11898,7 +12227,7 @@ function WorkbenchHostDock({
11898
12227
  },
11899
12228
  []
11900
12229
  );
11901
- const resolveLabelTooltipTargetAtPoint = useCallback12(
12230
+ const resolveLabelTooltipTargetAtPoint = useCallback13(
11902
12231
  (clientX, clientY) => {
11903
12232
  for (const [anchorKey, slotElement] of slotRefs.current) {
11904
12233
  if (slotElement.dataset.dockHoverPanelEntryId) {
@@ -11925,7 +12254,7 @@ function WorkbenchHostDock({
11925
12254
  },
11926
12255
  []
11927
12256
  );
11928
- const isPointerInsideActiveHoverPanelRegion = useCallback12(
12257
+ const isPointerInsideActiveHoverPanelRegion = useCallback13(
11929
12258
  (clientX, clientY) => {
11930
12259
  const activeHoverPanel2 = activeHoverPanelRef.current;
11931
12260
  if (!activeHoverPanel2) {
@@ -11957,7 +12286,7 @@ function WorkbenchHostDock({
11957
12286
  },
11958
12287
  []
11959
12288
  );
11960
- const scheduleHoverPanelAtPointAfterRest = useCallback12(
12289
+ const scheduleHoverPanelAtPointAfterRest = useCallback13(
11961
12290
  (clientX, clientY) => {
11962
12291
  const scheduledPoint = hoverPanelScheduledPointRef.current;
11963
12292
  if (hoverPanelOpenTimerRef.current !== null && scheduledPoint && Math.abs(clientX - scheduledPoint.clientX) <= dockHoverPanelPointerRestTolerancePx && Math.abs(clientY - scheduledPoint.clientY) <= dockHoverPanelPointerRestTolerancePx) {
@@ -11985,7 +12314,7 @@ function WorkbenchHostDock({
11985
12314
  },
11986
12315
  [clearHoverPanelOpenTimer, resolveHoverPanelTargetAtPoint, showHoverPanel]
11987
12316
  );
11988
- const scheduleLabelTooltipAtPointAfterRest = useCallback12(
12317
+ const scheduleLabelTooltipAtPointAfterRest = useCallback13(
11989
12318
  (clientX, clientY) => {
11990
12319
  if (activeLabelTooltipRef.current !== null) {
11991
12320
  return;
@@ -12015,7 +12344,7 @@ function WorkbenchHostDock({
12015
12344
  showLabelTooltip
12016
12345
  ]
12017
12346
  );
12018
- const beginDockIconInteraction = useCallback12(
12347
+ const beginDockIconInteraction = useCallback13(
12019
12348
  (anchorKey) => {
12020
12349
  hoverPanelRestTargetRef.current = null;
12021
12350
  clearHoverPanelOpenTimer();
@@ -12030,20 +12359,20 @@ function WorkbenchHostDock({
12030
12359
  triggerDockBounce
12031
12360
  ]
12032
12361
  );
12033
- const isDockEntryClickThrottled = useCallback12(
12362
+ const isDockEntryClickThrottled = useCallback13(
12034
12363
  (anchorKey) => {
12035
12364
  const throttledUntil = dockEntryClickThrottleUntilRef.current.get(anchorKey);
12036
12365
  return throttledUntil !== void 0 && Date.now() < throttledUntil;
12037
12366
  },
12038
12367
  []
12039
12368
  );
12040
- const claimDockEntryClick = useCallback12((anchorKey) => {
12369
+ const claimDockEntryClick = useCallback13((anchorKey) => {
12041
12370
  dockEntryClickThrottleUntilRef.current.set(
12042
12371
  anchorKey,
12043
12372
  Date.now() + DOCK_ENTRY_CLICK_THROTTLE_MS
12044
12373
  );
12045
12374
  }, []);
12046
- const beginDockMinimizedInteraction = useCallback12(
12375
+ const beginDockMinimizedInteraction = useCallback13(
12047
12376
  (anchorKey) => {
12048
12377
  hoverPanelRestTargetRef.current = null;
12049
12378
  clearHoverPanelOpenTimer();
@@ -12083,7 +12412,7 @@ function WorkbenchHostDock({
12083
12412
  pauseDockMagnification
12084
12413
  ]
12085
12414
  );
12086
- const runDockMinimizedLaunchAfterCollapse = useCallback12(
12415
+ const runDockMinimizedLaunchAfterCollapse = useCallback13(
12087
12416
  (intent, launch) => {
12088
12417
  const { anchorKey } = intent;
12089
12418
  beginDockMinimizedInteraction(anchorKey);
@@ -12097,14 +12426,14 @@ function WorkbenchHostDock({
12097
12426
  },
12098
12427
  [beginDockMinimizedInteraction, scheduleCollapsingMinimizedLaunchClear]
12099
12428
  );
12100
- const runDockMinimizedStackLaunch = useCallback12(
12429
+ const runDockMinimizedStackLaunch = useCallback13(
12101
12430
  (intent, launch) => {
12102
12431
  beginDockMinimizedInteraction();
12103
12432
  launch(intent);
12104
12433
  },
12105
12434
  [beginDockMinimizedInteraction]
12106
12435
  );
12107
- const handleDockPointerTravel = useCallback12(
12436
+ const handleDockPointerTravel = useCallback13(
12108
12437
  (clientX, clientY) => {
12109
12438
  if (activeHoverPanelRef.current !== null) {
12110
12439
  closeLabelTooltipImmediate();
@@ -12139,7 +12468,7 @@ function WorkbenchHostDock({
12139
12468
  scheduleLabelTooltipAtPointAfterRest
12140
12469
  ]
12141
12470
  );
12142
- const updateDockScrollState = useCallback12(() => {
12471
+ const updateDockScrollState = useCallback13(() => {
12143
12472
  const scrollElement = dockItemsRef.current;
12144
12473
  const viewportElement = dockMeasureRef.current;
12145
12474
  if (!scrollElement || !viewportElement) {
@@ -12166,7 +12495,7 @@ function WorkbenchHostDock({
12166
12495
  (current) => current.canScrollBackward === nextState.canScrollBackward && current.canScrollForward === nextState.canScrollForward && current.hasOverflow === nextState.hasOverflow ? current : nextState
12167
12496
  );
12168
12497
  }, [dockPlacement, dockWidth]);
12169
- useLayoutEffect7(() => {
12498
+ useLayoutEffect8(() => {
12170
12499
  const element = dockItemsRef.current;
12171
12500
  if (!element || typeof window === "undefined") {
12172
12501
  return void 0;
@@ -12209,7 +12538,7 @@ function WorkbenchHostDock({
12209
12538
  })()
12210
12539
  )
12211
12540
  );
12212
- useEffect10(() => {
12541
+ useEffect12(() => {
12213
12542
  const shouldSubscribe = activePopup !== null || hasMinimizedPreviewCapture;
12214
12543
  if (!shouldSubscribe || !externalStateSource?.subscribeNodeState) {
12215
12544
  return void 0;
@@ -12234,7 +12563,7 @@ function WorkbenchHostDock({
12234
12563
  hasMinimizedPreviewCapture,
12235
12564
  workspaceId
12236
12565
  ]);
12237
- useEffect10(() => {
12566
+ useEffect12(() => {
12238
12567
  const nextAttentionIds = /* @__PURE__ */ new Set();
12239
12568
  for (const entry of renderedDockEntries) {
12240
12569
  const nextToken = entry.attentionToken ?? null;
@@ -12275,7 +12604,7 @@ function WorkbenchHostDock({
12275
12604
  );
12276
12605
  }
12277
12606
  }, [renderedDockEntries]);
12278
- useEffect10(
12607
+ useEffect12(
12279
12608
  () => () => {
12280
12609
  for (const timeout of attentionTimeouts.current.values()) {
12281
12610
  globalThis.clearTimeout(timeout);
@@ -12284,7 +12613,7 @@ function WorkbenchHostDock({
12284
12613
  },
12285
12614
  []
12286
12615
  );
12287
- const captureMinimizedNodePreview = useCallback12(
12616
+ const captureMinimizedNodePreview = useCallback13(
12288
12617
  async (node) => {
12289
12618
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
12290
12619
  const capturePreview = minimizedDock?.kind === "snapshot" ? minimizedDock.capturePreview : void 0;
@@ -12315,7 +12644,7 @@ function WorkbenchHostDock({
12315
12644
  workspaceId
12316
12645
  ]
12317
12646
  );
12318
- const provideMinimizedNodePreview = useCallback12(
12647
+ const provideMinimizedNodePreview = useCallback13(
12319
12648
  (node) => {
12320
12649
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
12321
12650
  if (minimizedDock?.kind !== "component") {
@@ -12344,7 +12673,7 @@ function WorkbenchHostDock({
12344
12673
  workspaceId
12345
12674
  ]
12346
12675
  );
12347
- const provideMinimizedNodePreviewForNode = useCallback12(
12676
+ const provideMinimizedNodePreviewForNode = useCallback13(
12348
12677
  (node) => {
12349
12678
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
12350
12679
  return minimizedDock?.kind === "component" ? provideMinimizedNodePreview : void 0;
@@ -12380,7 +12709,7 @@ function WorkbenchHostDock({
12380
12709
  top: isVertical ? delta : 0
12381
12710
  });
12382
12711
  };
12383
- const registerDockSlot = useCallback12((anchorKey) => {
12712
+ const registerDockSlot = useCallback13((anchorKey) => {
12384
12713
  const existing = dockSlotRefCallbacksRef.current.get(anchorKey);
12385
12714
  if (existing) {
12386
12715
  return existing;
@@ -12401,7 +12730,7 @@ function WorkbenchHostDock({
12401
12730
  dockSlotRefCallbacksRef.current.set(anchorKey, callback);
12402
12731
  return callback;
12403
12732
  }, []);
12404
- const runDockEntryAction = useCallback12(
12733
+ const runDockEntryAction = useCallback13(
12405
12734
  (entryId, actionId) => {
12406
12735
  const actionKey = dockActionKey(entryId, actionId);
12407
12736
  if (pendingActionKeys.has(actionKey)) {
@@ -12457,13 +12786,13 @@ function WorkbenchHostDock({
12457
12786
  instanceMode: dockContextMenuInstanceMode,
12458
12787
  matchedNodes: popupEntry.matchedNodes
12459
12788
  }).kind === "launch";
12460
- return /* @__PURE__ */ jsxs9(
12789
+ return /* @__PURE__ */ jsxs10(
12461
12790
  "div",
12462
12791
  {
12463
12792
  className: "flex justify-center pointer-events-none",
12464
12793
  "data-dock-placement": dockPlacement,
12465
12794
  children: [
12466
- /* @__PURE__ */ jsx12(
12795
+ /* @__PURE__ */ jsx13(
12467
12796
  "div",
12468
12797
  {
12469
12798
  ref: dockPlateRef,
@@ -12472,7 +12801,7 @@ function WorkbenchHostDock({
12472
12801
  style: dockFrameSize === null ? void 0 : {
12473
12802
  "--desktop-dock-frame-size": `${dockFrameSize}px`
12474
12803
  },
12475
- children: /* @__PURE__ */ jsxs9(
12804
+ children: /* @__PURE__ */ jsxs10(
12476
12805
  "div",
12477
12806
  {
12478
12807
  ref: dockMeasureRef,
@@ -12498,7 +12827,7 @@ function WorkbenchHostDock({
12498
12827
  role: "toolbar",
12499
12828
  style: dockPlacement === "left" ? { height: dockWidth } : { width: dockWidth },
12500
12829
  children: [
12501
- /* @__PURE__ */ jsx12(
12830
+ /* @__PURE__ */ jsx13(
12502
12831
  "span",
12503
12832
  {
12504
12833
  className: "desktop-dock__pointer-rail",
@@ -12506,7 +12835,7 @@ function WorkbenchHostDock({
12506
12835
  "aria-hidden": true
12507
12836
  }
12508
12837
  ),
12509
- /* @__PURE__ */ jsx12(
12838
+ /* @__PURE__ */ jsx13(
12510
12839
  "button",
12511
12840
  {
12512
12841
  "aria-label": i18n.t(
@@ -12517,12 +12846,12 @@ function WorkbenchHostDock({
12517
12846
  disabled: !dockScrollState.canScrollBackward,
12518
12847
  onClick: () => scrollDockItems("backward"),
12519
12848
  type: "button",
12520
- children: dockPlacement === "left" ? /* @__PURE__ */ jsx12(ChevronUpIcon, { size: 16 }) : /* @__PURE__ */ jsx12(ArrowLeftIcon, { size: 16 })
12849
+ children: dockPlacement === "left" ? /* @__PURE__ */ jsx13(ChevronUpIcon, { size: 16 }) : /* @__PURE__ */ jsx13(ArrowLeftIcon, { size: 16 })
12521
12850
  }
12522
12851
  ),
12523
- /* @__PURE__ */ jsx12("div", { ref: dockItemsRef, className: "desktop-dock__items", children: presentDockItems.map((dockItem) => {
12852
+ /* @__PURE__ */ jsx13("div", { ref: dockItemsRef, className: "desktop-dock__items", children: presentDockItems.map((dockItem) => {
12524
12853
  if (dockItem.item.kind === "separator") {
12525
- return /* @__PURE__ */ jsx12(
12854
+ return /* @__PURE__ */ jsx13(
12526
12855
  "span",
12527
12856
  {
12528
12857
  ref: registerWallpaperToneElement(dockItem.key),
@@ -12549,7 +12878,7 @@ function WorkbenchHostDock({
12549
12878
  });
12550
12879
  const hasHoverPanel = dockEntryHasHoverPanel(entry);
12551
12880
  const labelTooltipTarget2 = hasHoverPanel ? null : dockLabelTooltipTarget(`entry:${entry.id}`, entry.label);
12552
- const dockButton2 = /* @__PURE__ */ jsx12(
12881
+ const dockButton2 = /* @__PURE__ */ jsx13(
12553
12882
  "button",
12554
12883
  {
12555
12884
  "aria-expanded": currentPopup ? true : void 0,
@@ -12708,7 +13037,7 @@ function WorkbenchHostDock({
12708
13037
  entryId: entry.id
12709
13038
  });
12710
13039
  },
12711
- children: /* @__PURE__ */ jsxs9(
13040
+ children: /* @__PURE__ */ jsxs10(
12712
13041
  "span",
12713
13042
  {
12714
13043
  className: "desktop-dock__icon-shell",
@@ -12716,7 +13045,7 @@ function WorkbenchHostDock({
12716
13045
  "data-entry-state": entry.state?.kind ?? "enabled",
12717
13046
  "aria-hidden": true,
12718
13047
  children: [
12719
- /* @__PURE__ */ jsx12("span", { className: "desktop-dock__icon-content", children: entry.icon }),
13048
+ /* @__PURE__ */ jsx13("span", { className: "desktop-dock__icon-content", children: entry.icon }),
12720
13049
  renderDockBadge(
12721
13050
  entry,
12722
13051
  resolvedEntry.matchedNodes.length
@@ -12726,7 +13055,7 @@ function WorkbenchHostDock({
12726
13055
  )
12727
13056
  }
12728
13057
  );
12729
- return /* @__PURE__ */ jsx12(
13058
+ return /* @__PURE__ */ jsx13(
12730
13059
  "span",
12731
13060
  {
12732
13061
  ref: registerDockSlot(anchorKey),
@@ -12827,7 +13156,7 @@ function WorkbenchHostDock({
12827
13156
  `minimized-stack:${slot.anchorKey}`,
12828
13157
  stackLabel
12829
13158
  );
12830
- const stackButton = /* @__PURE__ */ jsx12(
13159
+ const stackButton = /* @__PURE__ */ jsx13(
12831
13160
  "span",
12832
13161
  {
12833
13162
  "aria-expanded": stackPopupActive,
@@ -12861,7 +13190,7 @@ function WorkbenchHostDock({
12861
13190
  }
12862
13191
  );
12863
13192
  },
12864
- children: /* @__PURE__ */ jsxs9(
13193
+ children: /* @__PURE__ */ jsxs10(
12865
13194
  "span",
12866
13195
  {
12867
13196
  className: "desktop-dock__minimized-stack-icon",
@@ -12876,7 +13205,7 @@ function WorkbenchHostDock({
12876
13205
  (_, index) => {
12877
13206
  const node2 = slot.nodes[index];
12878
13207
  if (index === 0 && node2) {
12879
- return /* @__PURE__ */ jsx12(
13208
+ return /* @__PURE__ */ jsx13(
12880
13209
  WorkbenchHostDockMinimizedNodePreview,
12881
13210
  {
12882
13211
  capturePreview: captureMinimizedNodePreview,
@@ -12891,7 +13220,7 @@ function WorkbenchHostDock({
12891
13220
  minimizedDockPreviewFreezeKey(node2)
12892
13221
  );
12893
13222
  }
12894
- return /* @__PURE__ */ jsx12(
13223
+ return /* @__PURE__ */ jsx13(
12895
13224
  "span",
12896
13225
  {
12897
13226
  "aria-hidden": "true",
@@ -12901,13 +13230,13 @@ function WorkbenchHostDock({
12901
13230
  );
12902
13231
  }
12903
13232
  ),
12904
- /* @__PURE__ */ jsx12("span", { className: "desktop-dock__count-badge", children: slot.nodes.length })
13233
+ /* @__PURE__ */ jsx13("span", { className: "desktop-dock__count-badge", children: slot.nodes.length })
12905
13234
  ]
12906
13235
  }
12907
13236
  )
12908
13237
  }
12909
13238
  );
12910
- return /* @__PURE__ */ jsx12(
13239
+ return /* @__PURE__ */ jsx13(
12911
13240
  "span",
12912
13241
  {
12913
13242
  ref: registerDockSlot(slot.anchorKey),
@@ -12962,7 +13291,7 @@ function WorkbenchHostDock({
12962
13291
  `minimized-node:${node.id}`,
12963
13292
  node.title
12964
13293
  );
12965
- const dockButton = /* @__PURE__ */ jsx12(
13294
+ const dockButton = /* @__PURE__ */ jsx13(
12966
13295
  "span",
12967
13296
  {
12968
13297
  "aria-label": i18n.t("launch", { title: node.title }),
@@ -13023,7 +13352,7 @@ function WorkbenchHostDock({
13023
13352
  }
13024
13353
  );
13025
13354
  },
13026
- children: /* @__PURE__ */ jsx12(
13355
+ children: /* @__PURE__ */ jsx13(
13027
13356
  WorkbenchHostDockMinimizedNodePreview,
13028
13357
  {
13029
13358
  capturePreview: isPendingMinimizedNode ? void 0 : captureMinimizedNodePreview,
@@ -13037,7 +13366,7 @@ function WorkbenchHostDock({
13037
13366
  )
13038
13367
  }
13039
13368
  );
13040
- return /* @__PURE__ */ jsx12(
13369
+ return /* @__PURE__ */ jsx13(
13041
13370
  "span",
13042
13371
  {
13043
13372
  ref: registerDockSlot(slot.anchorKey),
@@ -13087,7 +13416,7 @@ function WorkbenchHostDock({
13087
13416
  dockItem.key
13088
13417
  );
13089
13418
  }) }),
13090
- /* @__PURE__ */ jsx12(
13419
+ /* @__PURE__ */ jsx13(
13091
13420
  "button",
13092
13421
  {
13093
13422
  "aria-label": i18n.t(
@@ -13098,10 +13427,10 @@ function WorkbenchHostDock({
13098
13427
  disabled: !dockScrollState.canScrollForward,
13099
13428
  onClick: () => scrollDockItems("forward"),
13100
13429
  type: "button",
13101
- children: dockPlacement === "left" ? /* @__PURE__ */ jsx12(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx12(ArrowRightIcon, { size: 16 })
13430
+ children: dockPlacement === "left" ? /* @__PURE__ */ jsx13(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx13(ArrowRightIcon, { size: 16 })
13102
13431
  }
13103
13432
  ),
13104
- activeHoverPanel ? /* @__PURE__ */ jsx12(
13433
+ activeHoverPanel ? /* @__PURE__ */ jsx13(
13105
13434
  WorkbenchHostDockHoverPanel,
13106
13435
  {
13107
13436
  entry: resolvedEntries.find(
@@ -13134,7 +13463,7 @@ function WorkbenchHostDock({
13134
13463
  }
13135
13464
  }
13136
13465
  ) : null,
13137
- activeLabelTooltip ? /* @__PURE__ */ jsx12(
13466
+ activeLabelTooltip ? /* @__PURE__ */ jsx13(
13138
13467
  WorkbenchHostDockLabelTooltip,
13139
13468
  {
13140
13469
  placement: dockPlacement,
@@ -13146,7 +13475,7 @@ function WorkbenchHostDock({
13146
13475
  )
13147
13476
  }
13148
13477
  ),
13149
- popupEntry && activePopup ? /* @__PURE__ */ jsx12(
13478
+ popupEntry && activePopup ? /* @__PURE__ */ jsx13(
13150
13479
  WorkbenchHostDockPopup,
13151
13480
  {
13152
13481
  anchorRect: activePopup.anchorRect,
@@ -13337,7 +13666,7 @@ function WorkbenchHostDock({
13337
13666
  variant: activePopup.kind === "context-menu" ? "context-menu" : "default"
13338
13667
  }
13339
13668
  ) : null,
13340
- activeMinimizedStackSlot && activeMinimizedStackPopup ? /* @__PURE__ */ jsx12(
13669
+ activeMinimizedStackSlot && activeMinimizedStackPopup ? /* @__PURE__ */ jsx13(
13341
13670
  WorkbenchHostDockPopup,
13342
13671
  {
13343
13672
  anchorRect: activeMinimizedStackPopup,
@@ -13437,11 +13766,11 @@ function WorkbenchHostDockMinimizedNodePreview({
13437
13766
  providePreview,
13438
13767
  workspaceId
13439
13768
  }) {
13440
- const [componentPreview, setComponentPreview] = useState8(void 0);
13441
- const [previewImageUrl, setPreviewImageUrl] = useState8(
13769
+ const [componentPreview, setComponentPreview] = useState10(void 0);
13770
+ const [previewImageUrl, setPreviewImageUrl] = useState10(
13442
13771
  () => deferPreview ? null : readCachedWorkbenchNodePreviewImage(node.id)
13443
13772
  );
13444
- useEffect10(() => {
13773
+ useEffect12(() => {
13445
13774
  if (deferPreview || !providePreview || componentPreview !== void 0 || previewImageUrl) {
13446
13775
  return void 0;
13447
13776
  }
@@ -13491,7 +13820,7 @@ function WorkbenchHostDockMinimizedNodePreview({
13491
13820
  previewImageUrl,
13492
13821
  providePreview
13493
13822
  ]);
13494
- useEffect10(() => {
13823
+ useEffect12(() => {
13495
13824
  if (deferPreview) {
13496
13825
  return void 0;
13497
13826
  }
@@ -13550,7 +13879,7 @@ function WorkbenchHostDockMinimizedNodePreview({
13550
13879
  return renderMinimizedDockPreviewPlaceholder(className);
13551
13880
  }
13552
13881
  if (previewImageUrl) {
13553
- return /* @__PURE__ */ jsx12(
13882
+ return /* @__PURE__ */ jsx13(
13554
13883
  "span",
13555
13884
  {
13556
13885
  className: [
@@ -13559,7 +13888,7 @@ function WorkbenchHostDockMinimizedNodePreview({
13559
13888
  className
13560
13889
  ].filter(Boolean).join(" "),
13561
13890
  "aria-hidden": "true",
13562
- children: /* @__PURE__ */ jsx12(
13891
+ children: /* @__PURE__ */ jsx13(
13563
13892
  "img",
13564
13893
  {
13565
13894
  alt: "",
@@ -13577,22 +13906,22 @@ function WorkbenchHostDockMinimizedNodePreview({
13577
13906
  return renderMinimizedDockPreviewPlaceholder(className);
13578
13907
  }
13579
13908
  function renderMinimizedDockPreviewPlaceholder(className) {
13580
- return /* @__PURE__ */ jsxs9(
13909
+ return /* @__PURE__ */ jsxs10(
13581
13910
  "span",
13582
13911
  {
13583
13912
  className: ["desktop-dock__minimized-preview", className].filter(Boolean).join(" "),
13584
13913
  "aria-hidden": "true",
13585
13914
  children: [
13586
- /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line" }),
13587
- /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--short" }),
13588
- /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--accent" })
13915
+ /* @__PURE__ */ jsx13("span", { className: "desktop-dock__minimized-preview-line" }),
13916
+ /* @__PURE__ */ jsx13("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--short" }),
13917
+ /* @__PURE__ */ jsx13("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--accent" })
13589
13918
  ]
13590
13919
  }
13591
13920
  );
13592
13921
  }
13593
13922
  function renderMinimizedDockPreviewContent(preview, className) {
13594
13923
  if (preview.kind === "image") {
13595
- return /* @__PURE__ */ jsx12(
13924
+ return /* @__PURE__ */ jsx13(
13596
13925
  "span",
13597
13926
  {
13598
13927
  className: [
@@ -13601,7 +13930,7 @@ function renderMinimizedDockPreviewContent(preview, className) {
13601
13930
  className
13602
13931
  ].filter(Boolean).join(" "),
13603
13932
  "aria-hidden": "true",
13604
- children: /* @__PURE__ */ jsx12(
13933
+ children: /* @__PURE__ */ jsx13(
13605
13934
  "img",
13606
13935
  {
13607
13936
  alt: "",
@@ -13613,7 +13942,7 @@ function renderMinimizedDockPreviewContent(preview, className) {
13613
13942
  }
13614
13943
  );
13615
13944
  }
13616
- return /* @__PURE__ */ jsx12(
13945
+ return /* @__PURE__ */ jsx13(
13617
13946
  WorkbenchHostDockFrozenComponentPreview,
13618
13947
  {
13619
13948
  className,
@@ -13625,15 +13954,15 @@ function WorkbenchHostDockFrozenComponentPreview({
13625
13954
  className,
13626
13955
  preview
13627
13956
  }) {
13628
- const sourceRef = useRef9(null);
13629
- const [frozenMarkup, setFrozenMarkup] = useState8(null);
13630
- useLayoutEffect7(() => {
13957
+ const sourceRef = useRef11(null);
13958
+ const [frozenMarkup, setFrozenMarkup] = useState10(null);
13959
+ useLayoutEffect8(() => {
13631
13960
  if (frozenMarkup !== null) {
13632
13961
  return;
13633
13962
  }
13634
13963
  setFrozenMarkup(sourceRef.current?.innerHTML ?? "");
13635
13964
  }, [frozenMarkup]);
13636
- return /* @__PURE__ */ jsx12(
13965
+ return /* @__PURE__ */ jsx13(
13637
13966
  "span",
13638
13967
  {
13639
13968
  className: [
@@ -13642,14 +13971,14 @@ function WorkbenchHostDockFrozenComponentPreview({
13642
13971
  className
13643
13972
  ].filter(Boolean).join(" "),
13644
13973
  "aria-hidden": "true",
13645
- children: frozenMarkup === null ? /* @__PURE__ */ jsx12(
13974
+ children: frozenMarkup === null ? /* @__PURE__ */ jsx13(
13646
13975
  "span",
13647
13976
  {
13648
13977
  ref: sourceRef,
13649
13978
  className: "desktop-dock__minimized-preview-freeze-source",
13650
13979
  children: preview.element
13651
13980
  }
13652
- ) : /* @__PURE__ */ jsx12(
13981
+ ) : /* @__PURE__ */ jsx13(
13653
13982
  "span",
13654
13983
  {
13655
13984
  className: "desktop-dock__minimized-preview-frozen-content",
@@ -13697,18 +14026,18 @@ function renderDockBadge(entry, matchedNodeCount) {
13697
14026
  return null;
13698
14027
  }
13699
14028
  if (badge.kind === "count") {
13700
- return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__count-badge", children: badge.value });
14029
+ return /* @__PURE__ */ jsx13("span", { className: "desktop-dock__count-badge", children: badge.value });
13701
14030
  }
13702
14031
  if (badge.kind === "custom") {
13703
- return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__custom-badge", children: badge.content });
14032
+ return /* @__PURE__ */ jsx13("span", { className: "desktop-dock__custom-badge", children: badge.content });
13704
14033
  }
13705
- return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__status-badge", "data-status": badge.status });
14034
+ return /* @__PURE__ */ jsx13("span", { className: "desktop-dock__status-badge", "data-status": badge.status });
13706
14035
  }
13707
14036
  function WorkbenchHostDockLabelTooltip({
13708
14037
  placement,
13709
14038
  state
13710
14039
  }) {
13711
- return /* @__PURE__ */ jsx12(
14040
+ return /* @__PURE__ */ jsx13(
13712
14041
  "div",
13713
14042
  {
13714
14043
  className: "desktop-dock__label-tooltip",
@@ -13738,7 +14067,7 @@ function WorkbenchHostDockHoverPanel({
13738
14067
  setPendingActionKeys,
13739
14068
  state
13740
14069
  }) {
13741
- const lastPointerActionAtRef = useRef9(/* @__PURE__ */ new Map());
14070
+ const lastPointerActionAtRef = useRef11(/* @__PURE__ */ new Map());
13742
14071
  if (!entry) {
13743
14072
  return null;
13744
14073
  }
@@ -13772,7 +14101,7 @@ function WorkbenchHostDockHoverPanel({
13772
14101
  }
13773
14102
  })();
13774
14103
  };
13775
- return /* @__PURE__ */ jsxs9(
14104
+ return /* @__PURE__ */ jsxs10(
13776
14105
  "div",
13777
14106
  {
13778
14107
  ref: hoverPanelRef,
@@ -13791,13 +14120,13 @@ function WorkbenchHostDockHoverPanel({
13791
14120
  "--desktop-dock-hover-panel-anchor-width": `${state.anchorRect.width}px`
13792
14121
  },
13793
14122
  children: [
13794
- /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-panel-title", children: entry.label }),
13795
- entry.state?.reason ? /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-panel-description", children: stripDockDescriptionTerminalPunctuation(entry.state.reason) }) : null,
13796
- entry.hoverActions?.length ? /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-actions", children: entry.hoverActions.map((action) => {
14123
+ /* @__PURE__ */ jsx13("div", { className: "desktop-dock__hover-panel-title", children: entry.label }),
14124
+ entry.state?.reason ? /* @__PURE__ */ jsx13("div", { className: "desktop-dock__hover-panel-description", children: stripDockDescriptionTerminalPunctuation(entry.state.reason) }) : null,
14125
+ entry.hoverActions?.length ? /* @__PURE__ */ jsx13("div", { className: "desktop-dock__hover-actions", children: entry.hoverActions.map((action) => {
13797
14126
  const actionKey = dockActionKey(entry.id, action.id);
13798
14127
  const isLocallyPending = pendingActionKeys.has(actionKey);
13799
14128
  const isPending = isLocallyPending || action.disabled === true && action.pendingLabel !== void 0;
13800
- return /* @__PURE__ */ jsx12(
14129
+ return /* @__PURE__ */ jsx13(
13801
14130
  Button3,
13802
14131
  {
13803
14132
  "aria-busy": isPending ? true : void 0,
@@ -14019,22 +14348,22 @@ function resolveDockPresenceSettleMs(items) {
14019
14348
  return dockPresenceAnimationMs;
14020
14349
  }
14021
14350
  function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
14022
- const latestItemsByKey = useRef9(/* @__PURE__ */ new Map());
14023
- const shouldAnimateMinimizedDockEnterRef = useRef9(
14351
+ const latestItemsByKey = useRef11(/* @__PURE__ */ new Map());
14352
+ const shouldAnimateMinimizedDockEnterRef = useRef11(
14024
14353
  shouldAnimateMinimizedDockEnter
14025
14354
  );
14026
14355
  latestItemsByKey.current = new Map(items.map((item) => [item.key, item]));
14027
14356
  shouldAnimateMinimizedDockEnterRef.current = shouldAnimateMinimizedDockEnter;
14028
14357
  const itemKeys = items.map((item) => item.key).join("\0");
14029
- const [presentItems, setPresentItems] = useState8(
14358
+ const [presentItems, setPresentItems] = useState10(
14030
14359
  () => items.map((item) => ({
14031
14360
  item,
14032
14361
  key: item.key,
14033
14362
  presence: "present"
14034
14363
  }))
14035
14364
  );
14036
- const initialized = useRef9(false);
14037
- useEffect10(() => {
14365
+ const initialized = useRef11(false);
14366
+ useEffect12(() => {
14038
14367
  let nextSettleMs = dockPresenceAnimationMs;
14039
14368
  setPresentItems((current) => {
14040
14369
  const filteredItems = resolveDockPresenceItems({
@@ -14072,10 +14401,10 @@ function useDockWallpaperTones({
14072
14401
  elementRefs,
14073
14402
  itemKeys
14074
14403
  }) {
14075
- const [tones, setTones] = useState8(
14404
+ const [tones, setTones] = useState10(
14076
14405
  () => /* @__PURE__ */ new Map()
14077
14406
  );
14078
- useLayoutEffect7(() => {
14407
+ useLayoutEffect8(() => {
14079
14408
  if (typeof window === "undefined") {
14080
14409
  return void 0;
14081
14410
  }
@@ -14262,8 +14591,8 @@ function dockWallpaperToneMapsEqual(left, right) {
14262
14591
  var DOCK_BOUNCE_MS = 600;
14263
14592
  var DOCK_ENTRY_CLICK_THROTTLE_MS = DOCK_BOUNCE_MS;
14264
14593
  function useDockBounce(slotRefs) {
14265
- const timeoutsRef = useRef9(/* @__PURE__ */ new Map());
14266
- const clearDockBounce = useCallback12(
14594
+ const timeoutsRef = useRef11(/* @__PURE__ */ new Map());
14595
+ const clearDockBounce = useCallback13(
14267
14596
  (anchorKey) => {
14268
14597
  const timeout = timeoutsRef.current.get(anchorKey);
14269
14598
  const slotElement = slotRefs.current.get(anchorKey);
@@ -14277,7 +14606,7 @@ function useDockBounce(slotRefs) {
14277
14606
  },
14278
14607
  [slotRefs]
14279
14608
  );
14280
- useEffect10(
14609
+ useEffect12(
14281
14610
  () => () => {
14282
14611
  for (const anchorKey of timeoutsRef.current.keys()) {
14283
14612
  clearDockBounce(anchorKey);
@@ -14286,7 +14615,7 @@ function useDockBounce(slotRefs) {
14286
14615
  },
14287
14616
  [clearDockBounce]
14288
14617
  );
14289
- const triggerDockBounce = useCallback12(
14618
+ const triggerDockBounce = useCallback13(
14290
14619
  (anchorKey) => {
14291
14620
  const shouldRestartAnimation = clearDockBounce(anchorKey);
14292
14621
  const slotElement = slotRefs.current.get(anchorKey);
@@ -14495,7 +14824,7 @@ function createWorkbenchHostNodeHeaderContext({
14495
14824
  }
14496
14825
 
14497
14826
  // src/host/WorkbenchHostWindowActions.tsx
14498
- import { jsx as jsx13 } from "react/jsx-runtime";
14827
+ import { jsx as jsx14 } from "react/jsx-runtime";
14499
14828
  function WorkbenchHostWindowActions({
14500
14829
  context,
14501
14830
  host,
@@ -14508,7 +14837,7 @@ function WorkbenchHostWindowActions({
14508
14837
  }
14509
14838
  const minimizable = definition.window?.minimizable !== false;
14510
14839
  const closable = definition.window?.closable !== false;
14511
- return /* @__PURE__ */ jsx13(
14840
+ return /* @__PURE__ */ jsx14(
14512
14841
  WorkbenchWindowTrafficLights,
14513
14842
  {
14514
14843
  close: closable ? {
@@ -14531,11 +14860,11 @@ function WorkbenchHostWindowActions({
14531
14860
  }
14532
14861
 
14533
14862
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
14534
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
14863
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
14535
14864
  function useWorkbenchHostSurfaceRenderers(input) {
14536
- const renderBottomChrome = useMemo10(() => {
14865
+ const renderBottomChrome = useMemo11(() => {
14537
14866
  const renderChrome = input.renderBottomChrome;
14538
- return renderChrome ? () => /* @__PURE__ */ jsx14(
14867
+ return renderChrome ? () => /* @__PURE__ */ jsx15(
14539
14868
  WorkbenchHostSurfaceRenderErrorBoundary,
14540
14869
  {
14541
14870
  debugDiagnostics: input.debugDiagnostics,
@@ -14546,7 +14875,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14546
14875
  fallbackKind: "bottom-chrome",
14547
14876
  resetKey: `${input.workspaceId}:bottom-chrome`,
14548
14877
  workspaceId: input.workspaceId,
14549
- children: /* @__PURE__ */ jsx14(
14878
+ children: /* @__PURE__ */ jsx15(
14550
14879
  WorkbenchHostChromeRenderer,
14551
14880
  {
14552
14881
  context: input.chromeContext,
@@ -14561,9 +14890,9 @@ function useWorkbenchHostSurfaceRenderers(input) {
14561
14890
  input.renderBottomChrome,
14562
14891
  input.workspaceId
14563
14892
  ]);
14564
- const renderTopChrome = useMemo10(() => {
14893
+ const renderTopChrome = useMemo11(() => {
14565
14894
  const renderChrome = input.renderTopChrome;
14566
- return renderChrome ? () => /* @__PURE__ */ jsx14(
14895
+ return renderChrome ? () => /* @__PURE__ */ jsx15(
14567
14896
  WorkbenchHostSurfaceRenderErrorBoundary,
14568
14897
  {
14569
14898
  debugDiagnostics: input.debugDiagnostics,
@@ -14574,7 +14903,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14574
14903
  fallbackKind: "top-chrome",
14575
14904
  resetKey: `${input.workspaceId}:top-chrome`,
14576
14905
  workspaceId: input.workspaceId,
14577
- children: /* @__PURE__ */ jsx14(
14906
+ children: /* @__PURE__ */ jsx15(
14578
14907
  WorkbenchHostChromeRenderer,
14579
14908
  {
14580
14909
  context: input.chromeContext,
@@ -14589,7 +14918,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14589
14918
  input.renderTopChrome,
14590
14919
  input.workspaceId
14591
14920
  ]);
14592
- const captureNodeDefinitionPreviewImage = useCallback13(
14921
+ const captureNodeDefinitionPreviewImage = useCallback14(
14593
14922
  async (node) => {
14594
14923
  const definition = input.nodeDefinitionByType.get(node.data.typeId);
14595
14924
  const minimizedDock = definition?.window?.minimizedDock;
@@ -14618,13 +14947,13 @@ function useWorkbenchHostSurfaceRenderers(input) {
14618
14947
  input.workspaceId
14619
14948
  ]
14620
14949
  );
14621
- const captureNodePreviewImage = useCallback13(
14950
+ const captureNodePreviewImage = useCallback14(
14622
14951
  async (node) => await captureNodeDefinitionPreviewImage(node) ?? await Promise.resolve(
14623
14952
  input.captureNodePreviewImage?.(node) ?? null
14624
14953
  ).catch(() => null),
14625
14954
  [captureNodeDefinitionPreviewImage, input.captureNodePreviewImage]
14626
14955
  );
14627
- const captureNodePreviewImages = useCallback13(
14956
+ const captureNodePreviewImages = useCallback14(
14628
14957
  async (node) => {
14629
14958
  const [images, definitionDockPreviewImageUrl] = await Promise.all([
14630
14959
  Promise.resolve(input.captureNodePreviewImages?.(node) ?? null).catch(
@@ -14652,8 +14981,8 @@ function useWorkbenchHostSurfaceRenderers(input) {
14652
14981
  input.captureNodePreviewImages
14653
14982
  ]
14654
14983
  );
14655
- const renderDock = useCallback13(
14656
- (context) => /* @__PURE__ */ jsx14(
14984
+ const renderDock = useCallback14(
14985
+ (context) => /* @__PURE__ */ jsx15(
14657
14986
  WorkbenchHostSurfaceRenderErrorBoundary,
14658
14987
  {
14659
14988
  debugDiagnostics: input.debugDiagnostics,
@@ -14665,7 +14994,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14665
14994
  fallbackKind: "dock",
14666
14995
  resetKey: `${input.workspaceId}:dock`,
14667
14996
  workspaceId: input.workspaceId,
14668
- children: /* @__PURE__ */ jsx14(
14997
+ children: /* @__PURE__ */ jsx15(
14669
14998
  WorkbenchHostDock,
14670
14999
  {
14671
15000
  captureNodePreviewImage,
@@ -14704,7 +15033,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14704
15033
  input.workspaceId
14705
15034
  ]
14706
15035
  );
14707
- const renderNode = useCallback13(
15036
+ const renderNode = useCallback14(
14708
15037
  (context) => {
14709
15038
  const definition = input.nodeDefinitionByType.get(
14710
15039
  context.node.data.typeId
@@ -14712,7 +15041,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14712
15041
  if (!definition) {
14713
15042
  return null;
14714
15043
  }
14715
- return /* @__PURE__ */ jsx14(
15044
+ return /* @__PURE__ */ jsx15(
14716
15045
  WorkbenchHostNodeRenderer,
14717
15046
  {
14718
15047
  debugDiagnostics: input.debugDiagnostics,
@@ -14732,8 +15061,8 @@ function useWorkbenchHostSurfaceRenderers(input) {
14732
15061
  input.workspaceId
14733
15062
  ]
14734
15063
  );
14735
- const renderWindowActions = useCallback13(
14736
- (context) => /* @__PURE__ */ jsx14(
15064
+ const renderWindowActions = useCallback14(
15065
+ (context) => /* @__PURE__ */ jsx15(
14737
15066
  WorkbenchHostWindowActions,
14738
15067
  {
14739
15068
  context,
@@ -14744,7 +15073,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14744
15073
  ),
14745
15074
  [input.hostI18n, input.hostSession, input.nodeDefinitionByType]
14746
15075
  );
14747
- const renderWindowHeader = useCallback13(
15076
+ const renderWindowHeader = useCallback14(
14748
15077
  (context) => {
14749
15078
  const definition = input.nodeDefinitionByType.get(
14750
15079
  context.node.data.typeId
@@ -14752,7 +15081,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14752
15081
  if (!definition?.renderHeader) {
14753
15082
  return null;
14754
15083
  }
14755
- return /* @__PURE__ */ jsx14(
15084
+ return /* @__PURE__ */ jsx15(
14756
15085
  MemoizedWorkbenchHostNodeHeaderStateBridge,
14757
15086
  {
14758
15087
  context,
@@ -14770,18 +15099,18 @@ function useWorkbenchHostSurfaceRenderers(input) {
14770
15099
  input.workspaceId
14771
15100
  ]
14772
15101
  );
14773
- const shouldKeepMinimizedNodeMounted = useCallback13(
15102
+ const shouldKeepMinimizedNodeMounted = useCallback14(
14774
15103
  (node) => {
14775
15104
  const capability = input.nodeDefinitionByType.get(node.data.typeId)?.window?.keepMountedWhenMinimized;
14776
15105
  return typeof capability === "function" ? capability(node) : capability === true;
14777
15106
  },
14778
15107
  [input.nodeDefinitionByType]
14779
15108
  );
14780
- const shouldCaptureNodePreviewImage = useCallback13(
15109
+ const shouldCaptureNodePreviewImage = useCallback14(
14781
15110
  (_node) => true,
14782
15111
  []
14783
15112
  );
14784
- const renderNodeGeniePreview = useCallback13(
15113
+ const renderNodeGeniePreview = useCallback14(
14785
15114
  (node, {
14786
15115
  previewViewport
14787
15116
  }) => {
@@ -14815,7 +15144,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14815
15144
  input.workspaceId
14816
15145
  ]
14817
15146
  );
14818
- const resolveDockAnchorKey = useCallback13(
15147
+ const resolveDockAnchorKey = useCallback14(
14819
15148
  (node) => {
14820
15149
  if (node.isMinimized && isWorkbenchMinimizedDockEligibleNode({
14821
15150
  node,
@@ -14848,7 +15177,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
14848
15177
  },
14849
15178
  [input.dockEntries, input.hostSession, input.nodeDefinitionByType]
14850
15179
  );
14851
- const resolveDockPreviewCacheKey2 = useCallback13(
15180
+ const resolveDockPreviewCacheKey2 = useCallback14(
14852
15181
  (node) => ({
14853
15182
  instanceId: node.data.instanceId,
14854
15183
  instanceKey: node.data.instanceKey ?? null,
@@ -14858,20 +15187,20 @@ function useWorkbenchHostSurfaceRenderers(input) {
14858
15187
  }),
14859
15188
  [input.workspaceId]
14860
15189
  );
14861
- const windowChromeMode = useCallback13(
15190
+ const windowChromeMode = useCallback14(
14862
15191
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.renderHeader ? "custom-header" : "system",
14863
15192
  [input.nodeDefinitionByType]
14864
15193
  );
14865
- const resolveWindowZIndex = useCallback13(({ baseZIndex }) => baseZIndex, []);
14866
- const resolveWindowSurfaceLayer = useCallback13(
15194
+ const resolveWindowZIndex = useCallback14(({ baseZIndex }) => baseZIndex, []);
15195
+ const resolveWindowSurfaceLayer = useCallback14(
14867
15196
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.surfaceLayer ?? "default",
14868
15197
  [input.nodeDefinitionByType]
14869
15198
  );
14870
- const resolveFullscreenHeaderMode = useCallback13(
15199
+ const resolveFullscreenHeaderMode = useCallback14(
14871
15200
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.fullscreenHeaderMode,
14872
15201
  [input.nodeDefinitionByType]
14873
15202
  );
14874
- const resolveWindowHeaderPresentation = useCallback13(
15203
+ const resolveWindowHeaderPresentation = useCallback14(
14875
15204
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.header,
14876
15205
  [input.nodeDefinitionByType]
14877
15206
  );
@@ -14912,7 +15241,7 @@ function WorkbenchHostNodeRenderer(input) {
14912
15241
  isVisible,
14913
15242
  workspaceId: input.workspaceId
14914
15243
  });
14915
- const resetKey = useMemo10(
15244
+ const resetKey = useMemo11(
14916
15245
  () => [
14917
15246
  input.context.node.id,
14918
15247
  input.context.node.data.typeId,
@@ -14926,7 +15255,7 @@ function WorkbenchHostNodeRenderer(input) {
14926
15255
  input.context.node.id
14927
15256
  ]
14928
15257
  );
14929
- return /* @__PURE__ */ jsx14(
15258
+ return /* @__PURE__ */ jsx15(
14930
15259
  WorkbenchHostNodeRenderErrorBoundary,
14931
15260
  {
14932
15261
  debugDiagnostics: input.debugDiagnostics,
@@ -14937,7 +15266,7 @@ function WorkbenchHostNodeRenderer(input) {
14937
15266
  }),
14938
15267
  resetKey,
14939
15268
  workspaceId: input.workspaceId,
14940
- children: /* @__PURE__ */ jsx14(
15269
+ children: /* @__PURE__ */ jsx15(
14941
15270
  MemoizedWorkbenchHostNodeBodyRenderer,
14942
15271
  {
14943
15272
  context: bodyContext,
@@ -14962,7 +15291,7 @@ function WorkbenchHostNodeHeaderStateBridge(input) {
14962
15291
  workspaceId: input.workspaceId
14963
15292
  });
14964
15293
  const getFrameRenderKey = input.definition.getHeaderFrameRenderKey;
14965
- return /* @__PURE__ */ jsx14(
15294
+ return /* @__PURE__ */ jsx15(
14966
15295
  MemoizedWorkbenchHostNodeHeaderRenderer,
14967
15296
  {
14968
15297
  context,
@@ -15039,7 +15368,7 @@ var WorkbenchHostSurfaceRenderErrorBoundary = class extends Component {
15039
15368
  }
15040
15369
  render() {
15041
15370
  if (this.state.hasError) {
15042
- return /* @__PURE__ */ jsx14(
15371
+ return /* @__PURE__ */ jsx15(
15043
15372
  "div",
15044
15373
  {
15045
15374
  "data-workbench-surface-render-error": this.props.fallbackKind,
@@ -15098,7 +15427,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
15098
15427
  }
15099
15428
  render() {
15100
15429
  if (this.state.hasError) {
15101
- return /* @__PURE__ */ jsxs10(
15430
+ return /* @__PURE__ */ jsxs11(
15102
15431
  "div",
15103
15432
  {
15104
15433
  "data-workbench-node-render-error": "true",
@@ -15116,7 +15445,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
15116
15445
  width: "100%"
15117
15446
  },
15118
15447
  children: [
15119
- /* @__PURE__ */ jsx14(
15448
+ /* @__PURE__ */ jsx15(
15120
15449
  "div",
15121
15450
  {
15122
15451
  "data-workbench-node-render-error-message": "true",
@@ -15128,8 +15457,8 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
15128
15457
  children: "This workspace view failed to render."
15129
15458
  }
15130
15459
  ),
15131
- /* @__PURE__ */ jsx14("div", { style: { fontSize: 12 }, children: "Try selecting another conversation or reopen the window." }),
15132
- /* @__PURE__ */ jsx14(
15460
+ /* @__PURE__ */ jsx15("div", { style: { fontSize: 12 }, children: "Try selecting another conversation or reopen the window." }),
15461
+ /* @__PURE__ */ jsx15(
15133
15462
  "button",
15134
15463
  {
15135
15464
  type: "button",
@@ -15166,7 +15495,7 @@ function WorkbenchHostChromeRenderer({
15166
15495
  }
15167
15496
 
15168
15497
  // src/host/WorkbenchHost.tsx
15169
- import { jsx as jsx15 } from "react/jsx-runtime";
15498
+ import { jsx as jsx16 } from "react/jsx-runtime";
15170
15499
  var noop3 = () => {
15171
15500
  };
15172
15501
  function WorkbenchHost({
@@ -15202,7 +15531,7 @@ function WorkbenchHost({
15202
15531
  windowManagement,
15203
15532
  workspaceId
15204
15533
  }) {
15205
- const hostRuntimeConfig = useMemo11(
15534
+ const hostRuntimeConfig = useMemo12(
15206
15535
  () => resolveWorkbenchHostRuntimeConfig({
15207
15536
  contributions,
15208
15537
  externalStateSource,
@@ -15218,7 +15547,7 @@ function WorkbenchHost({
15218
15547
  onNodeCloseRequest
15219
15548
  ]
15220
15549
  );
15221
- const hostDockEntries = useMemo11(
15550
+ const hostDockEntries = useMemo12(
15222
15551
  () => resolveWorkbenchHostDockEntries({
15223
15552
  contributions,
15224
15553
  dockEntryPresentationOverrides,
@@ -15283,7 +15612,7 @@ function WorkbenchHost({
15283
15612
  });
15284
15613
  const missionControlPresence = useWorkbenchMissionControlPresence(missionControlState);
15285
15614
  const missionControlRenderedState = missionControlPresence.state;
15286
- return /* @__PURE__ */ jsx15(
15615
+ return /* @__PURE__ */ jsx16(
15287
15616
  WorkbenchSurface,
15288
15617
  {
15289
15618
  className,
@@ -15298,7 +15627,7 @@ function WorkbenchHost({
15298
15627
  missionControlPhase: missionControlPresence.phase,
15299
15628
  minimizeAnimation,
15300
15629
  presentation: missionControlState?.presentation ?? null,
15301
- renderBackdrop: missionControlRenderedState ? () => /* @__PURE__ */ jsx15(
15630
+ renderBackdrop: missionControlRenderedState ? () => /* @__PURE__ */ jsx16(
15302
15631
  WorkbenchMissionControlBackdrop,
15303
15632
  {
15304
15633
  onExitTransitionComplete: () => missionControlPresence.completeExitTransition(),
@@ -15309,7 +15638,7 @@ function WorkbenchHost({
15309
15638
  renderDock: surfaceRenderers.renderDock,
15310
15639
  renderNode: surfaceRenderers.renderNode,
15311
15640
  renderNodeGeniePreview: surfaceRenderers.renderNodeGeniePreview,
15312
- renderOverlay: missionControlRenderedState ? () => /* @__PURE__ */ jsx15(
15641
+ renderOverlay: missionControlRenderedState ? () => /* @__PURE__ */ jsx16(
15313
15642
  WorkbenchMissionControlOverlay,
15314
15643
  {
15315
15644
  i18n: missionControlI18n,
@@ -15338,7 +15667,7 @@ function WorkbenchHost({
15338
15667
  }
15339
15668
 
15340
15669
  // src/react/WorkbenchDockComponentPreviewFrame.tsx
15341
- import { jsx as jsx16 } from "react/jsx-runtime";
15670
+ import { jsx as jsx17 } from "react/jsx-runtime";
15342
15671
  function WorkbenchDockComponentPreviewFrame({
15343
15672
  children,
15344
15673
  sourceSize,
@@ -15374,13 +15703,13 @@ function WorkbenchDockComponentPreviewFrame({
15374
15703
  transformOrigin: "center",
15375
15704
  width: `${sourceWidth}px`
15376
15705
  };
15377
- return /* @__PURE__ */ jsx16(
15706
+ return /* @__PURE__ */ jsx17(
15378
15707
  "span",
15379
15708
  {
15380
15709
  "aria-hidden": "true",
15381
15710
  "data-workbench-dock-component-preview-frame": "true",
15382
15711
  style: frameStyle,
15383
- children: /* @__PURE__ */ jsx16(
15712
+ children: /* @__PURE__ */ jsx17(
15384
15713
  "span",
15385
15714
  {
15386
15715
  "data-workbench-dock-component-preview-content": "true",
@@ -15393,21 +15722,43 @@ function WorkbenchDockComponentPreviewFrame({
15393
15722
  }
15394
15723
 
15395
15724
  // src/core/visualOcclusion.ts
15725
+ var noNodeIDs = /* @__PURE__ */ new Set();
15726
+ var defaultVisualOcclusionPresentation = {
15727
+ hiddenNodeIDs: noNodeIDs,
15728
+ nonOccludingNodeIDs: noNodeIDs,
15729
+ topLayerNodeIDs: []
15730
+ };
15396
15731
  var exposedNodeIDsByState = /* @__PURE__ */ new WeakMap();
15397
- function selectVisuallyExposedWorkbenchNodeIDs(state) {
15398
- const cached = exposedNodeIDsByState.get(state);
15399
- if (cached) {
15400
- return cached;
15732
+ var exposedNodeIDsByNodeStack = /* @__PURE__ */ new WeakMap();
15733
+ function selectVisuallyExposedWorkbenchNodeIDs(state, presentation = defaultVisualOcclusionPresentation) {
15734
+ const cachedByState = exposedNodeIDsByState.get(state);
15735
+ if (cachedByState?.presentation === presentation) {
15736
+ return cachedByState.exposedNodeIDs;
15737
+ }
15738
+ const cachedByGeometry = exposedNodeIDsByNodeStack.get(state.nodeStack);
15739
+ if (cachedByGeometry && cachedByGeometry.presentation === presentation && hasEquivalentVisualOcclusionGeometry(cachedByGeometry, state)) {
15740
+ cachedByGeometry.nodes = state.nodes;
15741
+ cachedByGeometry.surfaceSize = state.surfaceSize;
15742
+ exposedNodeIDsByState.set(state, {
15743
+ exposedNodeIDs: cachedByGeometry.exposedNodeIDs,
15744
+ presentation
15745
+ });
15746
+ return cachedByGeometry.exposedNodeIDs;
15401
15747
  }
15402
15748
  const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
15403
15749
  const stackedIDs = new Set(state.nodeStack);
15404
- const orderedNodes = [
15750
+ const stackOrderedNodes = [
15405
15751
  ...state.nodes.filter((node) => !stackedIDs.has(node.id)),
15406
15752
  ...state.nodeStack.flatMap((nodeID) => {
15407
15753
  const node = nodeByID.get(nodeID);
15408
15754
  return node ? [node] : [];
15409
15755
  })
15410
15756
  ];
15757
+ const topLayerNodeIDs = new Set(presentation.topLayerNodeIDs);
15758
+ const orderedNodes = topLayerNodeIDs.size === 0 ? stackOrderedNodes : [
15759
+ ...stackOrderedNodes.filter((node) => !topLayerNodeIDs.has(node.id)),
15760
+ ...stackOrderedNodes.filter((node) => topLayerNodeIDs.has(node.id))
15761
+ ];
15411
15762
  const surfaceFrame = {
15412
15763
  x: 0,
15413
15764
  y: 0,
@@ -15416,7 +15767,7 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15416
15767
  };
15417
15768
  const exposedNodeIDs = /* @__PURE__ */ new Set();
15418
15769
  orderedNodes.forEach((node, nodeIndex) => {
15419
- if (node.isMinimized) {
15770
+ if (node.isMinimized || presentation.hiddenNodeIDs.has(node.id)) {
15420
15771
  return;
15421
15772
  }
15422
15773
  const visibleFrame = intersectFrames(node.frame, surfaceFrame);
@@ -15426,7 +15777,7 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15426
15777
  let uncoveredFrames = [visibleFrame];
15427
15778
  for (let occluderIndex = nodeIndex + 1; occluderIndex < orderedNodes.length && uncoveredFrames.length > 0; occluderIndex += 1) {
15428
15779
  const occluder = orderedNodes[occluderIndex];
15429
- if (!occluder || occluder.isMinimized) {
15780
+ if (!occluder || occluder.isMinimized || presentation.hiddenNodeIDs.has(occluder.id) || presentation.nonOccludingNodeIDs.has(occluder.id)) {
15430
15781
  continue;
15431
15782
  }
15432
15783
  uncoveredFrames = uncoveredFrames.flatMap(
@@ -15437,11 +15788,20 @@ function selectVisuallyExposedWorkbenchNodeIDs(state) {
15437
15788
  exposedNodeIDs.add(node.id);
15438
15789
  }
15439
15790
  });
15440
- exposedNodeIDsByState.set(state, exposedNodeIDs);
15791
+ exposedNodeIDsByState.set(state, {
15792
+ exposedNodeIDs,
15793
+ presentation
15794
+ });
15795
+ exposedNodeIDsByNodeStack.set(state.nodeStack, {
15796
+ exposedNodeIDs,
15797
+ nodes: state.nodes,
15798
+ presentation,
15799
+ surfaceSize: state.surfaceSize
15800
+ });
15441
15801
  return exposedNodeIDs;
15442
15802
  }
15443
- function selectWorkbenchNodeIsVisuallyExposed(state, nodeID) {
15444
- return selectVisuallyExposedWorkbenchNodeIDs(state).has(nodeID);
15803
+ function selectWorkbenchNodeIsVisuallyExposed(state, nodeID, presentation) {
15804
+ return selectVisuallyExposedWorkbenchNodeIDs(state, presentation).has(nodeID);
15445
15805
  }
15446
15806
  function intersectFrames(left, right) {
15447
15807
  const x = Math.max(left.x, right.x);
@@ -15505,6 +15865,18 @@ function pushFrame(frames, frame) {
15505
15865
  frames.push(frame);
15506
15866
  }
15507
15867
  }
15868
+ function hasEquivalentVisualOcclusionGeometry(cached, state) {
15869
+ if (cached.surfaceSize.width !== state.surfaceSize.width || cached.surfaceSize.height !== state.surfaceSize.height || cached.nodes.length !== state.nodes.length) {
15870
+ return false;
15871
+ }
15872
+ if (cached.nodes === state.nodes) {
15873
+ return true;
15874
+ }
15875
+ return cached.nodes.every((cachedNode, index) => {
15876
+ const node = state.nodes[index];
15877
+ 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;
15878
+ });
15879
+ }
15508
15880
  export {
15509
15881
  WorkbenchDockComponentPreviewFrame,
15510
15882
  WorkbenchHost,
@@ -15534,6 +15906,7 @@ export {
15534
15906
  selectVisuallyExposedWorkbenchNodeIDs,
15535
15907
  selectWorkbenchNodeIsVisuallyExposed,
15536
15908
  useWorkbenchSelector,
15909
+ useWorkbenchVisualOcclusionPresentation,
15537
15910
  workbenchFocusInputActivationType,
15538
15911
  workbenchHostI18nResources,
15539
15912
  workbenchWindowChromeI18nNamespace,