@tutti-os/workbench-surface 0.0.74 → 0.0.76

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
@@ -5,7 +5,7 @@ import {
5
5
  workbenchHostI18nResources,
6
6
  workbenchWindowChromeI18nNamespace,
7
7
  workbenchWindowChromeI18nResources
8
- } from "./chunk-B5MSA47V.js";
8
+ } from "./chunk-TIMYSQM7.js";
9
9
 
10
10
  // src/store/commands.ts
11
11
  function createWorkbenchCommands(store) {
@@ -40,12 +40,21 @@ function createWorkbenchCommands(store) {
40
40
  applyQuickLayout(nodeID, target) {
41
41
  store.dispatch({ type: "applyQuickLayout", nodeID, target });
42
42
  },
43
- applyLayoutPreset(nodeIDs, preset) {
44
- store.dispatch({ type: "applyLayoutPreset", nodeIDs, preset });
43
+ applyLayoutPreset(nodeIDs, preset, lock) {
44
+ store.dispatch({ type: "applyLayoutPreset", nodeIDs, preset, lock });
45
45
  },
46
46
  applyVisibleLayoutPreset(preset) {
47
47
  store.dispatch({ type: "applyVisibleLayoutPreset", preset });
48
48
  },
49
+ settleLockedDrag(nodeID) {
50
+ store.dispatch({ type: "settleLockedDrag", nodeID });
51
+ },
52
+ moveLockedNode(nodeID, direction) {
53
+ store.dispatch({ type: "moveLockedNode", nodeID, direction });
54
+ },
55
+ releaseLockedLayout() {
56
+ store.dispatch({ type: "releaseLockedLayout" });
57
+ },
49
58
  applyActiveSnapTarget(nodeID) {
50
59
  store.dispatch({ type: "applyActiveSnapTarget", nodeID });
51
60
  },
@@ -400,6 +409,57 @@ function getWorkbenchLayoutPresetFrames(itemCount, preset, surfaceSize, constrai
400
409
  return getSingleColumnLayoutFrames(itemCount, frame, normalized);
401
410
  }
402
411
  }
412
+ function normalizeWorkbenchFrameToRect(frame, rect) {
413
+ const width = Math.max(rect.width, 1);
414
+ const height = Math.max(rect.height, 1);
415
+ return {
416
+ x: (frame.x - rect.x) / width,
417
+ y: (frame.y - rect.y) / height,
418
+ width: frame.width / width,
419
+ height: frame.height / height
420
+ };
421
+ }
422
+ function denormalizeWorkbenchFrameFromRect(normalized, rect) {
423
+ return {
424
+ x: rect.x + normalized.x * rect.width,
425
+ y: rect.y + normalized.y * rect.height,
426
+ width: normalized.width * rect.width,
427
+ height: normalized.height * rect.height
428
+ };
429
+ }
430
+ function getWorkbenchLockedSlotFrames(lockedLayout, surfaceSize, constraints = defaultWorkbenchLayoutConstraints) {
431
+ if (!lockedLayout || lockedLayout.nodeIDs.length < 2) {
432
+ return null;
433
+ }
434
+ const normalizedFrames = lockedLayout.normalizedFrames;
435
+ if (normalizedFrames) {
436
+ const rect = getWorkbenchSafeLayoutRect(surfaceSize, constraints);
437
+ const slots = [];
438
+ for (const nodeID of lockedLayout.nodeIDs) {
439
+ const normalized = normalizedFrames[nodeID];
440
+ if (normalized) {
441
+ slots.push({
442
+ nodeID,
443
+ frame: denormalizeWorkbenchFrameFromRect(normalized, rect)
444
+ });
445
+ }
446
+ }
447
+ return slots.length >= 2 ? slots : null;
448
+ }
449
+ const frames = getWorkbenchLayoutPresetFrames(
450
+ lockedLayout.nodeIDs.length,
451
+ lockedLayout.preset,
452
+ surfaceSize,
453
+ constraints
454
+ );
455
+ if (!frames) {
456
+ return null;
457
+ }
458
+ return lockedLayout.nodeIDs.map((nodeID, index) => ({
459
+ nodeID,
460
+ frame: frames[index]
461
+ }));
462
+ }
403
463
  function getWorkbenchSafeLayoutRect(surfaceSize, constraints = defaultWorkbenchLayoutConstraints) {
404
464
  const normalized = normalizeWorkbenchLayoutConstraints(constraints);
405
465
  const frame = getWorkbenchLayoutFrame(surfaceSize, normalized);
@@ -595,7 +655,8 @@ function createWorkbenchInitialState(partial = {}) {
595
655
  surfaceSize: partial.surfaceSize ?? defaultWorkbenchSurfaceSize,
596
656
  layoutConstraints: normalizeWorkbenchLayoutConstraints(
597
657
  partial.layoutConstraints ?? defaultWorkbenchLayoutConstraints
598
- )
658
+ ),
659
+ lockedLayout: partial.lockedLayout ?? null
599
660
  };
600
661
  }
601
662
  function reduceWorkbenchState(state, action) {
@@ -605,7 +666,7 @@ function reduceWorkbenchState(state, action) {
605
666
  ...state,
606
667
  ...action.state
607
668
  });
608
- if (state.nodes === nextState.nodes && state.nodeStack === nextState.nodeStack && state.activeDragNodeId === nextState.activeDragNodeId && state.activeResizeNodeId === nextState.activeResizeNodeId && state.activeSnapTarget === nextState.activeSnapTarget && state.surfaceSize === nextState.surfaceSize && layoutConstraintsEqual(
669
+ if (state.nodes === nextState.nodes && state.nodeStack === nextState.nodeStack && state.activeDragNodeId === nextState.activeDragNodeId && state.activeResizeNodeId === nextState.activeResizeNodeId && state.activeSnapTarget === nextState.activeSnapTarget && state.surfaceSize === nextState.surfaceSize && state.lockedLayout === nextState.lockedLayout && layoutConstraintsEqual(
609
670
  state.layoutConstraints,
610
671
  nextState.layoutConstraints
611
672
  )) {
@@ -625,7 +686,7 @@ function reduceWorkbenchState(state, action) {
625
686
  const nodes = existing ? state.nodes.map(
626
687
  (node) => node.id === action.node.id ? action.node : node
627
688
  ) : [...state.nodes, action.node];
628
- return {
689
+ const openedState = {
629
690
  ...state,
630
691
  nodes,
631
692
  nodeStack: focusWorkbenchStack(
@@ -633,6 +694,18 @@ function reduceWorkbenchState(state, action) {
633
694
  action.node.id
634
695
  )
635
696
  };
697
+ if (!existing && state.lockedLayout) {
698
+ const grownState = applyLayoutPresetToNodes(
699
+ openedState,
700
+ [...state.lockedLayout.nodeIDs, action.node.id],
701
+ state.lockedLayout.preset,
702
+ { lock: true, reorderStack: false }
703
+ );
704
+ if (grownState !== openedState) {
705
+ return grownState;
706
+ }
707
+ }
708
+ return openedState;
636
709
  }
637
710
  case "closeNode":
638
711
  if (!state.nodes.some((node) => node.id === action.nodeID)) {
@@ -641,7 +714,8 @@ function reduceWorkbenchState(state, action) {
641
714
  return {
642
715
  ...state,
643
716
  nodes: state.nodes.filter((node) => node.id !== action.nodeID),
644
- nodeStack: removeFromWorkbenchStack(state.nodeStack, action.nodeID)
717
+ nodeStack: removeFromWorkbenchStack(state.nodeStack, action.nodeID),
718
+ lockedLayout: pruneLockedLayout(state.lockedLayout, action.nodeID)
645
719
  };
646
720
  case "focusNode":
647
721
  if (!state.nodes.some((node) => node.id === action.nodeID)) {
@@ -721,13 +795,25 @@ function reduceWorkbenchState(state, action) {
721
795
  };
722
796
  });
723
797
  case "applyLayoutPreset":
724
- return applyLayoutPresetToNodes(state, action.nodeIDs, action.preset);
798
+ return applyLayoutPresetToNodes(state, action.nodeIDs, action.preset, {
799
+ lock: action.lock ?? false
800
+ });
725
801
  case "applyVisibleLayoutPreset":
726
802
  return applyLayoutPresetToNodes(
727
803
  state,
728
804
  state.nodes.filter((node) => !node.isMinimized).map((node) => node.id),
729
- action.preset
805
+ action.preset,
806
+ { lock: false }
730
807
  );
808
+ case "settleLockedDrag":
809
+ return settleLockedDrag(state, action.nodeID);
810
+ case "moveLockedNode":
811
+ return moveLockedNode(state, action.nodeID, action.direction);
812
+ case "releaseLockedLayout":
813
+ if (state.lockedLayout === null) {
814
+ return state;
815
+ }
816
+ return { ...state, lockedLayout: null };
731
817
  case "applyActiveSnapTarget":
732
818
  case "applySnapTarget":
733
819
  return updateNode(state, action.nodeID, (node) => {
@@ -752,8 +838,8 @@ function reduceWorkbenchState(state, action) {
752
838
  minimizedAtUnixMs: null
753
839
  };
754
840
  });
755
- case "dragNode":
756
- return updateNode(state, action.nodeID, (node) => {
841
+ case "dragNode": {
842
+ const draggedState = updateNode(state, action.nodeID, (node) => {
757
843
  const frame = clampWorkbenchDragRect(
758
844
  action.frame,
759
845
  state.surfaceSize,
@@ -770,25 +856,37 @@ function reduceWorkbenchState(state, action) {
770
856
  restoreFrame: node.displayMode === "fullscreen" ? node.restoreFrame : null
771
857
  };
772
858
  });
859
+ if (isLockedLayoutNode(state, action.nodeID)) {
860
+ return draggedState;
861
+ }
862
+ return releaseLockedLayout(state, draggedState);
863
+ }
773
864
  case "moveNode":
774
- case "resizeNode":
775
- return updateNode(state, action.nodeID, (node) => {
776
- const frame = clampWorkbenchRect(
777
- action.frame,
778
- state.surfaceSize,
779
- state.layoutConstraints,
780
- node.sizeConstraints
781
- );
782
- if (rectsEqual(node.frame, frame)) {
783
- return node;
784
- }
785
- return {
786
- ...node,
787
- frame,
788
- displayMode: "floating",
789
- restoreFrame: node.displayMode === "fullscreen" ? node.restoreFrame : null
790
- };
791
- });
865
+ case "resizeNode": {
866
+ if (action.type === "resizeNode" && isLockedLayoutNode(state, action.nodeID)) {
867
+ return resizeLockedGrid(state, action.nodeID, action.frame);
868
+ }
869
+ return releaseLockedLayout(
870
+ state,
871
+ updateNode(state, action.nodeID, (node) => {
872
+ const frame = clampWorkbenchRect(
873
+ action.frame,
874
+ state.surfaceSize,
875
+ state.layoutConstraints,
876
+ node.sizeConstraints
877
+ );
878
+ if (rectsEqual(node.frame, frame)) {
879
+ return node;
880
+ }
881
+ return {
882
+ ...node,
883
+ frame,
884
+ displayMode: "floating",
885
+ restoreFrame: node.displayMode === "fullscreen" ? node.restoreFrame : null
886
+ };
887
+ })
888
+ );
889
+ }
792
890
  case "setActiveDragNode":
793
891
  if (state.activeDragNodeId === action.nodeID) {
794
892
  return state;
@@ -804,11 +902,11 @@ function reduceWorkbenchState(state, action) {
804
902
  return state;
805
903
  }
806
904
  return { ...state, activeSnapTarget: action.snapTarget };
807
- case "setSurfaceSize":
905
+ case "setSurfaceSize": {
808
906
  if (state.surfaceSize.width === action.size.width && state.surfaceSize.height === action.size.height) {
809
907
  return state;
810
908
  }
811
- return {
909
+ const resizedState = {
812
910
  ...state,
813
911
  surfaceSize: action.size,
814
912
  nodes: state.nodes.map(
@@ -831,6 +929,19 @@ function reduceWorkbenchState(state, action) {
831
929
  }
832
930
  )
833
931
  };
932
+ if (state.lockedLayout && state.lockedLayout.nodeIDs.length >= 2) {
933
+ if (state.lockedLayout.normalizedFrames) {
934
+ return materializeLockedFrames(resizedState, state.lockedLayout);
935
+ }
936
+ return applyLayoutPresetToNodes(
937
+ resizedState,
938
+ state.lockedLayout.nodeIDs,
939
+ state.lockedLayout.preset,
940
+ { lock: true, reorderStack: false }
941
+ );
942
+ }
943
+ return resizedState;
944
+ }
834
945
  case "setLayoutConstraints": {
835
946
  const constraints = normalizeWorkbenchLayoutConstraints({
836
947
  ...state.layoutConstraints,
@@ -931,7 +1042,7 @@ function updateNode(state, nodeID, update) {
931
1042
  nodeStack: focusWorkbenchStack(state.nodeStack, nodeID)
932
1043
  };
933
1044
  }
934
- function applyLayoutPresetToNodes(state, inputNodeIDs, preset) {
1045
+ function applyLayoutPresetToNodes(state, inputNodeIDs, preset, options) {
935
1046
  const nodeIDs = uniqueKnownNodeIDs(state.nodes, inputNodeIDs);
936
1047
  if (nodeIDs.length === 0) {
937
1048
  return state;
@@ -969,10 +1080,306 @@ function applyLayoutPresetToNodes(state, inputNodeIDs, preset) {
969
1080
  };
970
1081
  });
971
1082
  let nodeStack = state.nodeStack;
972
- for (const nodeID of nodeIDs) {
973
- nodeStack = focusWorkbenchStack(nodeStack, nodeID);
1083
+ if (options.reorderStack !== false) {
1084
+ for (const nodeID of nodeIDs) {
1085
+ nodeStack = focusWorkbenchStack(nodeStack, nodeID);
1086
+ }
1087
+ }
1088
+ const lockedLayout = options.lock ? { preset, nodeIDs } : null;
1089
+ return { ...state, nodes, nodeStack, lockedLayout };
1090
+ }
1091
+ function isLockedLayoutNode(state, nodeID) {
1092
+ return state.lockedLayout?.nodeIDs.includes(nodeID) ?? false;
1093
+ }
1094
+ function settleLockedDrag(state, nodeID) {
1095
+ const lockedLayout = state.lockedLayout;
1096
+ if (!lockedLayout || !lockedLayout.nodeIDs.includes(nodeID)) {
1097
+ return state;
1098
+ }
1099
+ const draggedNode = state.nodes.find((node) => node.id === nodeID);
1100
+ if (!draggedNode) {
1101
+ return state;
1102
+ }
1103
+ const draggedCenter = {
1104
+ x: draggedNode.frame.x + draggedNode.frame.width / 2,
1105
+ y: draggedNode.frame.y + draggedNode.frame.height / 2
1106
+ };
1107
+ const targetNode = state.nodes.find(
1108
+ (node) => node.id !== nodeID && !node.isMinimized && lockedLayout.nodeIDs.includes(node.id) && frameContainsPoint(node.frame, draggedCenter)
1109
+ );
1110
+ return applyLockedArrangement(
1111
+ state,
1112
+ lockedLayout,
1113
+ targetNode ? { firstID: nodeID, secondID: targetNode.id } : null
1114
+ );
1115
+ }
1116
+ function moveLockedNode(state, nodeID, direction) {
1117
+ const lockedLayout = state.lockedLayout;
1118
+ if (!lockedLayout || !lockedLayout.nodeIDs.includes(nodeID)) {
1119
+ return state;
1120
+ }
1121
+ const sourceNode = state.nodes.find((node) => node.id === nodeID);
1122
+ if (!sourceNode) {
1123
+ return state;
1124
+ }
1125
+ const sourceCenter = frameCenter(sourceNode.frame);
1126
+ let targetID = null;
1127
+ let bestScore = Number.POSITIVE_INFINITY;
1128
+ for (const node of state.nodes) {
1129
+ if (node.id === nodeID || node.isMinimized || !lockedLayout.nodeIDs.includes(node.id)) {
1130
+ continue;
1131
+ }
1132
+ const center = frameCenter(node.frame);
1133
+ const dx = center.x - sourceCenter.x;
1134
+ const dy = center.y - sourceCenter.y;
1135
+ const primary = direction === "left" ? -dx : direction === "right" ? dx : direction === "up" ? -dy : dy;
1136
+ if (primary <= 0.5) {
1137
+ continue;
1138
+ }
1139
+ const secondary = direction === "left" || direction === "right" ? Math.abs(dy) : Math.abs(dx);
1140
+ const score = primary + secondary * 2;
1141
+ if (score < bestScore) {
1142
+ bestScore = score;
1143
+ targetID = node.id;
1144
+ }
1145
+ }
1146
+ if (targetID === null) {
1147
+ return state;
1148
+ }
1149
+ return applyLockedArrangement(state, lockedLayout, {
1150
+ firstID: nodeID,
1151
+ secondID: targetID
1152
+ });
1153
+ }
1154
+ function applyLockedArrangement(state, lockedLayout, swap) {
1155
+ const nodeIDs = swap ? swapNodeIDs(lockedLayout.nodeIDs, swap.firstID, swap.secondID) : lockedLayout.nodeIDs;
1156
+ if (lockedLayout.normalizedFrames) {
1157
+ let normalizedFrames = lockedLayout.normalizedFrames;
1158
+ if (swap) {
1159
+ const first = normalizedFrames[swap.firstID];
1160
+ const second = normalizedFrames[swap.secondID];
1161
+ if (first && second) {
1162
+ normalizedFrames = {
1163
+ ...normalizedFrames,
1164
+ [swap.firstID]: second,
1165
+ [swap.secondID]: first
1166
+ };
1167
+ }
1168
+ }
1169
+ return materializeLockedFrames(state, {
1170
+ ...lockedLayout,
1171
+ nodeIDs,
1172
+ normalizedFrames
1173
+ });
1174
+ }
1175
+ return applyLayoutPresetToNodes(state, nodeIDs, lockedLayout.preset, {
1176
+ lock: true,
1177
+ reorderStack: false
1178
+ });
1179
+ }
1180
+ function materializeLockedFrames(state, lockedLayout) {
1181
+ const normalizedFrames = lockedLayout.normalizedFrames;
1182
+ if (!normalizedFrames) {
1183
+ return { ...state, lockedLayout };
1184
+ }
1185
+ const layoutRect = getWorkbenchSafeLayoutRect(
1186
+ state.surfaceSize,
1187
+ state.layoutConstraints
1188
+ );
1189
+ const lockedNodeIDs = new Set(lockedLayout.nodeIDs);
1190
+ const nodes = state.nodes.map((node) => {
1191
+ const normalized = normalizedFrames[node.id];
1192
+ if (!normalized || !lockedNodeIDs.has(node.id)) {
1193
+ return node;
1194
+ }
1195
+ const frame = clampWorkbenchRect(
1196
+ denormalizeWorkbenchFrameFromRect(normalized, layoutRect),
1197
+ state.surfaceSize,
1198
+ state.layoutConstraints,
1199
+ node.sizeConstraints
1200
+ );
1201
+ if (node.displayMode === "floating" && !node.isMinimized && node.restoreFrame === null && rectsEqual(node.frame, frame)) {
1202
+ return node;
1203
+ }
1204
+ return {
1205
+ ...node,
1206
+ frame,
1207
+ displayMode: "floating",
1208
+ restoreFrame: null,
1209
+ isMinimized: false,
1210
+ minimizedAtUnixMs: null
1211
+ };
1212
+ });
1213
+ return { ...state, nodes, lockedLayout };
1214
+ }
1215
+ function resizeLockedGrid(state, nodeID, requestedFrame) {
1216
+ const lockedLayout = state.lockedLayout;
1217
+ if (!lockedLayout) {
1218
+ return state;
1219
+ }
1220
+ const sourceNode = state.nodes.find((node) => node.id === nodeID);
1221
+ if (!sourceNode) {
1222
+ return state;
1223
+ }
1224
+ const layoutRect = getWorkbenchSafeLayoutRect(
1225
+ state.surfaceSize,
1226
+ state.layoutConstraints
1227
+ );
1228
+ const lockedNodeIDs = lockedLayout.nodeIDs.filter(
1229
+ (lockedID) => state.nodes.some((node) => node.id === lockedID)
1230
+ );
1231
+ const frameByNodeID = new Map(
1232
+ state.nodes.filter((node) => lockedNodeIDs.includes(node.id)).map((node) => [
1233
+ node.id,
1234
+ {
1235
+ x: node.frame.x,
1236
+ y: node.frame.y,
1237
+ width: node.frame.width,
1238
+ height: node.frame.height
1239
+ }
1240
+ ])
1241
+ );
1242
+ const minSizeByNodeID = new Map(
1243
+ state.nodes.filter((node) => lockedNodeIDs.includes(node.id)).map(
1244
+ (node) => [
1245
+ node.id,
1246
+ {
1247
+ minWidth: Math.max(
1248
+ state.layoutConstraints.minWidth,
1249
+ node.sizeConstraints?.minWidth ?? 0
1250
+ ),
1251
+ minHeight: Math.max(
1252
+ state.layoutConstraints.minHeight,
1253
+ node.sizeConstraints?.minHeight ?? 0
1254
+ )
1255
+ }
1256
+ ]
1257
+ )
1258
+ );
1259
+ const oldFrame = sourceNode.frame;
1260
+ let changed = false;
1261
+ const dividerMoves = [
1262
+ { axis: "x", from: oldFrame.x, to: requestedFrame.x },
1263
+ {
1264
+ axis: "x",
1265
+ from: oldFrame.x + oldFrame.width,
1266
+ to: requestedFrame.x + requestedFrame.width
1267
+ },
1268
+ { axis: "y", from: oldFrame.y, to: requestedFrame.y },
1269
+ {
1270
+ axis: "y",
1271
+ from: oldFrame.y + oldFrame.height,
1272
+ to: requestedFrame.y + requestedFrame.height
1273
+ }
1274
+ ].filter((move) => Math.abs(move.to - move.from) > 0.1);
1275
+ const edgeTolerance = 2;
1276
+ const gapTolerance = WORKBENCH_LAYOUT_PRESET_GAP_PX + edgeTolerance;
1277
+ for (const move of dividerMoves) {
1278
+ const rectStart = move.axis === "x" ? layoutRect.x : layoutRect.y;
1279
+ const rectEnd = move.axis === "x" ? layoutRect.x + layoutRect.width : layoutRect.y + layoutRect.height;
1280
+ if (move.from - rectStart <= gapTolerance || rectEnd - move.from <= gapTolerance) {
1281
+ continue;
1282
+ }
1283
+ const trailing = [];
1284
+ const leading = [];
1285
+ let minDelta = Number.NEGATIVE_INFINITY;
1286
+ let maxDelta = Number.POSITIVE_INFINITY;
1287
+ for (const [lockedID, frame] of frameByNodeID) {
1288
+ const minSize = minSizeByNodeID.get(lockedID);
1289
+ const start = move.axis === "x" ? frame.x : frame.y;
1290
+ const size = move.axis === "x" ? frame.width : frame.height;
1291
+ const minLength = move.axis === "x" ? minSize.minWidth : minSize.minHeight;
1292
+ const endOffset = move.from - (start + size);
1293
+ const startOffset = start - move.from;
1294
+ if (endOffset >= -edgeTolerance && endOffset <= gapTolerance) {
1295
+ trailing.push(lockedID);
1296
+ minDelta = Math.max(minDelta, minLength - size);
1297
+ maxDelta = Math.min(maxDelta, rectEnd - (start + size));
1298
+ } else if (startOffset >= -edgeTolerance && startOffset <= gapTolerance) {
1299
+ leading.push(lockedID);
1300
+ maxDelta = Math.min(maxDelta, size - minLength);
1301
+ minDelta = Math.max(minDelta, rectStart - start);
1302
+ }
1303
+ }
1304
+ if (trailing.length === 0 && leading.length === 0) {
1305
+ continue;
1306
+ }
1307
+ const delta = Math.min(Math.max(move.to - move.from, minDelta), maxDelta);
1308
+ if (Math.abs(delta) <= 0.1) {
1309
+ continue;
1310
+ }
1311
+ for (const lockedID of trailing) {
1312
+ const frame = frameByNodeID.get(lockedID);
1313
+ if (move.axis === "x") {
1314
+ frame.width += delta;
1315
+ } else {
1316
+ frame.height += delta;
1317
+ }
1318
+ }
1319
+ for (const lockedID of leading) {
1320
+ const frame = frameByNodeID.get(lockedID);
1321
+ if (move.axis === "x") {
1322
+ frame.x += delta;
1323
+ frame.width -= delta;
1324
+ } else {
1325
+ frame.y += delta;
1326
+ frame.height -= delta;
1327
+ }
1328
+ }
1329
+ changed = true;
1330
+ }
1331
+ if (!changed) {
1332
+ return state;
1333
+ }
1334
+ const normalizedFrames = {};
1335
+ for (const [lockedID, frame] of frameByNodeID) {
1336
+ normalizedFrames[lockedID] = normalizeWorkbenchFrameToRect(
1337
+ frame,
1338
+ layoutRect
1339
+ );
1340
+ }
1341
+ const nodes = state.nodes.map((node) => {
1342
+ const frame = frameByNodeID.get(node.id);
1343
+ if (!frame || rectsEqual(node.frame, frame)) {
1344
+ return node;
1345
+ }
1346
+ return { ...node, frame };
1347
+ });
1348
+ return {
1349
+ ...state,
1350
+ nodes,
1351
+ nodeStack: focusWorkbenchStack(state.nodeStack, nodeID),
1352
+ lockedLayout: { ...lockedLayout, normalizedFrames }
1353
+ };
1354
+ }
1355
+ function swapNodeIDs(nodeIDs, firstID, secondID) {
1356
+ return nodeIDs.map(
1357
+ (entry) => entry === firstID ? secondID : entry === secondID ? firstID : entry
1358
+ );
1359
+ }
1360
+ function frameCenter(frame) {
1361
+ return {
1362
+ x: frame.x + frame.width / 2,
1363
+ y: frame.y + frame.height / 2
1364
+ };
1365
+ }
1366
+ function frameContainsPoint(frame, point) {
1367
+ return point.x >= frame.x && point.x <= frame.x + frame.width && point.y >= frame.y && point.y <= frame.y + frame.height;
1368
+ }
1369
+ function releaseLockedLayout(previousState, nextState) {
1370
+ if (nextState === previousState || nextState.lockedLayout === null) {
1371
+ return nextState;
1372
+ }
1373
+ return { ...nextState, lockedLayout: null };
1374
+ }
1375
+ function pruneLockedLayout(lockedLayout, removedNodeID) {
1376
+ if (!lockedLayout || !lockedLayout.nodeIDs.includes(removedNodeID)) {
1377
+ return lockedLayout;
974
1378
  }
975
- return { ...state, nodes, nodeStack };
1379
+ const nodeIDs = lockedLayout.nodeIDs.filter(
1380
+ (nodeID) => nodeID !== removedNodeID
1381
+ );
1382
+ return nodeIDs.length >= 2 ? { preset: lockedLayout.preset, nodeIDs } : null;
976
1383
  }
977
1384
  function uniqueKnownNodeIDs(nodes, nodeIDs) {
978
1385
  const knownNodeIDs = new Set(nodes.map((node) => node.id));
@@ -1151,10 +1558,11 @@ function createWorkbenchController(initialState = {}, options = {}) {
1151
1558
  }
1152
1559
 
1153
1560
  // src/host/WorkbenchHost.tsx
1154
- import { useMemo as useMemo7 } from "react";
1561
+ import { useMemo as useMemo8 } from "react";
1155
1562
 
1156
1563
  // src/mission-control/WorkbenchMissionControlOverlay.tsx
1157
1564
  import {
1565
+ useEffect,
1158
1566
  useLayoutEffect,
1159
1567
  useRef,
1160
1568
  useState
@@ -1162,6 +1570,10 @@ import {
1162
1570
  import {
1163
1571
  AppWindowIcon,
1164
1572
  Button,
1573
+ DropdownMenu,
1574
+ DropdownMenuContent,
1575
+ DropdownMenuItem,
1576
+ DropdownMenuTrigger,
1165
1577
  GridHorizontalLinedIcon,
1166
1578
  GridVerticalLinedIcon
1167
1579
  } from "@tutti-os/ui-system";
@@ -1184,7 +1596,7 @@ function shouldShowWorkbenchMissionControlLayoutPreset(selectedCount, preset) {
1184
1596
  }
1185
1597
 
1186
1598
  // src/mission-control/WorkbenchMissionControlOverlay.tsx
1187
- import { jsx } from "react/jsx-runtime";
1599
+ import { jsx, jsxs } from "react/jsx-runtime";
1188
1600
  function WorkbenchMissionControlBackdrop({
1189
1601
  className,
1190
1602
  onExitTransitionComplete,
@@ -1212,6 +1624,30 @@ function WorkbenchMissionControlOverlay({
1212
1624
  }) {
1213
1625
  const layoutDockContentRef = useRef(null);
1214
1626
  const [layoutDockWidth, setLayoutDockWidth] = useState(null);
1627
+ const [openLayoutKey, setOpenLayoutKey] = useState(null);
1628
+ const hoverOpenTimeoutRef = useRef(null);
1629
+ const clearHoverOpenTimeout = () => {
1630
+ if (hoverOpenTimeoutRef.current !== null) {
1631
+ window.clearTimeout(hoverOpenTimeoutRef.current);
1632
+ hoverOpenTimeoutRef.current = null;
1633
+ }
1634
+ };
1635
+ const requestHoverOpen = (key) => {
1636
+ clearHoverOpenTimeout();
1637
+ if (openLayoutKey !== null) {
1638
+ setOpenLayoutKey(key);
1639
+ return;
1640
+ }
1641
+ hoverOpenTimeoutRef.current = window.setTimeout(() => {
1642
+ hoverOpenTimeoutRef.current = null;
1643
+ setOpenLayoutKey(key);
1644
+ }, layoutPresetMenuHoverOpenDelayMs);
1645
+ };
1646
+ const closeLayoutMenu = (key) => {
1647
+ clearHoverOpenTimeout();
1648
+ setOpenLayoutKey((current) => current === key ? null : current);
1649
+ };
1650
+ useEffect(() => clearHoverOpenTimeout, []);
1215
1651
  const layoutPresets = [
1216
1652
  {
1217
1653
  icon: AppWindowIcon,
@@ -1278,32 +1714,26 @@ function WorkbenchMissionControlOverlay({
1278
1714
  {
1279
1715
  ref: layoutDockContentRef,
1280
1716
  className: "workbench-mission-control__layout-dock-content",
1281
- children: showLayoutSelectionHint ? /* @__PURE__ */ jsx("span", { className: "workbench-mission-control__layout-hint", children: i18n.t("layoutSelectionHint") }) : showNoAvailableLayoutMessage ? /* @__PURE__ */ jsx("span", { className: "workbench-mission-control__layout-hint", children: i18n.t("noAvailableLayout") }) : /* @__PURE__ */ jsx("div", { className: "flex items-end gap-2", children: layoutPresets.map((option) => {
1282
- const canApply = state.canApplyPreset(option.preset);
1283
- const LayoutIcon = option.icon;
1284
- return /* @__PURE__ */ jsx(
1285
- Button,
1286
- {
1287
- "aria-label": option.label,
1288
- className: "workbench-mission-control__layout-dock-button",
1289
- "data-layout-key": option.key,
1290
- disabled: !canApply,
1291
- size: "icon",
1292
- title: option.label,
1293
- type: "button",
1294
- variant: "ghost",
1295
- onClick: () => state.applyPreset(option.preset),
1296
- children: /* @__PURE__ */ jsx(
1297
- LayoutIcon,
1298
- {
1299
- "aria-hidden": true,
1300
- className: "workbench-mission-control__layout-glyph"
1301
- }
1302
- )
1717
+ children: showLayoutSelectionHint ? /* @__PURE__ */ jsx("span", { className: "workbench-mission-control__layout-hint", children: i18n.t("layoutSelectionHint") }) : showNoAvailableLayoutMessage ? /* @__PURE__ */ jsx("span", { className: "workbench-mission-control__layout-hint", children: i18n.t("noAvailableLayout") }) : /* @__PURE__ */ jsx("div", { className: "flex items-end gap-2", children: layoutPresets.map((option) => /* @__PURE__ */ jsx(
1718
+ WorkbenchMissionControlLayoutPresetButton,
1719
+ {
1720
+ arrangeOnceLabel: i18n.t("presetActions.arrangeOnce"),
1721
+ canApply: state.canApplyPreset(option.preset),
1722
+ icon: option.icon,
1723
+ layoutKey: option.key,
1724
+ lockLayoutLabel: i18n.t("presetActions.lockLayout"),
1725
+ open: openLayoutKey === option.key,
1726
+ onApply: (lock) => {
1727
+ closeLayoutMenu(option.key);
1728
+ state.applyPreset(option.preset, { lock });
1303
1729
  },
1304
- option.key
1305
- );
1306
- }) })
1730
+ onHoverOpen: () => requestHoverOpen(option.key),
1731
+ onHoverCancel: clearHoverOpenTimeout,
1732
+ onRequestClose: () => closeLayoutMenu(option.key),
1733
+ presetLabel: option.label
1734
+ },
1735
+ option.key
1736
+ )) })
1307
1737
  }
1308
1738
  )
1309
1739
  }
@@ -1311,6 +1741,86 @@ function WorkbenchMissionControlOverlay({
1311
1741
  }
1312
1742
  );
1313
1743
  }
1744
+ var layoutPresetMenuHoverOpenDelayMs = 200;
1745
+ function WorkbenchMissionControlLayoutPresetButton({
1746
+ arrangeOnceLabel,
1747
+ canApply,
1748
+ icon: LayoutIcon,
1749
+ layoutKey,
1750
+ lockLayoutLabel,
1751
+ onApply,
1752
+ onHoverCancel,
1753
+ onHoverOpen,
1754
+ onRequestClose,
1755
+ open,
1756
+ presetLabel
1757
+ }) {
1758
+ return /* @__PURE__ */ jsxs(
1759
+ DropdownMenu,
1760
+ {
1761
+ open,
1762
+ onOpenChange: (nextOpen) => {
1763
+ if (!nextOpen) {
1764
+ onRequestClose();
1765
+ return;
1766
+ }
1767
+ if (canApply) {
1768
+ onHoverOpen();
1769
+ }
1770
+ },
1771
+ children: [
1772
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1773
+ Button,
1774
+ {
1775
+ "aria-label": presetLabel,
1776
+ className: "workbench-mission-control__layout-dock-button",
1777
+ "data-layout-key": layoutKey,
1778
+ "data-menu-open": open ? "true" : void 0,
1779
+ disabled: !canApply,
1780
+ size: "icon",
1781
+ title: presetLabel,
1782
+ type: "button",
1783
+ variant: "ghost",
1784
+ onClick: () => {
1785
+ if (canApply) {
1786
+ onApply(true);
1787
+ }
1788
+ },
1789
+ onPointerDown: (event) => {
1790
+ event.preventDefault();
1791
+ },
1792
+ onPointerEnter: () => {
1793
+ if (canApply) {
1794
+ onHoverOpen();
1795
+ }
1796
+ },
1797
+ onPointerLeave: onHoverCancel,
1798
+ children: /* @__PURE__ */ jsx(
1799
+ LayoutIcon,
1800
+ {
1801
+ "aria-hidden": true,
1802
+ className: "workbench-mission-control__layout-glyph"
1803
+ }
1804
+ )
1805
+ }
1806
+ ) }),
1807
+ /* @__PURE__ */ jsxs(
1808
+ DropdownMenuContent,
1809
+ {
1810
+ align: "center",
1811
+ className: "w-auto min-w-40",
1812
+ sideOffset: 10,
1813
+ onCloseAutoFocus: (event) => event.preventDefault(),
1814
+ children: [
1815
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => onApply(false), children: arrangeOnceLabel }),
1816
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => onApply(true), children: lockLayoutLabel })
1817
+ ]
1818
+ }
1819
+ )
1820
+ ]
1821
+ }
1822
+ );
1823
+ }
1314
1824
 
1315
1825
  // src/mission-control/useWorkbenchMissionControlPresence.ts
1316
1826
  import { useCallback, useLayoutEffect as useLayoutEffect2, useRef as useRef2, useState as useState2 } from "react";
@@ -1373,7 +1883,7 @@ function useWorkbenchMissionControlPresence(state) {
1373
1883
  }
1374
1884
 
1375
1885
  // src/mission-control/useWorkbenchMissionControlState.ts
1376
- import { useCallback as useCallback2, useEffect, useMemo, useState as useState3 } from "react";
1886
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
1377
1887
  import {
1378
1888
  useExternalStoreSnapshot
1379
1889
  } from "@tutti-os/ui-react-hooks";
@@ -1560,13 +2070,13 @@ function useWorkbenchMissionControlState({
1560
2070
  return nextVisibleNodes.filter((node) => scopedNodeIdSet.has(node.id));
1561
2071
  }, [scopedNodeIdSet, snapshot?.visibleNodes]);
1562
2072
  const [selectedNodeIds, setSelectedNodeIds] = useState3([]);
1563
- useEffect(() => {
2073
+ useEffect2(() => {
1564
2074
  if (mode === null) {
1565
2075
  return;
1566
2076
  }
1567
2077
  setSelectedNodeIds([]);
1568
2078
  }, [mode]);
1569
- useEffect(() => {
2079
+ useEffect2(() => {
1570
2080
  if (mode !== null && visibleNodes.length === 0) {
1571
2081
  onRequestClose();
1572
2082
  }
@@ -1637,13 +2147,13 @@ function useWorkbenchMissionControlState({
1637
2147
  [adapter, onRequestClose]
1638
2148
  );
1639
2149
  const applyLayoutAndClose = useCallback2(
1640
- (nodeIds2, nextPreset) => {
2150
+ (nodeIds2, nextPreset, lock) => {
1641
2151
  if (!adapter || nodeIds2.length < 2) {
1642
2152
  return;
1643
2153
  }
1644
2154
  onRequestClose();
1645
2155
  window.requestAnimationFrame(() => {
1646
- adapter.applyLayoutPreset(nodeIds2, nextPreset);
2156
+ adapter.applyLayoutPreset(nodeIds2, nextPreset, lock);
1647
2157
  });
1648
2158
  },
1649
2159
  [adapter, onRequestClose]
@@ -1668,11 +2178,15 @@ function useWorkbenchMissionControlState({
1668
2178
  [selectedNodeIds]
1669
2179
  );
1670
2180
  const applyPreset = useCallback2(
1671
- (nextPreset) => {
2181
+ (nextPreset, options) => {
1672
2182
  if (!canApplyPreset(nextPreset)) {
1673
2183
  return;
1674
2184
  }
1675
- applyLayoutAndClose(orderedSelectedNodeIds, nextPreset);
2185
+ applyLayoutAndClose(
2186
+ orderedSelectedNodeIds,
2187
+ nextPreset,
2188
+ options?.lock ?? false
2189
+ );
1676
2190
  },
1677
2191
  [applyLayoutAndClose, canApplyPreset, orderedSelectedNodeIds]
1678
2192
  );
@@ -1699,7 +2213,7 @@ function useWorkbenchMissionControlState({
1699
2213
  selectedNodeIdSet
1700
2214
  ]
1701
2215
  );
1702
- useEffect(() => {
2216
+ useEffect2(() => {
1703
2217
  if (mode === null) {
1704
2218
  return void 0;
1705
2219
  }
@@ -1730,7 +2244,7 @@ function useWorkbenchMissionControlState({
1730
2244
  // src/react/WorkbenchSurface.tsx
1731
2245
  import {
1732
2246
  useCallback as useCallback7,
1733
- useEffect as useEffect4
2247
+ useEffect as useEffect5
1734
2248
  } from "react";
1735
2249
 
1736
2250
  // src/react/WorkbenchDockFrame.tsx
@@ -1832,7 +2346,7 @@ function useWorkbenchSelector(selector) {
1832
2346
  }
1833
2347
 
1834
2348
  // src/react/WorkbenchDockFrame.tsx
1835
- import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
2349
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1836
2350
  function WorkbenchDockFrame({
1837
2351
  dockPlacement = "bottom",
1838
2352
  genie,
@@ -1869,7 +2383,7 @@ function WorkbenchDockFrame({
1869
2383
  if (!renderDock && minimizedNodes.length === 0) {
1870
2384
  return null;
1871
2385
  }
1872
- return /* @__PURE__ */ jsxs(Fragment, { children: [
2386
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
1873
2387
  hasFullscreenNode ? /* @__PURE__ */ jsx3(
1874
2388
  "div",
1875
2389
  {
@@ -1926,8 +2440,44 @@ function mergePendingMinimizedDockNode(nodes, pendingNode) {
1926
2440
  return [...nodes.filter((node) => node.id !== pendingNode.id), pendingNode];
1927
2441
  }
1928
2442
 
2443
+ // src/react/WorkbenchLockedSlotLayer.tsx
2444
+ import { useMemo as useMemo3 } from "react";
2445
+ import { jsx as jsx4 } from "react/jsx-runtime";
2446
+ var selectLockedLayout = (state) => state.lockedLayout;
2447
+ var selectSurfaceSize = (state) => state.surfaceSize;
2448
+ var selectLayoutConstraints = (state) => state.layoutConstraints;
2449
+ function WorkbenchLockedSlotLayer() {
2450
+ const lockedLayout = useWorkbenchSelector(selectLockedLayout);
2451
+ const surfaceSize = useWorkbenchSelector(selectSurfaceSize);
2452
+ const layoutConstraints = useWorkbenchSelector(selectLayoutConstraints);
2453
+ const slots = useMemo3(
2454
+ () => getWorkbenchLockedSlotFrames(
2455
+ lockedLayout,
2456
+ surfaceSize,
2457
+ layoutConstraints
2458
+ ),
2459
+ [layoutConstraints, lockedLayout, surfaceSize]
2460
+ );
2461
+ if (!slots) {
2462
+ return null;
2463
+ }
2464
+ return /* @__PURE__ */ jsx4("div", { "aria-hidden": true, className: "workbench-locked-slot-layer", children: slots.map((slot) => /* @__PURE__ */ jsx4(
2465
+ "div",
2466
+ {
2467
+ className: "workbench-locked-slot",
2468
+ style: {
2469
+ left: slot.frame.x,
2470
+ top: slot.frame.y,
2471
+ width: slot.frame.width,
2472
+ height: slot.frame.height
2473
+ }
2474
+ },
2475
+ slot.nodeID
2476
+ )) });
2477
+ }
2478
+
1929
2479
  // src/react/WorkbenchNodeLayer.tsx
1930
- import { Fragment as Fragment3, memo, useMemo as useMemo3 } from "react";
2480
+ import { Fragment as Fragment3, memo, useMemo as useMemo4 } from "react";
1931
2481
  import { createPortal } from "react-dom";
1932
2482
 
1933
2483
  // src/react/WorkbenchWindowFrame.tsx
@@ -1942,7 +2492,7 @@ import {
1942
2492
  TooltipTrigger,
1943
2493
  WindowTrafficLightIcon
1944
2494
  } from "@tutti-os/ui-system";
1945
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
2495
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1946
2496
  function WorkbenchWindowTrafficLights({
1947
2497
  className,
1948
2498
  close,
@@ -1952,7 +2502,7 @@ function WorkbenchWindowTrafficLights({
1952
2502
  onPointerDown,
1953
2503
  ...props
1954
2504
  }) {
1955
- return /* @__PURE__ */ jsxs2(
2505
+ return /* @__PURE__ */ jsxs3(
1956
2506
  "div",
1957
2507
  {
1958
2508
  ...props,
@@ -1966,7 +2516,7 @@ function WorkbenchWindowTrafficLights({
1966
2516
  onPointerDown?.(event);
1967
2517
  },
1968
2518
  children: [
1969
- close ? /* @__PURE__ */ jsx4(
2519
+ close ? /* @__PURE__ */ jsx5(
1970
2520
  WorkbenchWindowTrafficLightButton,
1971
2521
  {
1972
2522
  action: "close",
@@ -1974,7 +2524,7 @@ function WorkbenchWindowTrafficLights({
1974
2524
  tone: "close"
1975
2525
  }
1976
2526
  ) : null,
1977
- minimize ? /* @__PURE__ */ jsx4(
2527
+ minimize ? /* @__PURE__ */ jsx5(
1978
2528
  WorkbenchWindowTrafficLightButton,
1979
2529
  {
1980
2530
  action: "minimize",
@@ -1982,7 +2532,7 @@ function WorkbenchWindowTrafficLights({
1982
2532
  tone: "minimize"
1983
2533
  }
1984
2534
  ) : null,
1985
- maximize ? /* @__PURE__ */ jsx4(
2535
+ maximize ? /* @__PURE__ */ jsx5(
1986
2536
  WorkbenchWindowTrafficLightButton,
1987
2537
  {
1988
2538
  action: "fullscreen",
@@ -2010,7 +2560,7 @@ function WorkbenchWindowTrafficLightButton({
2010
2560
  event.stopPropagation();
2011
2561
  };
2012
2562
  const iconName = tone === "maximize" ? input.pressed ? "unfullscreen" : "fullscreen" : tone;
2013
- const button = /* @__PURE__ */ jsx4(
2563
+ const button = /* @__PURE__ */ jsx5(
2014
2564
  "button",
2015
2565
  {
2016
2566
  "aria-label": input.label,
@@ -2023,7 +2573,7 @@ function WorkbenchWindowTrafficLightButton({
2023
2573
  onClick: handleClick,
2024
2574
  onDoubleClick: (event) => event.stopPropagation(),
2025
2575
  onPointerDown: stopPointer,
2026
- children: /* @__PURE__ */ jsx4(
2576
+ children: /* @__PURE__ */ jsx5(
2027
2577
  WindowTrafficLightIcon,
2028
2578
  {
2029
2579
  "aria-hidden": "true",
@@ -2034,14 +2584,14 @@ function WorkbenchWindowTrafficLightButton({
2034
2584
  )
2035
2585
  }
2036
2586
  );
2037
- return /* @__PURE__ */ jsx4(TooltipProvider, { delayDuration: 250, skipDelayDuration: 0, children: /* @__PURE__ */ jsxs2(Tooltip, { children: [
2038
- /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: button }),
2039
- /* @__PURE__ */ jsx4(TooltipContent, { side: "bottom", children: input.label })
2587
+ return /* @__PURE__ */ jsx5(TooltipProvider, { delayDuration: 250, skipDelayDuration: 0, children: /* @__PURE__ */ jsxs3(Tooltip, { children: [
2588
+ /* @__PURE__ */ jsx5(TooltipTrigger, { asChild: true, children: button }),
2589
+ /* @__PURE__ */ jsx5(TooltipContent, { side: "bottom", children: input.label })
2040
2590
  ] }) });
2041
2591
  }
2042
2592
 
2043
2593
  // src/react/WorkbenchWindowFullscreenToggle.tsx
2044
- import { jsx as jsx5 } from "react/jsx-runtime";
2594
+ import { jsx as jsx6 } from "react/jsx-runtime";
2045
2595
  function WorkbenchWindowFullscreenToggle({
2046
2596
  controller,
2047
2597
  disabled = false,
@@ -2050,7 +2600,7 @@ function WorkbenchWindowFullscreenToggle({
2050
2600
  }) {
2051
2601
  const isFullscreen = node.displayMode === "fullscreen";
2052
2602
  const label = i18n.t(isFullscreen ? "exitFullscreen" : "enterFullscreen");
2053
- return /* @__PURE__ */ jsx5(
2603
+ return /* @__PURE__ */ jsx6(
2054
2604
  WorkbenchWindowTrafficLights,
2055
2605
  {
2056
2606
  maximize: {
@@ -2127,16 +2677,22 @@ function useWorkbenchDrag(node, options = {}) {
2127
2677
  controller.commands.setActiveDragNode(node.id);
2128
2678
  const origin = { x: event.clientX, y: event.clientY };
2129
2679
  const initialFrame = node.frame;
2680
+ const isLockedLayoutDrag = () => {
2681
+ const lockedLayout = controller.getSnapshot().lockedLayout;
2682
+ return lockedLayout !== null && lockedLayout.nodeIDs.includes(node.id);
2683
+ };
2130
2684
  const onPointerMove = (moveEvent) => {
2131
2685
  const nextFrame = {
2132
2686
  ...initialFrame,
2133
2687
  x: initialFrame.x + moveEvent.clientX - origin.x,
2134
2688
  y: initialFrame.y + moveEvent.clientY - origin.y
2135
2689
  };
2136
- updateSnap(
2137
- { x: moveEvent.clientX, y: moveEvent.clientY },
2138
- { edgeSnapEnabled }
2139
- );
2690
+ if (!isLockedLayoutDrag()) {
2691
+ updateSnap(
2692
+ { x: moveEvent.clientX, y: moveEvent.clientY },
2693
+ { edgeSnapEnabled }
2694
+ );
2695
+ }
2140
2696
  controller.commands.dragNode(node.id, nextFrame);
2141
2697
  };
2142
2698
  const clearListeners = () => {
@@ -2147,7 +2703,9 @@ function useWorkbenchDrag(node, options = {}) {
2147
2703
  window.removeEventListener("pointercancel", cancelDrag);
2148
2704
  };
2149
2705
  const finishDrag = (upEvent) => {
2150
- if (updateSnap(
2706
+ if (isLockedLayoutDrag()) {
2707
+ controller.commands.settleLockedDrag(node.id);
2708
+ } else if (updateSnap(
2151
2709
  { x: upEvent.clientX, y: upEvent.clientY },
2152
2710
  { edgeSnapEnabled }
2153
2711
  ) !== null) {
@@ -2156,6 +2714,9 @@ function useWorkbenchDrag(node, options = {}) {
2156
2714
  clearListeners();
2157
2715
  };
2158
2716
  const cancelDrag = () => {
2717
+ if (isLockedLayoutDrag()) {
2718
+ controller.commands.settleLockedDrag(node.id);
2719
+ }
2159
2720
  clearListeners();
2160
2721
  };
2161
2722
  window.addEventListener("pointermove", onPointerMove);
@@ -2264,7 +2825,7 @@ function resolveWorkbenchWindowHeader({
2264
2825
  }
2265
2826
 
2266
2827
  // src/react/WorkbenchWindowFrame.tsx
2267
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
2828
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
2268
2829
  var resizeHandles = [
2269
2830
  "north",
2270
2831
  "east",
@@ -2336,7 +2897,7 @@ function WorkbenchWindowFrame({
2336
2897
  genie.minimizeNodeToAnchor(nodeID, minimize);
2337
2898
  }
2338
2899
  };
2339
- const defaultActions = interactive ? /* @__PURE__ */ jsxs3(
2900
+ const defaultActions = interactive ? /* @__PURE__ */ jsxs4(
2340
2901
  "div",
2341
2902
  {
2342
2903
  className: "workbench-window__traffic-light-actions",
@@ -2352,7 +2913,7 @@ function WorkbenchWindowFrame({
2352
2913
  genie: genieControls,
2353
2914
  node
2354
2915
  }) : null,
2355
- /* @__PURE__ */ jsx6(
2916
+ /* @__PURE__ */ jsx7(
2356
2917
  WorkbenchWindowFullscreenToggle,
2357
2918
  {
2358
2919
  controller,
@@ -2393,7 +2954,7 @@ function WorkbenchWindowFrame({
2393
2954
  (presentationFrame.height - node.frame.height * presentationScale) / 2
2394
2955
  ) - node.frame.y : 0;
2395
2956
  const shellTransform = presentationMode === "mission-control" && presentationFrame ? `matrix(${presentationScale}, 0, 0, ${presentationScale}, ${presentationOffsetX}, ${presentationOffsetY})` : void 0;
2396
- return /* @__PURE__ */ jsxs3(
2957
+ return /* @__PURE__ */ jsxs4(
2397
2958
  "section",
2398
2959
  {
2399
2960
  "aria-hidden": hiddenMounted || isPresentationHidden ? true : void 0,
@@ -2421,8 +2982,8 @@ function WorkbenchWindowFrame({
2421
2982
  },
2422
2983
  onPointerDown: hiddenMounted || isPresentationHidden || !interactive || presentationMode === "mission-control" ? void 0 : () => controller.commands.focusNode(node.id),
2423
2984
  children: [
2424
- /* @__PURE__ */ jsxs3("div", { className: "workbench-window-shell__content", children: [
2425
- /* @__PURE__ */ jsxs3(
2985
+ /* @__PURE__ */ jsxs4("div", { className: "workbench-window-shell__content", children: [
2986
+ /* @__PURE__ */ jsxs4(
2426
2987
  "div",
2427
2988
  {
2428
2989
  className: "workbench-window",
@@ -2434,7 +2995,7 @@ function WorkbenchWindowFrame({
2434
2995
  "data-window-drag-state": isDragging ? "dragging" : "idle",
2435
2996
  "data-window-resize-state": isResizing ? "resizing" : "idle",
2436
2997
  children: [
2437
- /* @__PURE__ */ jsx6(
2998
+ /* @__PURE__ */ jsx7(
2438
2999
  "div",
2439
3000
  {
2440
3001
  className: [
@@ -2443,19 +3004,19 @@ function WorkbenchWindowFrame({
2443
3004
  ].filter(Boolean).join(" "),
2444
3005
  onDoubleClick: shouldRenderCustomHeader || !interactive ? void 0 : onHeaderDoubleClick,
2445
3006
  onPointerDown: shouldRenderCustomHeader || !interactive ? void 0 : onDragStart,
2446
- children: shouldRenderCustomHeader ? resolvedHeader.customHeader : /* @__PURE__ */ jsxs3(Fragment2, { children: [
3007
+ children: shouldRenderCustomHeader ? resolvedHeader.customHeader : /* @__PURE__ */ jsxs4(Fragment2, { children: [
2447
3008
  defaultActions,
2448
- /* @__PURE__ */ jsx6("div", { className: "workbench-window__title", children: node.title })
3009
+ /* @__PURE__ */ jsx7("div", { className: "workbench-window__title", children: node.title })
2449
3010
  ] })
2450
3011
  }
2451
3012
  ),
2452
- /* @__PURE__ */ jsx6("div", { className: "workbench-window__body", children })
3013
+ /* @__PURE__ */ jsx7("div", { className: "workbench-window__body", children })
2453
3014
  ]
2454
3015
  }
2455
3016
  ),
2456
- node.displayMode === "floating" && !hiddenMounted && presentationMode !== "mission-control" && interactive ? resizeHandles.map((handle) => /* @__PURE__ */ jsx6(ResizeHandle, { handle, node }, handle)) : null
3017
+ node.displayMode === "floating" && !hiddenMounted && presentationMode !== "mission-control" && interactive ? resizeHandles.map((handle) => /* @__PURE__ */ jsx7(ResizeHandle, { handle, node }, handle)) : null
2457
3018
  ] }),
2458
- presentationInteraction ? /* @__PURE__ */ jsx6(
3019
+ presentationInteraction ? /* @__PURE__ */ jsx7(
2459
3020
  "button",
2460
3021
  {
2461
3022
  "aria-label": node.title,
@@ -2466,10 +3027,10 @@ function WorkbenchWindowFrame({
2466
3027
  event.stopPropagation();
2467
3028
  presentationInteraction.onNodePress(node.id);
2468
3029
  },
2469
- children: presentationInteraction.mode === "layout" && isMissionControlSelected ? /* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute inset-0 rounded-lg border-2 border-[var(--tutti-purple)] transition-[border-color,transform] duration-150 ease-out" }) : null
3030
+ children: presentationInteraction.mode === "layout" && isMissionControlSelected ? /* @__PURE__ */ jsx7("div", { className: "pointer-events-none absolute inset-0 rounded-lg border-2 border-[var(--tutti-purple)] transition-[border-color,transform] duration-150 ease-out" }) : null
2470
3031
  }
2471
3032
  ) : null,
2472
- presentationInteraction?.mode === "layout" && isMissionControlSelected ? /* @__PURE__ */ jsx6(
3033
+ presentationInteraction?.mode === "layout" && isMissionControlSelected ? /* @__PURE__ */ jsx7(
2473
3034
  Checkbox,
2474
3035
  {
2475
3036
  "aria-hidden": "true",
@@ -2487,7 +3048,7 @@ function ResizeHandle({
2487
3048
  node
2488
3049
  }) {
2489
3050
  const onPointerDown = useWorkbenchResize(node, handle);
2490
- return /* @__PURE__ */ jsx6(
3051
+ return /* @__PURE__ */ jsx7(
2491
3052
  "div",
2492
3053
  {
2493
3054
  className: "workbench-window__resize-handle",
@@ -2522,7 +3083,7 @@ function stringArraysEqual(left, right) {
2522
3083
  }
2523
3084
 
2524
3085
  // src/react/WorkbenchNodeLayer.tsx
2525
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
3086
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
2526
3087
  function WorkbenchNodeLayer({
2527
3088
  genie,
2528
3089
  edgeSnapEnabled = false,
@@ -2538,7 +3099,7 @@ function WorkbenchNodeLayer({
2538
3099
  windowChromeMode,
2539
3100
  windowChromeI18n
2540
3101
  }) {
2541
- const selectRenderedNodeIDs = useMemo3(
3102
+ const selectRenderedNodeIDs = useMemo4(
2542
3103
  () => createRenderedWorkbenchNodeIDsSelector(shouldKeepMinimizedNodeMounted),
2543
3104
  [shouldKeepMinimizedNodeMounted]
2544
3105
  );
@@ -2570,7 +3131,7 @@ function WorkbenchNodeLayer({
2570
3131
  });
2571
3132
  const snapPreviewRect = useWorkbenchSelector(selectWorkbenchSnapPreviewRect);
2572
3133
  const presentationInteraction = interactive && presentation?.mode === "mission-control" ? presentation.interaction ?? null : null;
2573
- const dialogPopoverLayer = dialogPopoverNodeIDs.length > 0 ? /* @__PURE__ */ jsx7(
3134
+ const dialogPopoverLayer = dialogPopoverNodeIDs.length > 0 ? /* @__PURE__ */ jsx8(
2574
3135
  WorkbenchNodeLayerGroup,
2575
3136
  {
2576
3137
  className: "workbench-node-layer workbench-node-layer--dialog-popover",
@@ -2588,8 +3149,8 @@ function WorkbenchNodeLayer({
2588
3149
  windowChromeMode
2589
3150
  }
2590
3151
  ) : null;
2591
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
2592
- /* @__PURE__ */ jsx7(
3152
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
3153
+ /* @__PURE__ */ jsx8(
2593
3154
  WorkbenchNodeLayerGroup,
2594
3155
  {
2595
3156
  className: "workbench-node-layer",
@@ -2629,7 +3190,7 @@ function WorkbenchNodeLayerGroup({
2629
3190
  windowChromeI18n,
2630
3191
  windowChromeMode
2631
3192
  }) {
2632
- return /* @__PURE__ */ jsxs4(
3193
+ return /* @__PURE__ */ jsxs5(
2633
3194
  "div",
2634
3195
  {
2635
3196
  className,
@@ -2641,7 +3202,7 @@ function WorkbenchNodeLayerGroup({
2641
3202
  onBackdropPress();
2642
3203
  } : void 0,
2643
3204
  children: [
2644
- snapPreviewRect ? /* @__PURE__ */ jsx7(
3205
+ snapPreviewRect ? /* @__PURE__ */ jsx8(
2645
3206
  "div",
2646
3207
  {
2647
3208
  className: "workbench-snap-preview",
@@ -2653,7 +3214,7 @@ function WorkbenchNodeLayerGroup({
2653
3214
  }
2654
3215
  }
2655
3216
  ) : null,
2656
- nodeIDs.map((nodeID) => /* @__PURE__ */ jsx7(
3217
+ nodeIDs.map((nodeID) => /* @__PURE__ */ jsx8(
2657
3218
  MemoizedWorkbenchNodeLayerItem,
2658
3219
  {
2659
3220
  fullscreenHeaderMode,
@@ -2702,7 +3263,7 @@ function WorkbenchNodeLayerItem({
2702
3263
  if (!node) {
2703
3264
  return null;
2704
3265
  }
2705
- return /* @__PURE__ */ jsx7(
3266
+ return /* @__PURE__ */ jsx8(
2706
3267
  WorkbenchWindowFrame,
2707
3268
  {
2708
3269
  edgeSnapEnabled,
@@ -2742,7 +3303,7 @@ var MemoizedWorkbenchNodeLayerItem = memo(
2742
3303
  );
2743
3304
 
2744
3305
  // src/react/hooks/useWorkbenchShortcuts.ts
2745
- import { useEffect as useEffect2 } from "react";
3306
+ import { useEffect as useEffect3 } from "react";
2746
3307
 
2747
3308
  // src/react/hooks/workbenchShortcutIntent.ts
2748
3309
  function resolveWorkbenchShortcutIntent(event, options = {}) {
@@ -2801,7 +3362,7 @@ function useWorkbenchShortcuts(options = {}) {
2801
3362
  const controller = useWorkbenchController();
2802
3363
  const enabled = options.enabled ?? true;
2803
3364
  const windowManagementShortcutPreset = options.windowManagementShortcutPreset ?? null;
2804
- useEffect2(() => {
3365
+ useEffect3(() => {
2805
3366
  if (!enabled) {
2806
3367
  return void 0;
2807
3368
  }
@@ -2813,9 +3374,9 @@ function useWorkbenchShortcuts(options = {}) {
2813
3374
  return;
2814
3375
  }
2815
3376
  let handled = false;
2816
- const focusedNode = selectFocusedVisibleWorkbenchNode(
2817
- controller.getSnapshot()
2818
- );
3377
+ const snapshot = controller.getSnapshot();
3378
+ const focusedNode = selectFocusedVisibleWorkbenchNode(snapshot);
3379
+ const isLockedFocusedNode = focusedNode !== null && (snapshot.lockedLayout?.nodeIDs.includes(focusedNode.id) ?? false);
2819
3380
  if (intent.type === "exitFullscreen") {
2820
3381
  if (focusedNode?.displayMode === "fullscreen") {
2821
3382
  controller.commands.exitFullscreen(focusedNode.id);
@@ -2823,15 +3384,25 @@ function useWorkbenchShortcuts(options = {}) {
2823
3384
  }
2824
3385
  } else if (intent.type === "applyFocusedSnapTarget") {
2825
3386
  if (focusedNode) {
2826
- controller.commands.applySnapTarget(
2827
- focusedNode.id,
2828
- intent.snapTarget
2829
- );
3387
+ const lockedDirection = isLockedFocusedNode ? resolveLockedMoveDirection(intent.snapTarget) : null;
3388
+ if (lockedDirection) {
3389
+ controller.commands.moveLockedNode(focusedNode.id, lockedDirection);
3390
+ } else {
3391
+ controller.commands.applySnapTarget(
3392
+ focusedNode.id,
3393
+ intent.snapTarget
3394
+ );
3395
+ }
2830
3396
  handled = true;
2831
3397
  }
2832
3398
  } else if (intent.type === "applyFocusedQuickLayout") {
2833
3399
  if (focusedNode) {
2834
- controller.commands.applyQuickLayout(focusedNode.id, intent.target);
3400
+ const lockedDirection = isLockedFocusedNode ? resolveLockedMoveDirection(intent.target) : null;
3401
+ if (lockedDirection) {
3402
+ controller.commands.moveLockedNode(focusedNode.id, lockedDirection);
3403
+ } else {
3404
+ controller.commands.applyQuickLayout(focusedNode.id, intent.target);
3405
+ }
2835
3406
  handled = true;
2836
3407
  }
2837
3408
  } else {
@@ -2849,6 +3420,20 @@ function useWorkbenchShortcuts(options = {}) {
2849
3420
  };
2850
3421
  }, [controller, enabled, windowManagementShortcutPreset]);
2851
3422
  }
3423
+ function resolveLockedMoveDirection(target) {
3424
+ switch (target) {
3425
+ case "left":
3426
+ return "left";
3427
+ case "right":
3428
+ return "right";
3429
+ case "top":
3430
+ return "up";
3431
+ case "bottom":
3432
+ return "down";
3433
+ default:
3434
+ return null;
3435
+ }
3436
+ }
2852
3437
 
2853
3438
  // src/react/hooks/useWorkbenchSurfaceSize.ts
2854
3439
  import { useLayoutEffect as useLayoutEffect3, useRef as useRef3 } from "react";
@@ -2885,7 +3470,7 @@ function useWorkbenchSurfaceSize(onSizeChange) {
2885
3470
  // src/react/useWorkbenchGenieAnimation.tsx
2886
3471
  import {
2887
3472
  useCallback as useCallback6,
2888
- useEffect as useEffect3,
3473
+ useEffect as useEffect4,
2889
3474
  useRef as useRef4,
2890
3475
  useState as useState4
2891
3476
  } from "react";
@@ -3216,7 +3801,7 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
3216
3801
  }
3217
3802
 
3218
3803
  // src/react/useWorkbenchGenieAnimation.tsx
3219
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
3804
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
3220
3805
  var genieDurationMs = 400;
3221
3806
  var previewCaptureRaceTimeoutMs = 120;
3222
3807
  var scaleMinimizeDurationMs = 220;
@@ -4088,7 +4673,7 @@ function useWorkbenchGenieAnimation({
4088
4673
  },
4089
4674
  [stopAnimation]
4090
4675
  );
4091
- useEffect3(() => () => stopAnimation(false), [stopAnimation]);
4676
+ useEffect4(() => () => stopAnimation(false), [stopAnimation]);
4092
4677
  const startOpenOrRestoreAnimation = useCallback6(
4093
4678
  async (nodeID, anchorKey, generation, dockRectFallback, minimizedNode) => {
4094
4679
  const effectiveMinimizeAnimation = shouldReduceMotion() ? "off" : minimizeAnimation;
@@ -4735,7 +5320,7 @@ function useWorkbenchGenieAnimation({
4735
5320
  writeMinimizedGenieTexture
4736
5321
  ]
4737
5322
  );
4738
- useEffect3(
5323
+ useEffect4(
4739
5324
  () => () => {
4740
5325
  for (const timer of minimizedDockEnterAnimationTimersRef.current.values()) {
4741
5326
  clearTimeout(timer);
@@ -4748,8 +5333,8 @@ function useWorkbenchGenieAnimation({
4748
5333
  );
4749
5334
  return {
4750
5335
  genieLayer: typeof document === "undefined" ? null : createPortal2(
4751
- /* @__PURE__ */ jsxs5(Fragment4, { children: [
4752
- /* @__PURE__ */ jsx8(
5336
+ /* @__PURE__ */ jsxs6(Fragment4, { children: [
5337
+ /* @__PURE__ */ jsx9(
4753
5338
  "canvas",
4754
5339
  {
4755
5340
  ref: canvasRef,
@@ -4758,7 +5343,7 @@ function useWorkbenchGenieAnimation({
4758
5343
  "aria-hidden": true
4759
5344
  }
4760
5345
  ),
4761
- pendingRenderedPreviewCapture ? /* @__PURE__ */ jsx8(
5346
+ pendingRenderedPreviewCapture ? /* @__PURE__ */ jsx9(
4762
5347
  "div",
4763
5348
  {
4764
5349
  ref: renderedPreviewCaptureElementRef,
@@ -4794,7 +5379,7 @@ function useWorkbenchGenieAnimation({
4794
5379
  }
4795
5380
 
4796
5381
  // src/react/WorkbenchSurface.tsx
4797
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
5382
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
4798
5383
  function WorkbenchSurface({
4799
5384
  captureNodePreviewImage,
4800
5385
  className,
@@ -4829,7 +5414,7 @@ function WorkbenchSurface({
4829
5414
  windowChromeMode,
4830
5415
  windowChromeI18n
4831
5416
  }) {
4832
- return /* @__PURE__ */ jsx9(WorkbenchProvider, { controller, children: /* @__PURE__ */ jsx9(
5417
+ return /* @__PURE__ */ jsx10(WorkbenchProvider, { controller, children: /* @__PURE__ */ jsx10(
4833
5418
  WorkbenchSurfaceInner,
4834
5419
  {
4835
5420
  captureNodePreviewImage,
@@ -4922,7 +5507,7 @@ function WorkbenchSurfaceInner({
4922
5507
  enabled: (shortcutsEnabled ?? true) && interactive,
4923
5508
  windowManagementShortcutPreset: windowManagement?.shortcutPreset ?? null
4924
5509
  });
4925
- useEffect4(() => {
5510
+ useEffect5(() => {
4926
5511
  if (!layoutConstraints) {
4927
5512
  return;
4928
5513
  }
@@ -4935,7 +5520,7 @@ function WorkbenchSurfaceInner({
4935
5520
  wallpaper.fit ?? "cover"
4936
5521
  )
4937
5522
  } : void 0;
4938
- return /* @__PURE__ */ jsxs6(
5523
+ return /* @__PURE__ */ jsxs7(
4939
5524
  "div",
4940
5525
  {
4941
5526
  ref,
@@ -4944,7 +5529,7 @@ function WorkbenchSurfaceInner({
4944
5529
  "data-presentation-mode": presentation?.mode ?? "default",
4945
5530
  "data-workbench-interactive": interactive ? "true" : "false",
4946
5531
  children: [
4947
- wallpaper ? /* @__PURE__ */ jsx9(
5532
+ wallpaper ? /* @__PURE__ */ jsx10(
4948
5533
  "div",
4949
5534
  {
4950
5535
  className: "workbench-surface__wallpaper",
@@ -4952,9 +5537,10 @@ function WorkbenchSurfaceInner({
4952
5537
  "aria-hidden": true
4953
5538
  }
4954
5539
  ) : null,
4955
- renderTopChrome ? /* @__PURE__ */ jsx9("div", { className: "workbench-surface__top-chrome", children: renderTopChrome() }) : null,
5540
+ renderTopChrome ? /* @__PURE__ */ jsx10("div", { className: "workbench-surface__top-chrome", children: renderTopChrome() }) : null,
4956
5541
  renderBackdrop ? renderBackdrop() : null,
4957
- /* @__PURE__ */ jsx9(
5542
+ presentation?.mode === "mission-control" ? null : /* @__PURE__ */ jsx10(WorkbenchLockedSlotLayer, {}),
5543
+ /* @__PURE__ */ jsx10(
4958
5544
  WorkbenchNodeLayer,
4959
5545
  {
4960
5546
  genie,
@@ -4972,7 +5558,7 @@ function WorkbenchSurfaceInner({
4972
5558
  windowChromeI18n
4973
5559
  }
4974
5560
  ),
4975
- /* @__PURE__ */ jsx9(
5561
+ /* @__PURE__ */ jsx10(
4976
5562
  WorkbenchDockFrame,
4977
5563
  {
4978
5564
  dockPlacement,
@@ -4981,7 +5567,7 @@ function WorkbenchSurfaceInner({
4981
5567
  renderDock
4982
5568
  }
4983
5569
  ),
4984
- renderBottomChrome ? /* @__PURE__ */ jsx9("div", { className: "workbench-surface__bottom-chrome", children: renderBottomChrome() }) : null,
5570
+ renderBottomChrome ? /* @__PURE__ */ jsx10("div", { className: "workbench-surface__bottom-chrome", children: renderBottomChrome() }) : null,
4985
5571
  renderOverlay ? renderOverlay() : null,
4986
5572
  genie.genieLayer
4987
5573
  ]
@@ -5146,7 +5732,7 @@ function resolveHostClosePreparer(contributions) {
5146
5732
  }
5147
5733
 
5148
5734
  // src/host/useWorkbenchHostRuntime.ts
5149
- import { useEffect as useEffect5, useMemo as useMemo4, useState as useState5 } from "react";
5735
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState5 } from "react";
5150
5736
 
5151
5737
  // src/store/createDerivedSnapshotGetter.ts
5152
5738
  function createDerivedSnapshotGetter(input) {
@@ -5184,8 +5770,8 @@ function createWorkbenchHostMissionControlAdapter(input) {
5184
5770
  }
5185
5771
  });
5186
5772
  return {
5187
- applyLayoutPreset(nodeIds, preset) {
5188
- input.controller.commands.applyLayoutPreset(nodeIds, preset);
5773
+ applyLayoutPreset(nodeIds, preset, lock) {
5774
+ input.controller.commands.applyLayoutPreset(nodeIds, preset, lock);
5189
5775
  },
5190
5776
  focusNode(nodeId) {
5191
5777
  if (input.activateNode) {
@@ -7028,7 +7614,7 @@ function useWorkbenchHostRuntime({
7028
7614
  }) {
7029
7615
  const [externalStateRevision, bumpExternalStateRevision] = useState5(0);
7030
7616
  const [, bumpHydrationRevision] = useState5(0);
7031
- const hostSession = useMemo4(() => {
7617
+ const hostSession = useMemo5(() => {
7032
7618
  logWorkbenchHostDebug("create-session", debugDiagnostics, {
7033
7619
  nodeTypeIDs: nodes.map((node) => node.typeId),
7034
7620
  projectedNodeCount: projectedNodes?.length ?? 0,
@@ -7053,32 +7639,32 @@ function useWorkbenchHostRuntime({
7053
7639
  snapshotRepository,
7054
7640
  workspaceId
7055
7641
  ]);
7056
- const hostI18n = useMemo4(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
7057
- const missionControlI18n = useMemo4(
7642
+ const hostI18n = useMemo5(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
7643
+ const missionControlI18n = useMemo5(
7058
7644
  () => createWorkbenchMissionControlI18nRuntime(i18n),
7059
7645
  [i18n]
7060
7646
  );
7061
- const windowChromeI18n = useMemo4(
7647
+ const windowChromeI18n = useMemo5(
7062
7648
  () => createWorkbenchWindowChromeI18nRuntime(i18n),
7063
7649
  [i18n]
7064
7650
  );
7065
- const nodeDefinitionByType = useMemo4(
7651
+ const nodeDefinitionByType = useMemo5(
7066
7652
  () => new Map(nodes.map((definition) => [definition.typeId, definition])),
7067
7653
  [nodes]
7068
7654
  );
7069
7655
  const isHydrating = hostSession.isHydrating?.() ?? false;
7070
- const missionControlAdapter = useMemo4(
7656
+ const missionControlAdapter = useMemo5(
7071
7657
  () => missionControlEnabled && !isHydrating ? createWorkbenchHostMissionControlAdapter({
7072
7658
  activateNode: hostSession.activateNode.bind(hostSession),
7073
7659
  controller: hostSession.controller
7074
7660
  }) : null,
7075
7661
  [hostSession.controller, isHydrating, missionControlEnabled]
7076
7662
  );
7077
- const chromeController = useMemo4(
7663
+ const chromeController = useMemo5(
7078
7664
  () => isHydrating ? createReadOnlyWorkbenchController(hostSession.controller) : hostSession.controller,
7079
7665
  [hostSession.controller, isHydrating]
7080
7666
  );
7081
- const chromeContext = useMemo4(
7667
+ const chromeContext = useMemo5(
7082
7668
  () => ({
7083
7669
  activateNode: hostSession.activateNode.bind(hostSession),
7084
7670
  controller: chromeController,
@@ -7087,7 +7673,7 @@ function useWorkbenchHostRuntime({
7087
7673
  }),
7088
7674
  [chromeController, hostSession]
7089
7675
  );
7090
- useEffect5(() => {
7676
+ useEffect6(() => {
7091
7677
  let isCurrent = true;
7092
7678
  void hostSession.load().finally(() => {
7093
7679
  if (isCurrent) {
@@ -7102,13 +7688,13 @@ function useWorkbenchHostRuntime({
7102
7688
  hostSession.dispose();
7103
7689
  };
7104
7690
  }, [debugDiagnostics, hostSession, workspaceId]);
7105
- useEffect5(() => {
7691
+ useEffect6(() => {
7106
7692
  onHandleReady?.(hostSession);
7107
7693
  return () => {
7108
7694
  onHandleReady?.(null);
7109
7695
  };
7110
7696
  }, [hostSession, onHandleReady]);
7111
- useEffect5(() => {
7697
+ useEffect6(() => {
7112
7698
  if (!onMissionControlAdapterReady) {
7113
7699
  return void 0;
7114
7700
  }
@@ -7117,10 +7703,10 @@ function useWorkbenchHostRuntime({
7117
7703
  onMissionControlAdapterReady(null);
7118
7704
  };
7119
7705
  }, [missionControlAdapter, onMissionControlAdapterReady]);
7120
- useEffect5(() => {
7706
+ useEffect6(() => {
7121
7707
  hostSession.reconcileProjectedNodes(projectedNodes ?? []);
7122
7708
  }, [hostSession, projectedNodes]);
7123
- useEffect5(() => {
7709
+ useEffect6(() => {
7124
7710
  if (!externalStateSource?.subscribe) {
7125
7711
  return void 0;
7126
7712
  }
@@ -7176,14 +7762,14 @@ function logWorkbenchHostDebug(event, debugDiagnostics, payload) {
7176
7762
  }
7177
7763
 
7178
7764
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
7179
- import { Component, useCallback as useCallback11, useMemo as useMemo6 } from "react";
7765
+ import { Component, useCallback as useCallback11, useMemo as useMemo7 } from "react";
7180
7766
 
7181
7767
  // src/host/WorkbenchHostDock.tsx
7182
7768
  import {
7183
7769
  useCallback as useCallback10,
7184
- useEffect as useEffect9,
7770
+ useEffect as useEffect10,
7185
7771
  useLayoutEffect as useLayoutEffect5,
7186
- useMemo as useMemo5,
7772
+ useMemo as useMemo6,
7187
7773
  useRef as useRef8,
7188
7774
  useState as useState8
7189
7775
  } from "react";
@@ -7288,7 +7874,7 @@ function isWorkbenchDockEntryBlocked(entry) {
7288
7874
  }
7289
7875
 
7290
7876
  // src/host/dockMagnification.ts
7291
- import { useCallback as useCallback8, useEffect as useEffect6, useRef as useRef5 } from "react";
7877
+ import { useCallback as useCallback8, useEffect as useEffect7, useRef as useRef5 } from "react";
7292
7878
 
7293
7879
  // src/host/dockMagnificationBounds.ts
7294
7880
  function resolveDockMagnificationViewportBounds(viewportRect, dockPlacement) {
@@ -7888,7 +8474,7 @@ function useDockMagnification({
7888
8474
  );
7889
8475
  handleGlobalPointerMoveRef.current = handlePointerMove;
7890
8476
  handleGlobalPointerCancelRef.current = handleGlobalPointerCancel;
7891
- useEffect6(() => {
8477
+ useEffect7(() => {
7892
8478
  if (typeof document === "undefined") {
7893
8479
  return;
7894
8480
  }
@@ -8016,7 +8602,7 @@ function useDockMagnification({
8016
8602
  entryRampStartedAtRef.current = null;
8017
8603
  setMagnifyActive(false);
8018
8604
  }, [setMagnifyActive, slotRefs, stopAnimation, stopGlobalPointerTracking]);
8019
- useEffect6(
8605
+ useEffect7(
8020
8606
  () => () => {
8021
8607
  resetMagnification();
8022
8608
  },
@@ -8122,7 +8708,7 @@ function orderWorkbenchMinimizedDockNodes(input) {
8122
8708
  }
8123
8709
 
8124
8710
  // src/host/minimizedDockStackPromotion.ts
8125
- import { useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
8711
+ import { useEffect as useEffect8, useRef as useRef6, useState as useState6 } from "react";
8126
8712
  var minimizedDockStackPromotionDurationMs = 520;
8127
8713
  function detectMinimizedDockStackPromotion(previous, next) {
8128
8714
  const previousVisibleNodeIds = new Set(
@@ -8146,7 +8732,7 @@ function useMinimizedDockStackPromotion(slots) {
8146
8732
  const promotionTimerRef = useRef6(null);
8147
8733
  const [promotedNodeId, setPromotedNodeId] = useState6(null);
8148
8734
  const [stackDispatching, setStackDispatching] = useState6(false);
8149
- useEffect7(() => {
8735
+ useEffect8(() => {
8150
8736
  const promotedNodeId2 = detectMinimizedDockStackPromotion(
8151
8737
  previousSlotsRef.current,
8152
8738
  slots
@@ -8213,7 +8799,7 @@ function resolveWorkbenchMinimizedDockRestoreIntent(input) {
8213
8799
  import {
8214
8800
  forwardRef,
8215
8801
  useCallback as useCallback9,
8216
- useEffect as useEffect8,
8802
+ useEffect as useEffect9,
8217
8803
  useLayoutEffect as useLayoutEffect4,
8218
8804
  useRef as useRef7,
8219
8805
  useState as useState7
@@ -8362,7 +8948,7 @@ function resolveMinimizedStackTrackTranslateXPx(input) {
8362
8948
  }
8363
8949
 
8364
8950
  // src/host/WorkbenchHostDockPopup.tsx
8365
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
8951
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
8366
8952
  var dockPopupCardWidthPx = 165;
8367
8953
  var dockPopupGridGapPx = 8;
8368
8954
  var dockPopupPanelPaddingInlinePx = 12;
@@ -8540,7 +9126,7 @@ function WorkbenchHostDockPopup({
8540
9126
  } : {}
8541
9127
  };
8542
9128
  const popupDiagnosticKey = items.map((item) => item.node.id).join("|");
8543
- useEffect8(() => {
9129
+ useEffect9(() => {
8544
9130
  logWorkbenchDockPopupDebug("dock.popup.rendered", debugDiagnostics, {
8545
9131
  hasCapturePreview: Boolean(capturePreview),
8546
9132
  itemCount: popupDiagnosticKey ? popupDiagnosticKey.split("|").length : 0,
@@ -8583,7 +9169,7 @@ function WorkbenchHostDockPopup({
8583
9169
  cardRefCallbacksRef.current.set(nodeId, callback);
8584
9170
  return callback;
8585
9171
  }, []);
8586
- useEffect8(() => {
9172
+ useEffect9(() => {
8587
9173
  if (!isLeftMinimizedStack) {
8588
9174
  return;
8589
9175
  }
@@ -8595,7 +9181,7 @@ function WorkbenchHostDockPopup({
8595
9181
  document.body.removeAttribute("data-desktop-dock-minimized-stack-open");
8596
9182
  };
8597
9183
  }, [isLeftMinimizedStack]);
8598
- useEffect8(() => {
9184
+ useEffect9(() => {
8599
9185
  const handlePointerDown = (event) => {
8600
9186
  if (!(event.target instanceof Element)) {
8601
9187
  onClose();
@@ -8623,13 +9209,13 @@ function WorkbenchHostDockPopup({
8623
9209
  const previewCaptureKey = items.map(
8624
9210
  (item) => `${item.node.id}:${previewCacheToken(item.preview)}:${item.previewRevision ?? ""}`
8625
9211
  ).join("|");
8626
- useEffect8(() => {
9212
+ useEffect9(() => {
8627
9213
  if (!isMinimizedStack) {
8628
9214
  return;
8629
9215
  }
8630
9216
  setMinimizedStackScrollOffset(initialMinimizedStackScrollOffset);
8631
9217
  }, [initialMinimizedStackScrollOffset, isMinimizedStack, items.length]);
8632
- useEffect8(() => {
9218
+ useEffect9(() => {
8633
9219
  if (!isMinimizedStack) {
8634
9220
  return;
8635
9221
  }
@@ -8650,7 +9236,7 @@ function WorkbenchHostDockPopup({
8650
9236
  viewport.addEventListener("wheel", handleWheel, { passive: false });
8651
9237
  return () => viewport.removeEventListener("wheel", handleWheel);
8652
9238
  }, [isMinimizedStack, minimizedStackMaxScrollOffset]);
8653
- useEffect8(() => {
9239
+ useEffect9(() => {
8654
9240
  if (!capturePreview || isContextMenu) {
8655
9241
  return;
8656
9242
  }
@@ -8867,7 +9453,7 @@ function WorkbenchHostDockPopup({
8867
9453
  previewCaptureKey,
8868
9454
  resolveDockPreviewCacheKey2
8869
9455
  ]);
8870
- const content = /* @__PURE__ */ jsx10(
9456
+ const content = /* @__PURE__ */ jsx11(
8871
9457
  "div",
8872
9458
  {
8873
9459
  ref: popupRootRef,
@@ -8876,7 +9462,7 @@ function WorkbenchHostDockPopup({
8876
9462
  "data-desktop-dock-popup-root": "true",
8877
9463
  "data-popup-variant": resolvedVariant,
8878
9464
  style: popupStyle,
8879
- children: /* @__PURE__ */ jsx10(
9465
+ children: /* @__PURE__ */ jsx11(
8880
9466
  "div",
8881
9467
  {
8882
9468
  "aria-label": label,
@@ -8892,7 +9478,7 @@ function WorkbenchHostDockPopup({
8892
9478
  onPointerLeave: isMinimizedStack ? () => setPointer(null) : void 0,
8893
9479
  role: "dialog",
8894
9480
  style: panelStyle,
8895
- children: isContextMenu ? /* @__PURE__ */ jsx10(
9481
+ children: isContextMenu ? /* @__PURE__ */ jsx11(
8896
9482
  WorkbenchHostDockContextMenu,
8897
9483
  {
8898
9484
  canCreateNew: showCreateNew !== false,
@@ -8915,9 +9501,9 @@ function WorkbenchHostDockPopup({
8915
9501
  showAllWindowsLabel,
8916
9502
  showOpen: showOpen === true
8917
9503
  }
8918
- ) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
8919
- /* @__PURE__ */ jsx10("div", { className: "mb-2.5 flex items-center justify-between", children: /* @__PURE__ */ jsx10("span", { className: "min-w-0 truncate text-sm font-semibold", children: label }) }),
8920
- isMinimizedStack ? /* @__PURE__ */ jsx10(
9504
+ ) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
9505
+ /* @__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 }) }),
9506
+ isMinimizedStack ? /* @__PURE__ */ jsx11(
8921
9507
  "div",
8922
9508
  {
8923
9509
  ref: minimizedStackViewportRef,
@@ -8926,7 +9512,7 @@ function WorkbenchHostDockPopup({
8926
9512
  height: minimizedStackViewportHeightPx,
8927
9513
  ...isLeftMinimizedStack ? { paddingLeft: minimizedStackLeftGutterPx } : {}
8928
9514
  },
8929
- children: /* @__PURE__ */ jsx10(
9515
+ children: /* @__PURE__ */ jsx11(
8930
9516
  "div",
8931
9517
  {
8932
9518
  className: "desktop-dock-popup__minimized-stack-track",
@@ -8945,7 +9531,7 @@ function WorkbenchHostDockPopup({
8945
9531
  capturedPreview,
8946
9532
  Boolean(capturePreview)
8947
9533
  );
8948
- return /* @__PURE__ */ jsx10(
9534
+ return /* @__PURE__ */ jsx11(
8949
9535
  WorkbenchHostDockPopupCard,
8950
9536
  {
8951
9537
  ref: registerCard(item.node.id),
@@ -8974,7 +9560,7 @@ function WorkbenchHostDockPopup({
8974
9560
  }
8975
9561
  )
8976
9562
  }
8977
- ) : /* @__PURE__ */ jsxs7("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: [
9563
+ ) : /* @__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: [
8978
9564
  items.map((item) => {
8979
9565
  const previewMemoryKey = resolveDockPopupPreviewMemoryKey(
8980
9566
  item.node,
@@ -8986,7 +9572,7 @@ function WorkbenchHostDockPopup({
8986
9572
  capturedPreview,
8987
9573
  Boolean(capturePreview)
8988
9574
  );
8989
- return /* @__PURE__ */ jsx10(
9575
+ return /* @__PURE__ */ jsx11(
8990
9576
  WorkbenchHostDockPopupCard,
8991
9577
  {
8992
9578
  ref: registerCard(item.node.id),
@@ -9001,14 +9587,14 @@ function WorkbenchHostDockPopup({
9001
9587
  item.node.id
9002
9588
  );
9003
9589
  }),
9004
- showCreateNew !== false ? /* @__PURE__ */ jsxs7(
9590
+ showCreateNew !== false ? /* @__PURE__ */ jsxs8(
9005
9591
  "button",
9006
9592
  {
9007
9593
  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)]",
9008
9594
  type: "button",
9009
9595
  onClick: onCreateNew,
9010
9596
  children: [
9011
- /* @__PURE__ */ jsx10(
9597
+ /* @__PURE__ */ jsx11(
9012
9598
  FileCreateIcon,
9013
9599
  {
9014
9600
  "aria-hidden": "true",
@@ -9016,7 +9602,7 @@ function WorkbenchHostDockPopup({
9016
9602
  size: 28
9017
9603
  }
9018
9604
  ),
9019
- /* @__PURE__ */ jsx10("span", { className: "text-xs font-semibold text-[var(--text-primary)]", children: newWindowLabel })
9605
+ /* @__PURE__ */ jsx11("span", { className: "text-xs font-semibold text-[var(--text-primary)]", children: newWindowLabel })
9020
9606
  ]
9021
9607
  }
9022
9608
  ) : null
@@ -9057,14 +9643,14 @@ function WorkbenchHostDockContextMenu({
9057
9643
  const hasOpenCommand = !hasOpenWindows;
9058
9644
  const hasDockActionGroup = Boolean(dockRetention) || hasNewWindowCommand || hasOpenCommand;
9059
9645
  const hasWindowActionGroup = hasOpenWindows;
9060
- return /* @__PURE__ */ jsxs7(
9646
+ return /* @__PURE__ */ jsxs8(
9061
9647
  "div",
9062
9648
  {
9063
9649
  className: "flex min-w-0 flex-col gap-1",
9064
9650
  "data-desktop-dock-context-menu": "true",
9065
9651
  role: "menu",
9066
9652
  children: [
9067
- hasOpenWindows ? /* @__PURE__ */ jsx10(Fragment5, { children: /* @__PURE__ */ jsx10("div", { className: "max-h-48 min-w-0 overflow-auto overscroll-contain", children: items.map((item) => /* @__PURE__ */ jsx10(
9653
+ 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(
9068
9654
  WorkbenchHostDockContextMenuItem,
9069
9655
  {
9070
9656
  checked: !item.isMinimized,
@@ -9073,12 +9659,12 @@ function WorkbenchHostDockContextMenu({
9073
9659
  },
9074
9660
  item.node.id
9075
9661
  )) }) }) : null,
9076
- hasOpenWindows && (hasDockActionGroup || hasWindowActionGroup) ? /* @__PURE__ */ jsx10(WorkbenchHostDockContextMenuSeparator, {}) : null,
9077
- dockRetention ? /* @__PURE__ */ jsx10(
9662
+ hasOpenWindows && (hasDockActionGroup || hasWindowActionGroup) ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
9663
+ dockRetention ? /* @__PURE__ */ jsx11(
9078
9664
  WorkbenchHostDockContextMenuItem,
9079
9665
  {
9080
9666
  checked: dockRetention.checked,
9081
- checkedIcon: /* @__PURE__ */ jsx10(
9667
+ checkedIcon: /* @__PURE__ */ jsx11(
9082
9668
  PinFilledIcon,
9083
9669
  {
9084
9670
  "aria-hidden": "true",
@@ -9086,61 +9672,61 @@ function WorkbenchHostDockContextMenu({
9086
9672
  }
9087
9673
  ),
9088
9674
  disabled: dockRetention.disabled,
9089
- icon: /* @__PURE__ */ jsx10(PinIcon, { "aria-hidden": "true", className: "size-4" }),
9675
+ icon: /* @__PURE__ */ jsx11(PinIcon, { "aria-hidden": "true", className: "size-4" }),
9090
9676
  label: dockRetention.pendingLabel ?? dockRetention.label,
9091
9677
  onSelect: onRunDockRetentionAction
9092
9678
  }
9093
9679
  ) : null,
9094
- hasNewWindowCommand ? /* @__PURE__ */ jsx10(
9680
+ hasNewWindowCommand ? /* @__PURE__ */ jsx11(
9095
9681
  WorkbenchHostDockContextMenuItem,
9096
9682
  {
9097
- icon: /* @__PURE__ */ jsx10(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
9683
+ icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
9098
9684
  label: newWindowLabel,
9099
9685
  onSelect: onCreateNew
9100
9686
  }
9101
9687
  ) : null,
9102
- hasOpenCommand ? /* @__PURE__ */ jsx10(
9688
+ hasOpenCommand ? /* @__PURE__ */ jsx11(
9103
9689
  WorkbenchHostDockContextMenuItem,
9104
9690
  {
9105
9691
  disabled: !showOpen,
9106
- icon: /* @__PURE__ */ jsx10(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
9692
+ icon: /* @__PURE__ */ jsx11(FileCreateIcon, { "aria-hidden": "true", className: "size-4" }),
9107
9693
  label: openLabel,
9108
9694
  onSelect: onCreateNew
9109
9695
  }
9110
9696
  ) : null,
9111
- hasOpenWindows ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
9112
- hasDockActionGroup ? /* @__PURE__ */ jsx10(WorkbenchHostDockContextMenuSeparator, {}) : null,
9113
- canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx10(
9697
+ hasOpenWindows ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
9698
+ hasDockActionGroup ? /* @__PURE__ */ jsx11(WorkbenchHostDockContextMenuSeparator, {}) : null,
9699
+ canShowAllWindows && onShowAllWindows ? /* @__PURE__ */ jsx11(
9114
9700
  WorkbenchHostDockContextMenuItem,
9115
9701
  {
9116
- icon: /* @__PURE__ */ jsx10(OverviewLayoutIcon, { "aria-hidden": "true", className: "size-4" }),
9702
+ icon: /* @__PURE__ */ jsx11(OverviewLayoutIcon, { "aria-hidden": "true", className: "size-4" }),
9117
9703
  label: showAllWindowsLabel,
9118
9704
  onSelect: onShowAllWindows
9119
9705
  }
9120
9706
  ) : null,
9121
- /* @__PURE__ */ jsx10(
9707
+ /* @__PURE__ */ jsx11(
9122
9708
  WorkbenchHostDockContextMenuItem,
9123
9709
  {
9124
9710
  disabled: !canEnterFullscreen || !onEnterFullscreen,
9125
- icon: /* @__PURE__ */ jsx10(MaximizeIcon, { "aria-hidden": "true", className: "size-4" }),
9711
+ icon: /* @__PURE__ */ jsx11(MaximizeIcon, { "aria-hidden": "true", className: "size-4" }),
9126
9712
  label: fullscreenLabel,
9127
9713
  onSelect: onEnterFullscreen
9128
9714
  }
9129
9715
  ),
9130
- /* @__PURE__ */ jsx10(
9716
+ /* @__PURE__ */ jsx11(
9131
9717
  WorkbenchHostDockContextMenuItem,
9132
9718
  {
9133
9719
  disabled: !onHide,
9134
- icon: /* @__PURE__ */ jsx10(MinimizeIcon, { "aria-hidden": "true", className: "size-4" }),
9720
+ icon: /* @__PURE__ */ jsx11(MinimizeIcon, { "aria-hidden": "true", className: "size-4" }),
9135
9721
  label: hideLabel,
9136
9722
  onSelect: onHide
9137
9723
  }
9138
9724
  ),
9139
- /* @__PURE__ */ jsx10(
9725
+ /* @__PURE__ */ jsx11(
9140
9726
  WorkbenchHostDockContextMenuItem,
9141
9727
  {
9142
9728
  disabled: !onQuit,
9143
- icon: /* @__PURE__ */ jsx10(CloseIcon, { "aria-hidden": "true", className: "size-4" }),
9729
+ icon: /* @__PURE__ */ jsx11(CloseIcon, { "aria-hidden": "true", className: "size-4" }),
9144
9730
  label: quitLabel,
9145
9731
  onSelect: onQuit
9146
9732
  }
@@ -9158,7 +9744,7 @@ function WorkbenchHostDockContextMenuItem({
9158
9744
  label,
9159
9745
  onSelect
9160
9746
  }) {
9161
- return /* @__PURE__ */ jsxs7(
9747
+ return /* @__PURE__ */ jsxs8(
9162
9748
  "button",
9163
9749
  {
9164
9750
  className: cn(
@@ -9175,20 +9761,20 @@ function WorkbenchHostDockContextMenuItem({
9175
9761
  onSelect();
9176
9762
  },
9177
9763
  children: [
9178
- /* @__PURE__ */ jsx10("span", { className: "flex size-4 shrink-0 items-center justify-center text-[var(--text-secondary)]", children: checked && checkedIcon ? checkedIcon : checked ? /* @__PURE__ */ jsx10(
9764
+ /* @__PURE__ */ jsx11("span", { className: "flex size-4 shrink-0 items-center justify-center text-[var(--text-secondary)]", children: checked && checkedIcon ? checkedIcon : checked ? /* @__PURE__ */ jsx11(
9179
9765
  CheckIcon,
9180
9766
  {
9181
9767
  "aria-hidden": "true",
9182
9768
  className: "size-4 text-[var(--tutti-purple)]"
9183
9769
  }
9184
9770
  ) : icon ?? null }),
9185
- /* @__PURE__ */ jsx10("span", { className: "min-w-0 truncate", children: label })
9771
+ /* @__PURE__ */ jsx11("span", { className: "min-w-0 truncate", children: label })
9186
9772
  ]
9187
9773
  }
9188
9774
  );
9189
9775
  }
9190
9776
  function WorkbenchHostDockContextMenuSeparator() {
9191
- return /* @__PURE__ */ jsx10(
9777
+ return /* @__PURE__ */ jsx11(
9192
9778
  "div",
9193
9779
  {
9194
9780
  "aria-hidden": "true",
@@ -9304,7 +9890,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9304
9890
  const isMinimizedStack = variant === "minimized-stack";
9305
9891
  const [isLaunching, setIsLaunching] = useState7(false);
9306
9892
  const launchTimerRef = useRef7(null);
9307
- useEffect8(
9893
+ useEffect9(
9308
9894
  () => () => {
9309
9895
  if (launchTimerRef.current !== null) {
9310
9896
  clearTimeout(launchTimerRef.current);
@@ -9337,7 +9923,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9337
9923
  [handleSelect]
9338
9924
  );
9339
9925
  const hasReadyPreview = previewState.status === "ready";
9340
- return /* @__PURE__ */ jsxs7(
9926
+ return /* @__PURE__ */ jsxs8(
9341
9927
  "div",
9342
9928
  {
9343
9929
  ref,
@@ -9352,7 +9938,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9352
9938
  "data-minimized": item.isMinimized ? "true" : void 0,
9353
9939
  style,
9354
9940
  children: [
9355
- /* @__PURE__ */ jsxs7(
9941
+ /* @__PURE__ */ jsxs8(
9356
9942
  "div",
9357
9943
  {
9358
9944
  "aria-label": title,
@@ -9366,12 +9952,12 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9366
9952
  onClick: handleSelect,
9367
9953
  onKeyDown: handleSelectKeyDown,
9368
9954
  children: [
9369
- /* @__PURE__ */ jsx10(WorkbenchHostDockPopupCardPreview, { previewState }),
9370
- labelMode === "hover-overlay" && item.title?.trim() ? /* @__PURE__ */ jsx10(WorkbenchHostDockPopupCardLabel, { title: item.title }) : null
9955
+ /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardPreview, { previewState }),
9956
+ labelMode === "hover-overlay" && item.title?.trim() ? /* @__PURE__ */ jsx11(WorkbenchHostDockPopupCardLabel, { title: item.title }) : null
9371
9957
  ]
9372
9958
  }
9373
9959
  ),
9374
- /* @__PURE__ */ jsx10(
9960
+ /* @__PURE__ */ jsx11(
9375
9961
  Button2,
9376
9962
  {
9377
9963
  "aria-label": closeWindowLabel(title),
@@ -9385,10 +9971,10 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9385
9971
  event.stopPropagation();
9386
9972
  onCloseNode(item.node.id);
9387
9973
  },
9388
- children: /* @__PURE__ */ jsx10(CloseIcon, { className: "size-3.5" })
9974
+ children: /* @__PURE__ */ jsx11(CloseIcon, { className: "size-3.5" })
9389
9975
  }
9390
9976
  ),
9391
- item.isFocused ? /* @__PURE__ */ jsx10(
9977
+ item.isFocused ? /* @__PURE__ */ jsx11(
9392
9978
  "span",
9393
9979
  {
9394
9980
  "aria-hidden": "true",
@@ -9396,7 +9982,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
9396
9982
  "data-desktop-dock-popup-card-active-overlay": "true"
9397
9983
  }
9398
9984
  ) : null,
9399
- isMinimizedStack ? /* @__PURE__ */ jsx10("span", { className: "desktop-dock-popup__fan-title-tip", title, children: title }) : null
9985
+ isMinimizedStack ? /* @__PURE__ */ jsx11("span", { className: "desktop-dock-popup__fan-title-tip", title, children: title }) : null
9400
9986
  ]
9401
9987
  }
9402
9988
  );
@@ -9405,23 +9991,23 @@ function WorkbenchHostDockPopupCardPreview({
9405
9991
  previewState
9406
9992
  }) {
9407
9993
  if (previewState.status !== "ready") {
9408
- return /* @__PURE__ */ jsxs7(
9994
+ return /* @__PURE__ */ jsxs8(
9409
9995
  "span",
9410
9996
  {
9411
9997
  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]",
9412
9998
  "aria-hidden": "true",
9413
9999
  "data-preview-state": previewState.status,
9414
10000
  children: [
9415
- /* @__PURE__ */ jsx10("span", { className: "block h-[7px] w-[72%] rounded-full bg-transparency-hover" }),
9416
- /* @__PURE__ */ jsx10("span", { className: "block h-[7px] w-[58%] rounded-full bg-transparency-hover" }),
9417
- /* @__PURE__ */ jsx10("span", { className: "block h-[7px] w-[34%] rounded-full bg-transparency-hover" })
10001
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[72%] rounded-full bg-transparency-hover" }),
10002
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[58%] rounded-full bg-transparency-hover" }),
10003
+ /* @__PURE__ */ jsx11("span", { className: "block h-[7px] w-[34%] rounded-full bg-transparency-hover" })
9418
10004
  ]
9419
10005
  }
9420
10006
  );
9421
10007
  }
9422
10008
  const preview = previewState.preview;
9423
10009
  if (preview.kind === "component") {
9424
- return /* @__PURE__ */ jsx10(
10010
+ return /* @__PURE__ */ jsx11(
9425
10011
  "span",
9426
10012
  {
9427
10013
  className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
@@ -9432,14 +10018,14 @@ function WorkbenchHostDockPopupCardPreview({
9432
10018
  }
9433
10019
  );
9434
10020
  }
9435
- return /* @__PURE__ */ jsx10(
10021
+ return /* @__PURE__ */ jsx11(
9436
10022
  "span",
9437
10023
  {
9438
10024
  className: "block min-h-0 min-w-0 flex-1 overflow-hidden rounded-md",
9439
10025
  "aria-hidden": "true",
9440
10026
  "data-preview-kind": preview.kind,
9441
10027
  "data-preview-state": previewState.status,
9442
- children: /* @__PURE__ */ jsx10(
10028
+ children: /* @__PURE__ */ jsx11(
9443
10029
  "img",
9444
10030
  {
9445
10031
  alt: "",
@@ -9452,7 +10038,7 @@ function WorkbenchHostDockPopupCardPreview({
9452
10038
  );
9453
10039
  }
9454
10040
  function WorkbenchHostDockPopupCardLabel({ title }) {
9455
- return /* @__PURE__ */ jsx10(
10041
+ return /* @__PURE__ */ jsx11(
9456
10042
  "span",
9457
10043
  {
9458
10044
  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",
@@ -9460,17 +10046,18 @@ function WorkbenchHostDockPopupCardLabel({ title }) {
9460
10046
  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%)"
9461
10047
  },
9462
10048
  title,
9463
- children: /* @__PURE__ */ jsx10("span", { className: "desktop-dock-popup__title-viewport block min-w-0 flex-1 overflow-hidden whitespace-nowrap", children: /* @__PURE__ */ jsx10("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 }) })
10049
+ 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 }) })
9464
10050
  }
9465
10051
  );
9466
10052
  }
9467
10053
 
9468
10054
  // src/host/WorkbenchHostDock.tsx
9469
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
10055
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
9470
10056
  var minimizedDockPreviewViewport = {
9471
10057
  height: 34.2,
9472
10058
  width: 46.8
9473
10059
  };
10060
+ var dockPopupNewWindowLaunchSource = "dock-popup-new-window";
9474
10061
  function stripDockDescriptionTerminalPunctuation(value) {
9475
10062
  const trimmed = value.trim();
9476
10063
  if (!trimmed || trimmed.endsWith("...") || trimmed.endsWith("\u2026")) {
@@ -9510,7 +10097,7 @@ function WorkbenchHostDock({
9510
10097
  onMissionControlRequestOpen,
9511
10098
  workspaceId
9512
10099
  }) {
9513
- const minimizedNodeIDs = useMemo5(
10100
+ const minimizedNodeIDs = useMemo6(
9514
10101
  () => new Set(context.minimizedNodes.map((node) => node.id)),
9515
10102
  [context.minimizedNodes]
9516
10103
  );
@@ -9591,7 +10178,7 @@ function WorkbenchHostDock({
9591
10178
  labelTooltipOpenTimerRef.current = null;
9592
10179
  labelTooltipScheduledPointRef.current = null;
9593
10180
  }, []);
9594
- useEffect9(
10181
+ useEffect10(
9595
10182
  () => () => {
9596
10183
  clearHoverPanelCloseTimer();
9597
10184
  clearHoverPanelOpenTimer();
@@ -9685,7 +10272,7 @@ function WorkbenchHostDock({
9685
10272
  pendingDockStateRefreshRef.current = false;
9686
10273
  setDockStateRevision((revision) => revision + 1);
9687
10274
  }, []);
9688
- useEffect9(() => {
10275
+ useEffect10(() => {
9689
10276
  if (!dockStateSource) {
9690
10277
  return void 0;
9691
10278
  }
@@ -9697,14 +10284,14 @@ function WorkbenchHostDock({
9697
10284
  setDockStateRevision((revision) => revision + 1);
9698
10285
  });
9699
10286
  }, [dockStateSource]);
9700
- const renderedDockEntries = useMemo5(
10287
+ const renderedDockEntries = useMemo6(
9701
10288
  () => dockEntries.map((entry) => {
9702
10289
  const dynamicState = dockStateSource?.getEntryState(entry.id);
9703
10290
  return dynamicState ? { ...entry, ...dynamicState } : entry;
9704
10291
  }),
9705
10292
  [dockEntries, dockStateRevision, dockStateSource]
9706
10293
  );
9707
- const resolvedEntries = useMemo5(
10294
+ const resolvedEntries = useMemo6(
9708
10295
  () => resolveWorkbenchDockEntries({
9709
10296
  dockEntries: renderedDockEntries,
9710
10297
  minimizedNodeIds: minimizedNodeIDs,
@@ -9712,7 +10299,7 @@ function WorkbenchHostDock({
9712
10299
  }),
9713
10300
  [context.nodes, minimizedNodeIDs, renderedDockEntries]
9714
10301
  );
9715
- const minimizedDockSlots = useMemo5(
10302
+ const minimizedDockSlots = useMemo6(
9716
10303
  () => resolveWorkbenchMinimizedDockSlots({
9717
10304
  nodeDefinitions,
9718
10305
  nodes: context.minimizedNodes
@@ -9720,7 +10307,7 @@ function WorkbenchHostDock({
9720
10307
  [context.minimizedNodes, nodeDefinitions]
9721
10308
  );
9722
10309
  const { promotedNodeId, stackDispatching } = useMinimizedDockStackPromotion(minimizedDockSlots);
9723
- const dockItems = useMemo5(
10310
+ const dockItems = useMemo6(
9724
10311
  () => createWorkbenchHostDockItems({
9725
10312
  minimizedDockSlots,
9726
10313
  resolvedEntries
@@ -9731,7 +10318,7 @@ function WorkbenchHostDock({
9731
10318
  dockItems,
9732
10319
  (nodeId) => context.genie.shouldAnimateMinimizedDockEnter(nodeId)
9733
10320
  );
9734
- const presentDockItemKeys = useMemo5(
10321
+ const presentDockItemKeys = useMemo6(
9735
10322
  () => presentDockItems.map((item) => item.key).join("\n"),
9736
10323
  [presentDockItems]
9737
10324
  );
@@ -9740,7 +10327,7 @@ function WorkbenchHostDock({
9740
10327
  elementRefs: wallpaperToneElementRefs,
9741
10328
  itemKeys: presentDockItemKeys
9742
10329
  });
9743
- const dockWidth = useMemo5(
10330
+ const dockWidth = useMemo6(
9744
10331
  () => resolveWorkbenchHostDockItemsWidth(dockItems),
9745
10332
  [dockItems]
9746
10333
  );
@@ -9790,10 +10377,10 @@ function WorkbenchHostDock({
9790
10377
  }
9791
10378
  dockMeasureRef.current?.removeAttribute("data-dock-hover-panel-open");
9792
10379
  }, []);
9793
- useEffect9(() => {
10380
+ useEffect10(() => {
9794
10381
  activeHoverPanelRef.current = activeHoverPanel;
9795
10382
  }, [activeHoverPanel]);
9796
- useEffect9(() => {
10383
+ useEffect10(() => {
9797
10384
  activeLabelTooltipRef.current = activeLabelTooltip;
9798
10385
  }, [activeLabelTooltip]);
9799
10386
  const closeLabelTooltipImmediate = useCallback10(
@@ -10268,7 +10855,7 @@ function WorkbenchHostDock({
10268
10855
  })()
10269
10856
  )
10270
10857
  );
10271
- useEffect9(() => {
10858
+ useEffect10(() => {
10272
10859
  const shouldSubscribe = activePopup !== null || hasMinimizedPreviewCapture;
10273
10860
  if (!shouldSubscribe || !externalStateSource?.subscribe) {
10274
10861
  return void 0;
@@ -10277,7 +10864,7 @@ function WorkbenchHostDock({
10277
10864
  setExternalStateRevision((revision) => revision + 1);
10278
10865
  });
10279
10866
  }, [activePopup, externalStateSource, hasMinimizedPreviewCapture]);
10280
- useEffect9(() => {
10867
+ useEffect10(() => {
10281
10868
  const nextAttentionIds = /* @__PURE__ */ new Set();
10282
10869
  for (const entry of renderedDockEntries) {
10283
10870
  const nextToken = entry.attentionToken ?? null;
@@ -10318,7 +10905,7 @@ function WorkbenchHostDock({
10318
10905
  );
10319
10906
  }
10320
10907
  }, [renderedDockEntries]);
10321
- useEffect9(
10908
+ useEffect10(
10322
10909
  () => () => {
10323
10910
  for (const timeout of attentionTimeouts.current.values()) {
10324
10911
  globalThis.clearTimeout(timeout);
@@ -10500,20 +11087,20 @@ function WorkbenchHostDock({
10500
11087
  instanceMode: dockContextMenuInstanceMode,
10501
11088
  matchedNodes: popupEntry.matchedNodes
10502
11089
  }).kind === "launch";
10503
- return /* @__PURE__ */ jsxs8(
11090
+ return /* @__PURE__ */ jsxs9(
10504
11091
  "div",
10505
11092
  {
10506
11093
  className: "flex justify-center pointer-events-none",
10507
11094
  "data-dock-placement": dockPlacement,
10508
11095
  children: [
10509
- /* @__PURE__ */ jsx11(
11096
+ /* @__PURE__ */ jsx12(
10510
11097
  "div",
10511
11098
  {
10512
11099
  className: "desktop-dock-plate",
10513
11100
  style: dockFrameSize === null ? void 0 : {
10514
11101
  "--desktop-dock-frame-size": `${dockFrameSize}px`
10515
11102
  },
10516
- children: /* @__PURE__ */ jsxs8(
11103
+ children: /* @__PURE__ */ jsxs9(
10517
11104
  "div",
10518
11105
  {
10519
11106
  ref: dockMeasureRef,
@@ -10539,7 +11126,7 @@ function WorkbenchHostDock({
10539
11126
  role: "toolbar",
10540
11127
  style: dockPlacement === "left" ? { height: dockWidth } : { width: dockWidth },
10541
11128
  children: [
10542
- /* @__PURE__ */ jsx11(
11129
+ /* @__PURE__ */ jsx12(
10543
11130
  "span",
10544
11131
  {
10545
11132
  className: "desktop-dock__pointer-rail",
@@ -10547,7 +11134,7 @@ function WorkbenchHostDock({
10547
11134
  "aria-hidden": true
10548
11135
  }
10549
11136
  ),
10550
- /* @__PURE__ */ jsx11(
11137
+ /* @__PURE__ */ jsx12(
10551
11138
  "button",
10552
11139
  {
10553
11140
  "aria-label": i18n.t(
@@ -10558,12 +11145,12 @@ function WorkbenchHostDock({
10558
11145
  disabled: !dockScrollState.canScrollBackward,
10559
11146
  onClick: () => scrollDockItems("backward"),
10560
11147
  type: "button",
10561
- children: dockPlacement === "left" ? /* @__PURE__ */ jsx11(ChevronUpIcon, { size: 16 }) : /* @__PURE__ */ jsx11(ArrowLeftIcon, { size: 16 })
11148
+ children: dockPlacement === "left" ? /* @__PURE__ */ jsx12(ChevronUpIcon, { size: 16 }) : /* @__PURE__ */ jsx12(ArrowLeftIcon, { size: 16 })
10562
11149
  }
10563
11150
  ),
10564
- /* @__PURE__ */ jsx11("div", { ref: dockItemsRef, className: "desktop-dock__items", children: presentDockItems.map((dockItem) => {
11151
+ /* @__PURE__ */ jsx12("div", { ref: dockItemsRef, className: "desktop-dock__items", children: presentDockItems.map((dockItem) => {
10565
11152
  if (dockItem.item.kind === "separator") {
10566
- return /* @__PURE__ */ jsx11(
11153
+ return /* @__PURE__ */ jsx12(
10567
11154
  "span",
10568
11155
  {
10569
11156
  ref: registerWallpaperToneElement(dockItem.key),
@@ -10590,7 +11177,7 @@ function WorkbenchHostDock({
10590
11177
  });
10591
11178
  const hasHoverPanel = dockEntryHasHoverPanel(entry);
10592
11179
  const labelTooltipTarget2 = hasHoverPanel ? null : dockLabelTooltipTarget(`entry:${entry.id}`, entry.label);
10593
- const dockButton2 = /* @__PURE__ */ jsx11(
11180
+ const dockButton2 = /* @__PURE__ */ jsx12(
10594
11181
  "button",
10595
11182
  {
10596
11183
  "aria-expanded": currentPopup ? true : void 0,
@@ -10749,7 +11336,7 @@ function WorkbenchHostDock({
10749
11336
  entryId: entry.id
10750
11337
  });
10751
11338
  },
10752
- children: /* @__PURE__ */ jsxs8(
11339
+ children: /* @__PURE__ */ jsxs9(
10753
11340
  "span",
10754
11341
  {
10755
11342
  className: "desktop-dock__icon-shell",
@@ -10757,7 +11344,7 @@ function WorkbenchHostDock({
10757
11344
  "data-entry-state": entry.state?.kind ?? "enabled",
10758
11345
  "aria-hidden": true,
10759
11346
  children: [
10760
- /* @__PURE__ */ jsx11("span", { className: "desktop-dock__icon-content", children: entry.icon }),
11347
+ /* @__PURE__ */ jsx12("span", { className: "desktop-dock__icon-content", children: entry.icon }),
10761
11348
  renderDockBadge(
10762
11349
  entry,
10763
11350
  resolvedEntry.matchedNodes.length
@@ -10767,7 +11354,7 @@ function WorkbenchHostDock({
10767
11354
  )
10768
11355
  }
10769
11356
  );
10770
- return /* @__PURE__ */ jsx11(
11357
+ return /* @__PURE__ */ jsx12(
10771
11358
  "span",
10772
11359
  {
10773
11360
  ref: registerDockSlot(anchorKey),
@@ -10868,7 +11455,7 @@ function WorkbenchHostDock({
10868
11455
  `minimized-stack:${slot.anchorKey}`,
10869
11456
  stackLabel
10870
11457
  );
10871
- const stackButton = /* @__PURE__ */ jsx11(
11458
+ const stackButton = /* @__PURE__ */ jsx12(
10872
11459
  "span",
10873
11460
  {
10874
11461
  "aria-expanded": stackPopupActive,
@@ -10902,7 +11489,7 @@ function WorkbenchHostDock({
10902
11489
  }
10903
11490
  );
10904
11491
  },
10905
- children: /* @__PURE__ */ jsxs8(
11492
+ children: /* @__PURE__ */ jsxs9(
10906
11493
  "span",
10907
11494
  {
10908
11495
  className: "desktop-dock__minimized-stack-icon",
@@ -10917,7 +11504,7 @@ function WorkbenchHostDock({
10917
11504
  (_, index) => {
10918
11505
  const node2 = slot.nodes[index];
10919
11506
  if (index === 0 && node2) {
10920
- return /* @__PURE__ */ jsx11(
11507
+ return /* @__PURE__ */ jsx12(
10921
11508
  WorkbenchHostDockMinimizedNodePreview,
10922
11509
  {
10923
11510
  capturePreview: captureMinimizedNodePreview,
@@ -10932,7 +11519,7 @@ function WorkbenchHostDock({
10932
11519
  minimizedDockPreviewFreezeKey(node2)
10933
11520
  );
10934
11521
  }
10935
- return /* @__PURE__ */ jsx11(
11522
+ return /* @__PURE__ */ jsx12(
10936
11523
  "span",
10937
11524
  {
10938
11525
  "aria-hidden": "true",
@@ -10942,13 +11529,13 @@ function WorkbenchHostDock({
10942
11529
  );
10943
11530
  }
10944
11531
  ),
10945
- /* @__PURE__ */ jsx11("span", { className: "desktop-dock__count-badge", children: slot.nodes.length })
11532
+ /* @__PURE__ */ jsx12("span", { className: "desktop-dock__count-badge", children: slot.nodes.length })
10946
11533
  ]
10947
11534
  }
10948
11535
  )
10949
11536
  }
10950
11537
  );
10951
- return /* @__PURE__ */ jsx11(
11538
+ return /* @__PURE__ */ jsx12(
10952
11539
  "span",
10953
11540
  {
10954
11541
  ref: registerDockSlot(slot.anchorKey),
@@ -11003,7 +11590,7 @@ function WorkbenchHostDock({
11003
11590
  `minimized-node:${node.id}`,
11004
11591
  node.title
11005
11592
  );
11006
- const dockButton = /* @__PURE__ */ jsx11(
11593
+ const dockButton = /* @__PURE__ */ jsx12(
11007
11594
  "span",
11008
11595
  {
11009
11596
  "aria-label": i18n.t("launch", { title: node.title }),
@@ -11064,7 +11651,7 @@ function WorkbenchHostDock({
11064
11651
  }
11065
11652
  );
11066
11653
  },
11067
- children: /* @__PURE__ */ jsx11(
11654
+ children: /* @__PURE__ */ jsx12(
11068
11655
  WorkbenchHostDockMinimizedNodePreview,
11069
11656
  {
11070
11657
  capturePreview: isPendingMinimizedNode ? void 0 : captureMinimizedNodePreview,
@@ -11078,7 +11665,7 @@ function WorkbenchHostDock({
11078
11665
  )
11079
11666
  }
11080
11667
  );
11081
- return /* @__PURE__ */ jsx11(
11668
+ return /* @__PURE__ */ jsx12(
11082
11669
  "span",
11083
11670
  {
11084
11671
  ref: registerDockSlot(slot.anchorKey),
@@ -11128,7 +11715,7 @@ function WorkbenchHostDock({
11128
11715
  dockItem.key
11129
11716
  );
11130
11717
  }) }),
11131
- /* @__PURE__ */ jsx11(
11718
+ /* @__PURE__ */ jsx12(
11132
11719
  "button",
11133
11720
  {
11134
11721
  "aria-label": i18n.t(
@@ -11139,10 +11726,10 @@ function WorkbenchHostDock({
11139
11726
  disabled: !dockScrollState.canScrollForward,
11140
11727
  onClick: () => scrollDockItems("forward"),
11141
11728
  type: "button",
11142
- children: dockPlacement === "left" ? /* @__PURE__ */ jsx11(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx11(ArrowRightIcon, { size: 16 })
11729
+ children: dockPlacement === "left" ? /* @__PURE__ */ jsx12(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx12(ArrowRightIcon, { size: 16 })
11143
11730
  }
11144
11731
  ),
11145
- activeHoverPanel ? /* @__PURE__ */ jsx11(
11732
+ activeHoverPanel ? /* @__PURE__ */ jsx12(
11146
11733
  WorkbenchHostDockHoverPanel,
11147
11734
  {
11148
11735
  entry: resolvedEntries.find(
@@ -11175,7 +11762,7 @@ function WorkbenchHostDock({
11175
11762
  }
11176
11763
  }
11177
11764
  ) : null,
11178
- activeLabelTooltip ? /* @__PURE__ */ jsx11(
11765
+ activeLabelTooltip ? /* @__PURE__ */ jsx12(
11179
11766
  WorkbenchHostDockLabelTooltip,
11180
11767
  {
11181
11768
  placement: dockPlacement,
@@ -11187,7 +11774,7 @@ function WorkbenchHostDock({
11187
11774
  )
11188
11775
  }
11189
11776
  ),
11190
- popupEntry && activePopup ? /* @__PURE__ */ jsx11(
11777
+ popupEntry && activePopup ? /* @__PURE__ */ jsx12(
11191
11778
  WorkbenchHostDockPopup,
11192
11779
  {
11193
11780
  anchorRect: activePopup.anchorRect,
@@ -11239,12 +11826,7 @@ function WorkbenchHostDock({
11239
11826
  node
11240
11827
  };
11241
11828
  const descriptor = popupEntry.entry.resolvePopupItem?.(item) ?? {};
11242
- const descriptorPreviewImageUrl = descriptor.previewImageUrl ?? null;
11243
- const descriptorPreview = descriptor.preview ?? (descriptorPreviewImageUrl ? {
11244
- kind: "image",
11245
- revision: descriptor.revision ?? null,
11246
- src: descriptorPreviewImageUrl
11247
- } : popupEntry.entry.providePopupItemPreview?.(item) ?? null);
11829
+ const descriptorPreview = descriptor.preview ?? popupEntry.entry.providePopupItemPreview?.(item) ?? null;
11248
11830
  return {
11249
11831
  ...item,
11250
11832
  preview: descriptorPreview,
@@ -11293,7 +11875,8 @@ function WorkbenchHostDock({
11293
11875
  popupEntry.entry.id,
11294
11876
  () => host.launchNode({
11295
11877
  dockEntryId: popupEntry.entry.id,
11296
- payload: popupEntry.entry.launchPayload,
11878
+ launchSource: dockPopupNewWindowLaunchSource,
11879
+ payload: popupEntry.entry.newWindowLaunchPayload ?? popupEntry.entry.launchPayload,
11297
11880
  reason: "dock",
11298
11881
  typeId: popupEntry.entry.typeId
11299
11882
  })
@@ -11378,7 +11961,7 @@ function WorkbenchHostDock({
11378
11961
  variant: activePopup.kind === "context-menu" ? "context-menu" : "default"
11379
11962
  }
11380
11963
  ) : null,
11381
- activeMinimizedStackSlot && activeMinimizedStackPopup ? /* @__PURE__ */ jsx11(
11964
+ activeMinimizedStackSlot && activeMinimizedStackPopup ? /* @__PURE__ */ jsx12(
11382
11965
  WorkbenchHostDockPopup,
11383
11966
  {
11384
11967
  anchorRect: activeMinimizedStackPopup,
@@ -11482,7 +12065,7 @@ function WorkbenchHostDockMinimizedNodePreview({
11482
12065
  const [previewImageUrl, setPreviewImageUrl] = useState8(
11483
12066
  () => deferPreview || providePreview ? null : readCachedWorkbenchNodePreviewImage(node.id)
11484
12067
  );
11485
- useEffect9(() => {
12068
+ useEffect10(() => {
11486
12069
  if (deferPreview || !providePreview || componentPreview !== void 0) {
11487
12070
  return void 0;
11488
12071
  }
@@ -11531,7 +12114,7 @@ function WorkbenchHostDockMinimizedNodePreview({
11531
12114
  node.minimizedAtUnixMs,
11532
12115
  providePreview
11533
12116
  ]);
11534
- useEffect9(() => {
12117
+ useEffect10(() => {
11535
12118
  if (deferPreview || providePreview) {
11536
12119
  return void 0;
11537
12120
  }
@@ -11593,7 +12176,7 @@ function WorkbenchHostDockMinimizedNodePreview({
11593
12176
  return renderMinimizedDockPreviewContent(componentPreview, className);
11594
12177
  }
11595
12178
  if (previewImageUrl) {
11596
- return /* @__PURE__ */ jsx11(
12179
+ return /* @__PURE__ */ jsx12(
11597
12180
  "span",
11598
12181
  {
11599
12182
  className: [
@@ -11602,7 +12185,7 @@ function WorkbenchHostDockMinimizedNodePreview({
11602
12185
  className
11603
12186
  ].filter(Boolean).join(" "),
11604
12187
  "aria-hidden": "true",
11605
- children: /* @__PURE__ */ jsx11(
12188
+ children: /* @__PURE__ */ jsx12(
11606
12189
  "img",
11607
12190
  {
11608
12191
  alt: "",
@@ -11617,22 +12200,22 @@ function WorkbenchHostDockMinimizedNodePreview({
11617
12200
  return renderMinimizedDockPreviewPlaceholder(className);
11618
12201
  }
11619
12202
  function renderMinimizedDockPreviewPlaceholder(className) {
11620
- return /* @__PURE__ */ jsxs8(
12203
+ return /* @__PURE__ */ jsxs9(
11621
12204
  "span",
11622
12205
  {
11623
12206
  className: ["desktop-dock__minimized-preview", className].filter(Boolean).join(" "),
11624
12207
  "aria-hidden": "true",
11625
12208
  children: [
11626
- /* @__PURE__ */ jsx11("span", { className: "desktop-dock__minimized-preview-line" }),
11627
- /* @__PURE__ */ jsx11("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--short" }),
11628
- /* @__PURE__ */ jsx11("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--accent" })
12209
+ /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line" }),
12210
+ /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--short" }),
12211
+ /* @__PURE__ */ jsx12("span", { className: "desktop-dock__minimized-preview-line desktop-dock__minimized-preview-line--accent" })
11629
12212
  ]
11630
12213
  }
11631
12214
  );
11632
12215
  }
11633
12216
  function renderMinimizedDockPreviewContent(preview, className) {
11634
12217
  if (preview.kind === "image") {
11635
- return /* @__PURE__ */ jsx11(
12218
+ return /* @__PURE__ */ jsx12(
11636
12219
  "span",
11637
12220
  {
11638
12221
  className: [
@@ -11641,7 +12224,7 @@ function renderMinimizedDockPreviewContent(preview, className) {
11641
12224
  className
11642
12225
  ].filter(Boolean).join(" "),
11643
12226
  "aria-hidden": "true",
11644
- children: /* @__PURE__ */ jsx11(
12227
+ children: /* @__PURE__ */ jsx12(
11645
12228
  "img",
11646
12229
  {
11647
12230
  alt: "",
@@ -11653,7 +12236,7 @@ function renderMinimizedDockPreviewContent(preview, className) {
11653
12236
  }
11654
12237
  );
11655
12238
  }
11656
- return /* @__PURE__ */ jsx11(
12239
+ return /* @__PURE__ */ jsx12(
11657
12240
  WorkbenchHostDockFrozenComponentPreview,
11658
12241
  {
11659
12242
  className,
@@ -11673,7 +12256,7 @@ function WorkbenchHostDockFrozenComponentPreview({
11673
12256
  }
11674
12257
  setFrozenMarkup(sourceRef.current?.innerHTML ?? "");
11675
12258
  }, [frozenMarkup]);
11676
- return /* @__PURE__ */ jsx11(
12259
+ return /* @__PURE__ */ jsx12(
11677
12260
  "span",
11678
12261
  {
11679
12262
  className: [
@@ -11682,14 +12265,14 @@ function WorkbenchHostDockFrozenComponentPreview({
11682
12265
  className
11683
12266
  ].filter(Boolean).join(" "),
11684
12267
  "aria-hidden": "true",
11685
- children: frozenMarkup === null ? /* @__PURE__ */ jsx11(
12268
+ children: frozenMarkup === null ? /* @__PURE__ */ jsx12(
11686
12269
  "span",
11687
12270
  {
11688
12271
  ref: sourceRef,
11689
12272
  className: "desktop-dock__minimized-preview-freeze-source",
11690
12273
  children: preview.element
11691
12274
  }
11692
- ) : /* @__PURE__ */ jsx11(
12275
+ ) : /* @__PURE__ */ jsx12(
11693
12276
  "span",
11694
12277
  {
11695
12278
  className: "desktop-dock__minimized-preview-frozen-content",
@@ -11757,18 +12340,18 @@ function renderDockBadge(entry, matchedNodeCount) {
11757
12340
  return null;
11758
12341
  }
11759
12342
  if (badge.kind === "count") {
11760
- return /* @__PURE__ */ jsx11("span", { className: "desktop-dock__count-badge", children: badge.value });
12343
+ return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__count-badge", children: badge.value });
11761
12344
  }
11762
12345
  if (badge.kind === "custom") {
11763
- return /* @__PURE__ */ jsx11("span", { className: "desktop-dock__custom-badge", children: badge.content });
12346
+ return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__custom-badge", children: badge.content });
11764
12347
  }
11765
- return /* @__PURE__ */ jsx11("span", { className: "desktop-dock__status-badge", "data-status": badge.status });
12348
+ return /* @__PURE__ */ jsx12("span", { className: "desktop-dock__status-badge", "data-status": badge.status });
11766
12349
  }
11767
12350
  function WorkbenchHostDockLabelTooltip({
11768
12351
  placement,
11769
12352
  state
11770
12353
  }) {
11771
- return /* @__PURE__ */ jsx11(
12354
+ return /* @__PURE__ */ jsx12(
11772
12355
  "div",
11773
12356
  {
11774
12357
  className: "desktop-dock__label-tooltip",
@@ -11832,7 +12415,7 @@ function WorkbenchHostDockHoverPanel({
11832
12415
  }
11833
12416
  })();
11834
12417
  };
11835
- return /* @__PURE__ */ jsxs8(
12418
+ return /* @__PURE__ */ jsxs9(
11836
12419
  "div",
11837
12420
  {
11838
12421
  ref: hoverPanelRef,
@@ -11851,13 +12434,13 @@ function WorkbenchHostDockHoverPanel({
11851
12434
  "--desktop-dock-hover-panel-anchor-width": `${state.anchorRect.width}px`
11852
12435
  },
11853
12436
  children: [
11854
- /* @__PURE__ */ jsx11("div", { className: "desktop-dock__hover-panel-title", children: entry.label }),
11855
- entry.state?.reason ? /* @__PURE__ */ jsx11("div", { className: "desktop-dock__hover-panel-description", children: stripDockDescriptionTerminalPunctuation(entry.state.reason) }) : null,
11856
- entry.hoverActions?.length ? /* @__PURE__ */ jsx11("div", { className: "desktop-dock__hover-actions", children: entry.hoverActions.map((action) => {
12437
+ /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-panel-title", children: entry.label }),
12438
+ entry.state?.reason ? /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-panel-description", children: stripDockDescriptionTerminalPunctuation(entry.state.reason) }) : null,
12439
+ entry.hoverActions?.length ? /* @__PURE__ */ jsx12("div", { className: "desktop-dock__hover-actions", children: entry.hoverActions.map((action) => {
11857
12440
  const actionKey = dockActionKey(entry.id, action.id);
11858
12441
  const isLocallyPending = pendingActionKeys.has(actionKey);
11859
12442
  const isPending = isLocallyPending || action.disabled === true && action.pendingLabel !== void 0;
11860
- return /* @__PURE__ */ jsx11(
12443
+ return /* @__PURE__ */ jsx12(
11861
12444
  Button3,
11862
12445
  {
11863
12446
  "aria-busy": isPending ? true : void 0,
@@ -12098,7 +12681,7 @@ function useDockPresenceItems(items, shouldAnimateMinimizedDockEnter) {
12098
12681
  }))
12099
12682
  );
12100
12683
  const initialized = useRef8(false);
12101
- useEffect9(() => {
12684
+ useEffect10(() => {
12102
12685
  let nextSettleMs = dockPresenceAnimationMs;
12103
12686
  setPresentItems((current) => {
12104
12687
  const filteredItems = resolveDockPresenceItems({
@@ -12400,7 +12983,7 @@ function useDockBounce(slotRefs) {
12400
12983
  },
12401
12984
  [slotRefs]
12402
12985
  );
12403
- useEffect9(
12986
+ useEffect10(
12404
12987
  () => () => {
12405
12988
  for (const anchorKey of timeoutsRef.current.keys()) {
12406
12989
  clearDockBounce(anchorKey);
@@ -12573,7 +13156,7 @@ function createWorkbenchHostNodeHeaderContext({
12573
13156
  }
12574
13157
 
12575
13158
  // src/host/WorkbenchHostWindowActions.tsx
12576
- import { jsx as jsx12 } from "react/jsx-runtime";
13159
+ import { jsx as jsx13 } from "react/jsx-runtime";
12577
13160
  function WorkbenchHostWindowActions({
12578
13161
  context,
12579
13162
  host,
@@ -12586,7 +13169,7 @@ function WorkbenchHostWindowActions({
12586
13169
  }
12587
13170
  const minimizable = definition.window?.minimizable !== false;
12588
13171
  const closable = definition.window?.closable !== false;
12589
- return /* @__PURE__ */ jsx12(
13172
+ return /* @__PURE__ */ jsx13(
12590
13173
  WorkbenchWindowTrafficLights,
12591
13174
  {
12592
13175
  close: closable ? {
@@ -12609,11 +13192,11 @@ function WorkbenchHostWindowActions({
12609
13192
  }
12610
13193
 
12611
13194
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
12612
- import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
13195
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
12613
13196
  function useWorkbenchHostSurfaceRenderers(input) {
12614
- const renderBottomChrome = useMemo6(() => {
13197
+ const renderBottomChrome = useMemo7(() => {
12615
13198
  const renderChrome = input.renderBottomChrome;
12616
- return renderChrome ? () => /* @__PURE__ */ jsx13(
13199
+ return renderChrome ? () => /* @__PURE__ */ jsx14(
12617
13200
  WorkbenchHostSurfaceRenderErrorBoundary,
12618
13201
  {
12619
13202
  debugDiagnostics: input.debugDiagnostics,
@@ -12624,7 +13207,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12624
13207
  fallbackKind: "bottom-chrome",
12625
13208
  resetKey: `${input.workspaceId}:bottom-chrome`,
12626
13209
  workspaceId: input.workspaceId,
12627
- children: /* @__PURE__ */ jsx13(
13210
+ children: /* @__PURE__ */ jsx14(
12628
13211
  WorkbenchHostChromeRenderer,
12629
13212
  {
12630
13213
  context: input.chromeContext,
@@ -12639,9 +13222,9 @@ function useWorkbenchHostSurfaceRenderers(input) {
12639
13222
  input.renderBottomChrome,
12640
13223
  input.workspaceId
12641
13224
  ]);
12642
- const renderTopChrome = useMemo6(() => {
13225
+ const renderTopChrome = useMemo7(() => {
12643
13226
  const renderChrome = input.renderTopChrome;
12644
- return renderChrome ? () => /* @__PURE__ */ jsx13(
13227
+ return renderChrome ? () => /* @__PURE__ */ jsx14(
12645
13228
  WorkbenchHostSurfaceRenderErrorBoundary,
12646
13229
  {
12647
13230
  debugDiagnostics: input.debugDiagnostics,
@@ -12652,7 +13235,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12652
13235
  fallbackKind: "top-chrome",
12653
13236
  resetKey: `${input.workspaceId}:top-chrome`,
12654
13237
  workspaceId: input.workspaceId,
12655
- children: /* @__PURE__ */ jsx13(
13238
+ children: /* @__PURE__ */ jsx14(
12656
13239
  WorkbenchHostChromeRenderer,
12657
13240
  {
12658
13241
  context: input.chromeContext,
@@ -12701,7 +13284,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12701
13284
  ]
12702
13285
  );
12703
13286
  const renderDock = useCallback11(
12704
- (context) => /* @__PURE__ */ jsx13(
13287
+ (context) => /* @__PURE__ */ jsx14(
12705
13288
  WorkbenchHostSurfaceRenderErrorBoundary,
12706
13289
  {
12707
13290
  debugDiagnostics: input.debugDiagnostics,
@@ -12713,7 +13296,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12713
13296
  fallbackKind: "dock",
12714
13297
  resetKey: `${input.workspaceId}:dock`,
12715
13298
  workspaceId: input.workspaceId,
12716
- children: /* @__PURE__ */ jsx13(
13299
+ children: /* @__PURE__ */ jsx14(
12717
13300
  WorkbenchHostDock,
12718
13301
  {
12719
13302
  captureNodePreviewImage,
@@ -12767,7 +13350,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12767
13350
  host: input.hostSession,
12768
13351
  workspaceId: input.workspaceId
12769
13352
  });
12770
- return /* @__PURE__ */ jsx13(
13353
+ return /* @__PURE__ */ jsx14(
12771
13354
  WorkbenchHostNodeRenderErrorBoundary,
12772
13355
  {
12773
13356
  debugDiagnostics: input.debugDiagnostics,
@@ -12778,7 +13361,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12778
13361
  }),
12779
13362
  resetKey: `${context.node.id}:${context.node.data.typeId}:${input.externalStateRevision}`,
12780
13363
  workspaceId: input.workspaceId,
12781
- children: /* @__PURE__ */ jsx13(
13364
+ children: /* @__PURE__ */ jsx14(
12782
13365
  WorkbenchHostNodeBodyRenderer,
12783
13366
  {
12784
13367
  context: bodyContext,
@@ -12798,7 +13381,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
12798
13381
  ]
12799
13382
  );
12800
13383
  const renderWindowActions = useCallback11(
12801
- (context) => /* @__PURE__ */ jsx13(
13384
+ (context) => /* @__PURE__ */ jsx14(
12802
13385
  WorkbenchHostWindowActions,
12803
13386
  {
12804
13387
  context,
@@ -12991,7 +13574,7 @@ var WorkbenchHostSurfaceRenderErrorBoundary = class extends Component {
12991
13574
  }
12992
13575
  render() {
12993
13576
  if (this.state.hasError) {
12994
- return /* @__PURE__ */ jsx13(
13577
+ return /* @__PURE__ */ jsx14(
12995
13578
  "div",
12996
13579
  {
12997
13580
  "data-workbench-surface-render-error": this.props.fallbackKind,
@@ -13050,7 +13633,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
13050
13633
  }
13051
13634
  render() {
13052
13635
  if (this.state.hasError) {
13053
- return /* @__PURE__ */ jsxs9(
13636
+ return /* @__PURE__ */ jsxs10(
13054
13637
  "div",
13055
13638
  {
13056
13639
  "data-workbench-node-render-error": "true",
@@ -13068,7 +13651,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
13068
13651
  width: "100%"
13069
13652
  },
13070
13653
  children: [
13071
- /* @__PURE__ */ jsx13(
13654
+ /* @__PURE__ */ jsx14(
13072
13655
  "div",
13073
13656
  {
13074
13657
  "data-workbench-node-render-error-message": "true",
@@ -13080,8 +13663,8 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
13080
13663
  children: "This workspace view failed to render."
13081
13664
  }
13082
13665
  ),
13083
- /* @__PURE__ */ jsx13("div", { style: { fontSize: 12 }, children: "Try selecting another conversation or reopen the window." }),
13084
- /* @__PURE__ */ jsx13(
13666
+ /* @__PURE__ */ jsx14("div", { style: { fontSize: 12 }, children: "Try selecting another conversation or reopen the window." }),
13667
+ /* @__PURE__ */ jsx14(
13085
13668
  "button",
13086
13669
  {
13087
13670
  type: "button",
@@ -13124,7 +13707,7 @@ function WorkbenchHostChromeRenderer({
13124
13707
  }
13125
13708
 
13126
13709
  // src/host/WorkbenchHost.tsx
13127
- import { jsx as jsx14 } from "react/jsx-runtime";
13710
+ import { jsx as jsx15 } from "react/jsx-runtime";
13128
13711
  var noop3 = () => {
13129
13712
  };
13130
13713
  function WorkbenchHost({
@@ -13158,7 +13741,7 @@ function WorkbenchHost({
13158
13741
  windowManagement,
13159
13742
  workspaceId
13160
13743
  }) {
13161
- const hostRuntimeConfig = useMemo7(
13744
+ const hostRuntimeConfig = useMemo8(
13162
13745
  () => resolveWorkbenchHostRuntimeConfig({
13163
13746
  contributions,
13164
13747
  externalStateSource,
@@ -13174,7 +13757,7 @@ function WorkbenchHost({
13174
13757
  onNodeCloseRequest
13175
13758
  ]
13176
13759
  );
13177
- const hostDockEntries = useMemo7(
13760
+ const hostDockEntries = useMemo8(
13178
13761
  () => resolveWorkbenchHostDockEntries({
13179
13762
  contributions,
13180
13763
  dockEntries
@@ -13237,7 +13820,7 @@ function WorkbenchHost({
13237
13820
  });
13238
13821
  const missionControlPresence = useWorkbenchMissionControlPresence(missionControlState);
13239
13822
  const missionControlRenderedState = missionControlPresence.state;
13240
- return /* @__PURE__ */ jsx14(
13823
+ return /* @__PURE__ */ jsx15(
13241
13824
  WorkbenchSurface,
13242
13825
  {
13243
13826
  className,
@@ -13251,7 +13834,7 @@ function WorkbenchHost({
13251
13834
  missionControlPhase: missionControlPresence.phase,
13252
13835
  minimizeAnimation,
13253
13836
  presentation: missionControlState?.presentation ?? null,
13254
- renderBackdrop: missionControlRenderedState ? () => /* @__PURE__ */ jsx14(
13837
+ renderBackdrop: missionControlRenderedState ? () => /* @__PURE__ */ jsx15(
13255
13838
  WorkbenchMissionControlBackdrop,
13256
13839
  {
13257
13840
  onExitTransitionComplete: () => missionControlPresence.completeExitTransition(),
@@ -13262,7 +13845,7 @@ function WorkbenchHost({
13262
13845
  renderDock: surfaceRenderers.renderDock,
13263
13846
  renderNode: surfaceRenderers.renderNode,
13264
13847
  renderNodeGeniePreview: surfaceRenderers.renderNodeGeniePreview,
13265
- renderOverlay: missionControlRenderedState ? () => /* @__PURE__ */ jsx14(
13848
+ renderOverlay: missionControlRenderedState ? () => /* @__PURE__ */ jsx15(
13266
13849
  WorkbenchMissionControlOverlay,
13267
13850
  {
13268
13851
  i18n: missionControlI18n,