@tutti-os/workbench-surface 0.0.153 → 0.0.155

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
@@ -1554,7 +1554,7 @@ function createWorkbenchController(initialState = {}, options = {}) {
1554
1554
  }
1555
1555
 
1556
1556
  // src/host/WorkbenchHost.tsx
1557
- import { useMemo as useMemo8 } from "react";
1557
+ import { useMemo as useMemo9 } from "react";
1558
1558
 
1559
1559
  // src/mission-control/WorkbenchMissionControlOverlay.tsx
1560
1560
  import {
@@ -5721,8 +5721,16 @@ function combineContributionExternalStateSources(contributions) {
5721
5721
  }
5722
5722
  return null;
5723
5723
  },
5724
- subscribe(listener) {
5725
- const disposers = sources.map((source) => source.subscribe?.(listener)).filter((dispose) => Boolean(dispose));
5724
+ subscribeNodeState(input, listener) {
5725
+ const disposers = sources.map((source) => source.subscribeNodeState?.(input, listener)).filter((dispose) => Boolean(dispose));
5726
+ return () => {
5727
+ for (const dispose of disposers) {
5728
+ dispose();
5729
+ }
5730
+ };
5731
+ },
5732
+ subscribeWorkspaceState(input, listener) {
5733
+ const disposers = sources.map((source) => source.subscribeWorkspaceState?.(input, listener)).filter((dispose) => Boolean(dispose));
5726
5734
  return () => {
5727
5735
  for (const dispose of disposers) {
5728
5736
  dispose();
@@ -5794,7 +5802,7 @@ function resolveHostClosePreparer(contributions) {
5794
5802
  }
5795
5803
 
5796
5804
  // src/host/useWorkbenchHostRuntime.ts
5797
- import { useEffect as useEffect6, useMemo as useMemo5, useState as useState5 } from "react";
5805
+ import { useEffect as useEffect6, useMemo as useMemo6, useState as useState5 } from "react";
5798
5806
 
5799
5807
  // src/store/createDerivedSnapshotGetter.ts
5800
5808
  function createDerivedSnapshotGetter(input) {
@@ -6668,14 +6676,11 @@ function projectedSubjectsEqual(left, right) {
6668
6676
  }
6669
6677
 
6670
6678
  // src/host/externalState.ts
6671
- function readWorkbenchHostExternalState(input) {
6672
- if (!input.externalStateSource) {
6673
- return {
6674
- externalNodeState: null,
6675
- externalWorkspaceState: null
6676
- };
6677
- }
6678
- const nodeStateInput = {
6679
+ import { useCallback as useCallback8, useMemo as useMemo5, useSyncExternalStore } from "react";
6680
+ var noopSubscribe = () => () => {
6681
+ };
6682
+ function createWorkbenchHostExternalStateLookupInput(input) {
6683
+ return {
6679
6684
  instanceId: input.node.data.instanceId,
6680
6685
  instanceKey: input.node.data.instanceKey ?? null,
6681
6686
  nodeId: input.node.id,
@@ -6683,6 +6688,59 @@ function readWorkbenchHostExternalState(input) {
6683
6688
  workspaceId: input.workspaceId,
6684
6689
  ...input.node.data.projectionSubject ? { subject: input.node.data.projectionSubject } : {}
6685
6690
  };
6691
+ }
6692
+ function useWorkbenchHostExternalState(input) {
6693
+ const lookupInput = useMemo5(
6694
+ () => createWorkbenchHostExternalStateLookupInput({
6695
+ node: input.node,
6696
+ workspaceId: input.workspaceId
6697
+ }),
6698
+ [input.node, input.workspaceId]
6699
+ );
6700
+ const workspaceInput = useMemo5(
6701
+ () => ({ workspaceId: input.workspaceId }),
6702
+ [input.workspaceId]
6703
+ );
6704
+ const subscribeNodeState = useCallback8(
6705
+ (listener) => input.externalStateSource?.subscribeNodeState?.(lookupInput, listener) ?? noopSubscribe(),
6706
+ [input.externalStateSource, lookupInput]
6707
+ );
6708
+ const getNodeState = useCallback8(
6709
+ () => input.externalStateSource?.getNodeState(lookupInput) ?? input.node.data.snapshotNodeState ?? null,
6710
+ [input.externalStateSource, input.node.data.snapshotNodeState, lookupInput]
6711
+ );
6712
+ const subscribeWorkspaceState = useCallback8(
6713
+ (listener) => input.externalStateSource?.subscribeWorkspaceState?.(
6714
+ workspaceInput,
6715
+ listener
6716
+ ) ?? noopSubscribe(),
6717
+ [input.externalStateSource, workspaceInput]
6718
+ );
6719
+ const getWorkspaceState = useCallback8(
6720
+ () => input.externalStateSource?.getWorkspaceState(workspaceInput) ?? null,
6721
+ [input.externalStateSource, workspaceInput]
6722
+ );
6723
+ return {
6724
+ externalNodeState: useSyncExternalStore(
6725
+ subscribeNodeState,
6726
+ getNodeState,
6727
+ getNodeState
6728
+ ),
6729
+ externalWorkspaceState: useSyncExternalStore(
6730
+ subscribeWorkspaceState,
6731
+ getWorkspaceState,
6732
+ getWorkspaceState
6733
+ )
6734
+ };
6735
+ }
6736
+ function readWorkbenchHostExternalState(input) {
6737
+ if (!input.externalStateSource) {
6738
+ return {
6739
+ externalNodeState: null,
6740
+ externalWorkspaceState: null
6741
+ };
6742
+ }
6743
+ const nodeStateInput = createWorkbenchHostExternalStateLookupInput(input);
6686
6744
  const sourceNodeState = input.externalStateSource.getNodeState(nodeStateInput);
6687
6745
  return {
6688
6746
  externalNodeState: sourceNodeState ?? input.node.data.snapshotNodeState ?? null,
@@ -6796,7 +6854,7 @@ var WorkbenchHostSessionController = class {
6796
6854
  saveTimer = null;
6797
6855
  appliedSaveSequence = 0;
6798
6856
  saveSequence = 0;
6799
- externalStateUnsubscribe = null;
6857
+ externalStatePersistenceSubscriptions = /* @__PURE__ */ new Map();
6800
6858
  leaseUnsubscribe = null;
6801
6859
  unsubscribe = null;
6802
6860
  constructor(input) {
@@ -6930,8 +6988,7 @@ var WorkbenchHostSessionController = class {
6930
6988
  this.leaseUnsubscribe = null;
6931
6989
  this.unsubscribe?.();
6932
6990
  this.unsubscribe = null;
6933
- this.externalStateUnsubscribe?.();
6934
- this.externalStateUnsubscribe = null;
6991
+ this.disposeExternalStatePersistenceSubscriptions();
6935
6992
  if (this.saveTimer !== null) {
6936
6993
  globalThis.clearTimeout(this.saveTimer);
6937
6994
  this.saveTimer = null;
@@ -7031,8 +7088,7 @@ var WorkbenchHostSessionController = class {
7031
7088
  async loadInitialSnapshot(generation) {
7032
7089
  this.unsubscribe?.();
7033
7090
  this.unsubscribe = null;
7034
- this.externalStateUnsubscribe?.();
7035
- this.externalStateUnsubscribe = null;
7091
+ this.disposeExternalStatePersistenceSubscriptions();
7036
7092
  if (this.saveTimer !== null) {
7037
7093
  globalThis.clearTimeout(this.saveTimer);
7038
7094
  this.saveTimer = null;
@@ -7529,18 +7585,51 @@ var WorkbenchHostSessionController = class {
7529
7585
  }
7530
7586
  this.unsubscribe = this.controller.subscribe(() => {
7531
7587
  this.schedulePersistedSnapshotWrite();
7588
+ this.refreshExternalStatePersistenceSubscription();
7532
7589
  });
7533
- if (this.externalStateUnsubscribe === null) {
7534
- const source = this.input.externalStateSource;
7535
- const canReadSnapshotNodeState = typeof source?.getSnapshotNodeState === "function";
7536
- if (!canReadSnapshotNodeState) {
7537
- return;
7590
+ this.refreshExternalStatePersistenceSubscription();
7591
+ }
7592
+ refreshExternalStatePersistenceSubscription() {
7593
+ const source = this.input.externalStateSource;
7594
+ if (typeof source?.getSnapshotNodeState !== "function" || !source.subscribeNodeState) {
7595
+ this.disposeExternalStatePersistenceSubscriptions();
7596
+ return;
7597
+ }
7598
+ const activeNodeIDs = /* @__PURE__ */ new Set();
7599
+ for (const node of this.controller.getSnapshot().nodes) {
7600
+ activeNodeIDs.add(node.id);
7601
+ const lookupInput = createWorkbenchHostExternalStateLookupInput({
7602
+ node,
7603
+ workspaceId: this.input.workspaceId
7604
+ });
7605
+ const existing = this.externalStatePersistenceSubscriptions.get(node.id);
7606
+ if (existing && sameExternalStateLookupInput(existing.lookupInput, lookupInput)) {
7607
+ continue;
7538
7608
  }
7539
- this.externalStateUnsubscribe = source?.subscribe?.(() => {
7540
- this.schedulePersistedSnapshotWrite();
7541
- }) ?? null;
7609
+ existing?.unsubscribe();
7610
+ const unsubscribe = source.subscribeNodeState(
7611
+ lookupInput,
7612
+ () => this.schedulePersistedSnapshotWrite()
7613
+ );
7614
+ this.externalStatePersistenceSubscriptions.set(node.id, {
7615
+ lookupInput,
7616
+ unsubscribe
7617
+ });
7618
+ }
7619
+ for (const [nodeID, subscription] of this.externalStatePersistenceSubscriptions) {
7620
+ if (activeNodeIDs.has(nodeID)) {
7621
+ continue;
7622
+ }
7623
+ subscription.unsubscribe();
7624
+ this.externalStatePersistenceSubscriptions.delete(nodeID);
7542
7625
  }
7543
7626
  }
7627
+ disposeExternalStatePersistenceSubscriptions() {
7628
+ for (const subscription of this.externalStatePersistenceSubscriptions.values()) {
7629
+ subscription.unsubscribe();
7630
+ }
7631
+ this.externalStatePersistenceSubscriptions.clear();
7632
+ }
7544
7633
  disposeNodeLeases() {
7545
7634
  for (const lease of this.nodeLeases.values()) {
7546
7635
  lease.release();
@@ -7609,6 +7698,9 @@ function withoutRuntimeNodeState(data) {
7609
7698
  delete next.runtimeNodeState;
7610
7699
  return next;
7611
7700
  }
7701
+ function sameExternalStateLookupInput(left, right) {
7702
+ return left.instanceId === right.instanceId && left.instanceKey === right.instanceKey && left.nodeId === right.nodeId && left.subject === right.subject && left.typeId === right.typeId && left.workspaceId === right.workspaceId;
7703
+ }
7612
7704
  function withoutSnapshotNodeState(data) {
7613
7705
  const next = { ...data };
7614
7706
  delete next.snapshotNodeState;
@@ -7688,9 +7780,8 @@ function useWorkbenchHostRuntime({
7688
7780
  snapshotRepository,
7689
7781
  workspaceId
7690
7782
  }) {
7691
- const [externalStateRevision, bumpExternalStateRevision] = useState5(0);
7692
7783
  const [, bumpHydrationRevision] = useState5(0);
7693
- const hostSession = useMemo5(() => {
7784
+ const hostSession = useMemo6(() => {
7694
7785
  logWorkbenchHostDebug("create-session", debugDiagnostics, {
7695
7786
  nodeTypeIDs: nodes.map((node) => node.typeId),
7696
7787
  projectedNodeCount: projectedNodes?.length ?? 0,
@@ -7715,32 +7806,32 @@ function useWorkbenchHostRuntime({
7715
7806
  snapshotRepository,
7716
7807
  workspaceId
7717
7808
  ]);
7718
- const hostI18n = useMemo5(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
7719
- const missionControlI18n = useMemo5(
7809
+ const hostI18n = useMemo6(() => createWorkbenchHostI18nRuntime(i18n), [i18n]);
7810
+ const missionControlI18n = useMemo6(
7720
7811
  () => createWorkbenchMissionControlI18nRuntime(i18n),
7721
7812
  [i18n]
7722
7813
  );
7723
- const windowChromeI18n = useMemo5(
7814
+ const windowChromeI18n = useMemo6(
7724
7815
  () => createWorkbenchWindowChromeI18nRuntime(i18n),
7725
7816
  [i18n]
7726
7817
  );
7727
- const nodeDefinitionByType = useMemo5(
7818
+ const nodeDefinitionByType = useMemo6(
7728
7819
  () => new Map(nodes.map((definition) => [definition.typeId, definition])),
7729
7820
  [nodes]
7730
7821
  );
7731
7822
  const isHydrating = hostSession.isHydrating?.() ?? false;
7732
- const missionControlAdapter = useMemo5(
7823
+ const missionControlAdapter = useMemo6(
7733
7824
  () => missionControlEnabled && !isHydrating ? createWorkbenchHostMissionControlAdapter({
7734
7825
  activateNode: hostSession.activateNode.bind(hostSession),
7735
7826
  controller: hostSession.controller
7736
7827
  }) : null,
7737
7828
  [hostSession.controller, isHydrating, missionControlEnabled]
7738
7829
  );
7739
- const chromeController = useMemo5(
7830
+ const chromeController = useMemo6(
7740
7831
  () => isHydrating ? createReadOnlyWorkbenchController(hostSession.controller) : hostSession.controller,
7741
7832
  [hostSession.controller, isHydrating]
7742
7833
  );
7743
- const chromeContext = useMemo5(
7834
+ const chromeContext = useMemo6(
7744
7835
  () => ({
7745
7836
  activateNode: hostSession.activateNode.bind(hostSession),
7746
7837
  controller: chromeController,
@@ -7782,17 +7873,8 @@ function useWorkbenchHostRuntime({
7782
7873
  useEffect6(() => {
7783
7874
  hostSession.reconcileProjectedNodes(projectedNodes ?? []);
7784
7875
  }, [hostSession, projectedNodes]);
7785
- useEffect6(() => {
7786
- if (!externalStateSource?.subscribe) {
7787
- return void 0;
7788
- }
7789
- return externalStateSource.subscribe(() => {
7790
- bumpExternalStateRevision((revision) => revision + 1);
7791
- });
7792
- }, [externalStateSource, workspaceId]);
7793
7876
  return {
7794
7877
  chromeContext,
7795
- externalStateRevision,
7796
7878
  hostI18n,
7797
7879
  isHydrating,
7798
7880
  hostSession,
@@ -7838,14 +7920,14 @@ function logWorkbenchHostDebug(event, debugDiagnostics, payload) {
7838
7920
  }
7839
7921
 
7840
7922
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
7841
- import { Component, useCallback as useCallback11, useMemo as useMemo7 } from "react";
7923
+ import { Component, useCallback as useCallback12, useMemo as useMemo8 } from "react";
7842
7924
 
7843
7925
  // src/host/WorkbenchHostDock.tsx
7844
7926
  import {
7845
- useCallback as useCallback10,
7927
+ useCallback as useCallback11,
7846
7928
  useEffect as useEffect10,
7847
7929
  useLayoutEffect as useLayoutEffect5,
7848
- useMemo as useMemo6,
7930
+ useMemo as useMemo7,
7849
7931
  useRef as useRef8,
7850
7932
  useState as useState8
7851
7933
  } from "react";
@@ -7950,7 +8032,7 @@ function isWorkbenchDockEntryBlocked(entry) {
7950
8032
  }
7951
8033
 
7952
8034
  // src/host/dockMagnification.ts
7953
- import { useCallback as useCallback8, useEffect as useEffect7, useRef as useRef5 } from "react";
8035
+ import { useCallback as useCallback9, useEffect as useEffect7, useRef as useRef5 } from "react";
7954
8036
 
7955
8037
  // src/host/dockMagnificationBounds.ts
7956
8038
  function resolveDockMagnificationViewportBounds(viewportRect, dockPlacement) {
@@ -8289,7 +8371,7 @@ function useDockMagnification({
8289
8371
  const handleGlobalPointerCancelRef = useRef5(() => {
8290
8372
  return;
8291
8373
  });
8292
- const setMagnifyActive = useCallback8(
8374
+ const setMagnifyActive = useCallback9(
8293
8375
  (active) => {
8294
8376
  if (magnifyActiveRef.current === active) {
8295
8377
  return;
@@ -8303,14 +8385,14 @@ function useDockMagnification({
8303
8385
  },
8304
8386
  [dockRootRef]
8305
8387
  );
8306
- const stopAnimation = useCallback8(() => {
8388
+ const stopAnimation = useCallback9(() => {
8307
8389
  if (animationFrameRef.current !== null) {
8308
8390
  cancelAnimationFrame(animationFrameRef.current);
8309
8391
  animationFrameRef.current = null;
8310
8392
  }
8311
8393
  lastFrameTimeRef.current = null;
8312
8394
  }, []);
8313
- const captureRestCenters = useCallback8(() => {
8395
+ const captureRestCenters = useCallback9(() => {
8314
8396
  const slots = slotRefs.current;
8315
8397
  const centers = /* @__PURE__ */ new Map();
8316
8398
  const slotRects = [];
@@ -8347,7 +8429,7 @@ function useDockMagnification({
8347
8429
  });
8348
8430
  restCentersRef.current = centers;
8349
8431
  }, [dockPlacement, dockViewportRef, slotRefs]);
8350
- const isPointerInsideAnyVisibleDockSlot = useCallback8(
8432
+ const isPointerInsideAnyVisibleDockSlot = useCallback9(
8351
8433
  (clientX, clientY) => {
8352
8434
  for (const rect of visibleSlotRectsRef.current ?? []) {
8353
8435
  if (isDockMagnificationPointInsideSlotRect({
@@ -8362,12 +8444,12 @@ function useDockMagnification({
8362
8444
  },
8363
8445
  []
8364
8446
  );
8365
- const ensureDockMagnificationGeometry = useCallback8(() => {
8447
+ const ensureDockMagnificationGeometry = useCallback9(() => {
8366
8448
  if (restCentersRef.current === null || hitBoundsRef.current === null || visibleSlotRectsRef.current === null) {
8367
8449
  captureRestCenters();
8368
8450
  }
8369
8451
  }, [captureRestCenters]);
8370
- const isPointerInsideDockMagnificationTarget = useCallback8(
8452
+ const isPointerInsideDockMagnificationTarget = useCallback9(
8371
8453
  (clientX, clientY) => isDockMagnificationPointInsideHitBounds({
8372
8454
  clientX,
8373
8455
  clientY,
@@ -8376,7 +8458,7 @@ function useDockMagnification({
8376
8458
  }) || isPointerInsideAnyVisibleDockSlot(clientX, clientY),
8377
8459
  [dockPlacement, isPointerInsideAnyVisibleDockSlot]
8378
8460
  );
8379
- const runAnimationFrame = useCallback8(
8461
+ const runAnimationFrame = useCallback9(
8380
8462
  (frameTime) => {
8381
8463
  if (pendingPointerAxisRef.current !== null) {
8382
8464
  pointerAxisRef.current = pendingPointerAxisRef.current;
@@ -8486,16 +8568,16 @@ function useDockMagnification({
8486
8568
  },
8487
8569
  [captureRestCenters, setMagnifyActive, slotRefs]
8488
8570
  );
8489
- const scheduleAnimation = useCallback8(() => {
8571
+ const scheduleAnimation = useCallback9(() => {
8490
8572
  if (animationFrameRef.current !== null) {
8491
8573
  return;
8492
8574
  }
8493
8575
  animationFrameRef.current = requestAnimationFrame(runAnimationFrame);
8494
8576
  }, [runAnimationFrame]);
8495
- const stopGlobalPointerTracking = useCallback8(() => {
8577
+ const stopGlobalPointerTracking = useCallback9(() => {
8496
8578
  globalPointerTrackerRef.current?.stop();
8497
8579
  }, []);
8498
- const startGlobalPointerTracking = useCallback8(() => {
8580
+ const startGlobalPointerTracking = useCallback9(() => {
8499
8581
  if (typeof document === "undefined") {
8500
8582
  return;
8501
8583
  }
@@ -8511,17 +8593,17 @@ function useDockMagnification({
8511
8593
  });
8512
8594
  globalPointerTrackerRef.current.start();
8513
8595
  }, []);
8514
- const clearTrackedPointer = useCallback8(() => {
8596
+ const clearTrackedPointer = useCallback9(() => {
8515
8597
  pendingPointerAxisRef.current = null;
8516
8598
  pointerAxisRef.current = null;
8517
8599
  entryRampStartedAtRef.current = null;
8518
8600
  scheduleAnimation();
8519
8601
  }, [scheduleAnimation]);
8520
- const handleGlobalPointerCancel = useCallback8(() => {
8602
+ const handleGlobalPointerCancel = useCallback9(() => {
8521
8603
  stopGlobalPointerTracking();
8522
8604
  clearTrackedPointer();
8523
8605
  }, [clearTrackedPointer, stopGlobalPointerTracking]);
8524
- const handlePointerMove = useCallback8(
8606
+ const handlePointerMove = useCallback9(
8525
8607
  (clientX, clientY) => {
8526
8608
  ensureDockMagnificationGeometry();
8527
8609
  if (!isPointerInsideDockMagnificationTarget(clientX, clientY)) {
@@ -8630,12 +8712,12 @@ function useDockMagnification({
8630
8712
  handlePointerMove,
8631
8713
  isPointerInsideDockMagnificationTarget
8632
8714
  ]);
8633
- const handlePointerLeave = useCallback8(() => {
8715
+ const handlePointerLeave = useCallback9(() => {
8634
8716
  pendingPointerAxisRef.current = null;
8635
8717
  pointerAxisRef.current = null;
8636
8718
  scheduleAnimation();
8637
8719
  }, [scheduleAnimation]);
8638
- const clearSlotMagnification = useCallback8(
8720
+ const clearSlotMagnification = useCallback9(
8639
8721
  (anchorKey) => {
8640
8722
  springsRef.current.delete(anchorKey);
8641
8723
  restCentersRef.current?.delete(anchorKey);
@@ -8652,7 +8734,7 @@ function useDockMagnification({
8652
8734
  },
8653
8735
  [slotRefs]
8654
8736
  );
8655
- const pauseMagnification = useCallback8(() => {
8737
+ const pauseMagnification = useCallback9(() => {
8656
8738
  stopGlobalPointerTracking();
8657
8739
  stopAnimation();
8658
8740
  pendingPointerAxisRef.current = null;
@@ -8660,7 +8742,7 @@ function useDockMagnification({
8660
8742
  entryRampStartedAtRef.current = null;
8661
8743
  lastFrameTimeRef.current = null;
8662
8744
  }, [stopAnimation, stopGlobalPointerTracking]);
8663
- const resetMagnification = useCallback8(() => {
8745
+ const resetMagnification = useCallback9(() => {
8664
8746
  stopGlobalPointerTracking();
8665
8747
  stopAnimation();
8666
8748
  for (const slotElement of slotRefs.current.values()) {
@@ -8963,7 +9045,7 @@ function resolveWorkbenchMinimizedDockRestoreIntent(input) {
8963
9045
  // src/host/WorkbenchHostDockPopup.tsx
8964
9046
  import {
8965
9047
  forwardRef,
8966
- useCallback as useCallback9,
9048
+ useCallback as useCallback10,
8967
9049
  useEffect as useEffect9,
8968
9050
  useLayoutEffect as useLayoutEffect4,
8969
9051
  useRef as useRef7,
@@ -9131,6 +9213,12 @@ function resolveDockPopupVerticalClampOffsetPx(input) {
9131
9213
  // src/host/WorkbenchHostDockPopup.tsx
9132
9214
  import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
9133
9215
  var dockPopupCardWidthPx = 165;
9216
+ var dockPopupCardHeightPx = 103;
9217
+ var dockPopupPreviewInsetPx = 4;
9218
+ var workbenchHostDockPopupPreviewViewport = Object.freeze({
9219
+ height: dockPopupCardHeightPx - dockPopupPreviewInsetPx * 2,
9220
+ width: dockPopupCardWidthPx - dockPopupPreviewInsetPx * 2
9221
+ });
9134
9222
  var dockPopupGridGapPx = 8;
9135
9223
  var dockPopupPanelPaddingInlinePx = 12;
9136
9224
  var dockPopupPanelBorderInlinePx = 2;
@@ -9375,7 +9463,7 @@ function WorkbenchHostDockPopup({
9375
9463
  popupCenterY,
9376
9464
  popupDiagnosticKey
9377
9465
  ]);
9378
- const registerCard = useCallback9((nodeId) => {
9466
+ const registerCard = useCallback10((nodeId) => {
9379
9467
  const existing = cardRefCallbacksRef.current.get(nodeId);
9380
9468
  if (existing) {
9381
9469
  return existing;
@@ -10117,7 +10205,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
10117
10205
  },
10118
10206
  []
10119
10207
  );
10120
- const handleSelect = useCallback9(() => {
10208
+ const handleSelect = useCallback10(() => {
10121
10209
  if (!isMinimizedStack) {
10122
10210
  onSelectNode(item.node.id);
10123
10211
  return;
@@ -10131,7 +10219,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
10131
10219
  onSelectNode(item.node.id);
10132
10220
  }, dockPopupMinimizedStackLaunchDisappearMs);
10133
10221
  }, [isMinimizedStack, item.node.id, onSelectNode]);
10134
- const handleSelectKeyDown = useCallback9(
10222
+ const handleSelectKeyDown = useCallback10(
10135
10223
  (event) => {
10136
10224
  if (event.key !== "Enter" && event.key !== " ") {
10137
10225
  return;
@@ -10316,7 +10404,7 @@ function WorkbenchHostDock({
10316
10404
  onMissionControlRequestOpen,
10317
10405
  workspaceId
10318
10406
  }) {
10319
- const minimizedNodeIDs = useMemo6(
10407
+ const minimizedNodeIDs = useMemo7(
10320
10408
  () => new Set(context.minimizedNodes.map((node) => node.id)),
10321
10409
  [context.minimizedNodes]
10322
10410
  );
@@ -10374,14 +10462,14 @@ function WorkbenchHostDock({
10374
10462
  const collapsingMinimizedLaunchTimerRef = useRef8(
10375
10463
  /* @__PURE__ */ new Map()
10376
10464
  );
10377
- const clearHoverPanelCloseTimer = useCallback10(() => {
10465
+ const clearHoverPanelCloseTimer = useCallback11(() => {
10378
10466
  if (hoverPanelCloseTimerRef.current === null) {
10379
10467
  return;
10380
10468
  }
10381
10469
  clearTimeout(hoverPanelCloseTimerRef.current);
10382
10470
  hoverPanelCloseTimerRef.current = null;
10383
10471
  }, []);
10384
- const clearHoverPanelOpenTimer = useCallback10(() => {
10472
+ const clearHoverPanelOpenTimer = useCallback11(() => {
10385
10473
  if (hoverPanelOpenTimerRef.current === null) {
10386
10474
  return;
10387
10475
  }
@@ -10389,7 +10477,7 @@ function WorkbenchHostDock({
10389
10477
  hoverPanelOpenTimerRef.current = null;
10390
10478
  hoverPanelScheduledPointRef.current = null;
10391
10479
  }, []);
10392
- const clearLabelTooltipOpenTimer = useCallback10(() => {
10480
+ const clearLabelTooltipOpenTimer = useCallback11(() => {
10393
10481
  if (labelTooltipOpenTimerRef.current === null) {
10394
10482
  return;
10395
10483
  }
@@ -10413,7 +10501,7 @@ function WorkbenchHostDock({
10413
10501
  clearLabelTooltipOpenTimer
10414
10502
  ]
10415
10503
  );
10416
- const clearCollapsingMinimizedLaunch = useCallback10((anchorKey) => {
10504
+ const clearCollapsingMinimizedLaunch = useCallback11((anchorKey) => {
10417
10505
  const timer = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
10418
10506
  if (timer) {
10419
10507
  clearTimeout(timer);
@@ -10432,7 +10520,7 @@ function WorkbenchHostDock({
10432
10520
  return next;
10433
10521
  });
10434
10522
  }, []);
10435
- const scheduleCollapsingMinimizedLaunchClear = useCallback10(
10523
+ const scheduleCollapsingMinimizedLaunchClear = useCallback11(
10436
10524
  (anchorKey) => {
10437
10525
  const existing = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
10438
10526
  if (existing) {
@@ -10484,7 +10572,7 @@ function WorkbenchHostDock({
10484
10572
  window.removeEventListener("resize", scheduleUpdate);
10485
10573
  };
10486
10574
  }, [dockPlacement]);
10487
- const flushPendingDockStateRefresh = useCallback10(() => {
10575
+ const flushPendingDockStateRefresh = useCallback11(() => {
10488
10576
  if (!pendingDockStateRefreshRef.current) {
10489
10577
  return;
10490
10578
  }
@@ -10503,14 +10591,14 @@ function WorkbenchHostDock({
10503
10591
  setDockStateRevision((revision) => revision + 1);
10504
10592
  });
10505
10593
  }, [dockStateSource]);
10506
- const renderedDockEntries = useMemo6(
10594
+ const renderedDockEntries = useMemo7(
10507
10595
  () => dockEntries.map((entry) => {
10508
10596
  const dynamicState = dockStateSource?.getEntryState(entry.id);
10509
10597
  return dynamicState ? { ...entry, ...dynamicState } : entry;
10510
10598
  }),
10511
10599
  [dockEntries, dockStateRevision, dockStateSource]
10512
10600
  );
10513
- const resolvedEntries = useMemo6(
10601
+ const resolvedEntries = useMemo7(
10514
10602
  () => resolveWorkbenchDockEntries({
10515
10603
  dockEntries: renderedDockEntries,
10516
10604
  minimizedNodeIds: minimizedNodeIDs,
@@ -10518,7 +10606,7 @@ function WorkbenchHostDock({
10518
10606
  }),
10519
10607
  [context.nodes, minimizedNodeIDs, renderedDockEntries]
10520
10608
  );
10521
- const minimizedDockSlots = useMemo6(
10609
+ const minimizedDockSlots = useMemo7(
10522
10610
  () => resolveWorkbenchMinimizedDockSlots({
10523
10611
  nodeDefinitions,
10524
10612
  nodes: context.minimizedNodes
@@ -10526,7 +10614,7 @@ function WorkbenchHostDock({
10526
10614
  [context.minimizedNodes, nodeDefinitions]
10527
10615
  );
10528
10616
  const { promotedNodeId, stackDispatching } = useMinimizedDockStackPromotion(minimizedDockSlots);
10529
- const dockItems = useMemo6(
10617
+ const dockItems = useMemo7(
10530
10618
  () => createWorkbenchHostDockItems({
10531
10619
  minimizedDockSlots,
10532
10620
  resolvedEntries
@@ -10537,7 +10625,7 @@ function WorkbenchHostDock({
10537
10625
  dockItems,
10538
10626
  (nodeId) => context.genie.shouldAnimateMinimizedDockEnter(nodeId)
10539
10627
  );
10540
- const presentDockItemKeys = useMemo6(
10628
+ const presentDockItemKeys = useMemo7(
10541
10629
  () => presentDockItems.map((item) => item.key).join("\n"),
10542
10630
  [presentDockItems]
10543
10631
  );
@@ -10546,7 +10634,7 @@ function WorkbenchHostDock({
10546
10634
  elementRefs: wallpaperToneElementRefs,
10547
10635
  itemKeys: presentDockItemKeys
10548
10636
  });
10549
- const dockWidth = useMemo6(
10637
+ const dockWidth = useMemo7(
10550
10638
  () => resolveWorkbenchHostDockItemsWidth(dockItems),
10551
10639
  [dockItems]
10552
10640
  );
@@ -10576,7 +10664,7 @@ function WorkbenchHostDock({
10576
10664
  registerDockAnchorRef.current = (anchorKey, element) => {
10577
10665
  context.genie.registerDockAnchor(anchorKey, element);
10578
10666
  };
10579
- const registerWallpaperToneElement = useCallback10(
10667
+ const registerWallpaperToneElement = useCallback11(
10580
10668
  (key) => (element) => {
10581
10669
  if (element) {
10582
10670
  wallpaperToneElementRefs.current.set(key, element);
@@ -10586,7 +10674,7 @@ function WorkbenchHostDock({
10586
10674
  },
10587
10675
  []
10588
10676
  );
10589
- const setDockHoverPanelOpen = useCallback10((open) => {
10677
+ const setDockHoverPanelOpen = useCallback11((open) => {
10590
10678
  if (open) {
10591
10679
  dockMeasureRef.current?.setAttribute(
10592
10680
  "data-dock-hover-panel-open",
@@ -10602,7 +10690,7 @@ function WorkbenchHostDock({
10602
10690
  useEffect10(() => {
10603
10691
  activeLabelTooltipRef.current = activeLabelTooltip;
10604
10692
  }, [activeLabelTooltip]);
10605
- const closeLabelTooltipImmediate = useCallback10(
10693
+ const closeLabelTooltipImmediate = useCallback11(
10606
10694
  (targetKey) => {
10607
10695
  clearLabelTooltipOpenTimer();
10608
10696
  if (targetKey !== void 0 && activeLabelTooltipRef.current?.key !== targetKey) {
@@ -10616,7 +10704,7 @@ function WorkbenchHostDock({
10616
10704
  },
10617
10705
  [clearLabelTooltipOpenTimer]
10618
10706
  );
10619
- const closeHoverPanelImmediate = useCallback10(
10707
+ const closeHoverPanelImmediate = useCallback11(
10620
10708
  (entryId) => {
10621
10709
  clearHoverPanelOpenTimer();
10622
10710
  clearHoverPanelCloseTimer();
@@ -10639,7 +10727,7 @@ function WorkbenchHostDock({
10639
10727
  setDockHoverPanelOpen
10640
10728
  ]
10641
10729
  );
10642
- const scheduleHoverPanelClose = useCallback10(
10730
+ const scheduleHoverPanelClose = useCallback11(
10643
10731
  (entryId) => {
10644
10732
  clearHoverPanelOpenTimer();
10645
10733
  clearHoverPanelCloseTimer();
@@ -10656,7 +10744,7 @@ function WorkbenchHostDock({
10656
10744
  handleDockPointerLeave
10657
10745
  ]
10658
10746
  );
10659
- const showHoverPanel = useCallback10(
10747
+ const showHoverPanel = useCallback11(
10660
10748
  (entryId, anchorKey, anchorElement) => {
10661
10749
  const dockElement = dockMeasureRef.current;
10662
10750
  if (!dockElement) {
@@ -10682,7 +10770,7 @@ function WorkbenchHostDock({
10682
10770
  },
10683
10771
  [clearHoverPanelCloseTimer, pauseDockMagnification, setDockHoverPanelOpen]
10684
10772
  );
10685
- const scheduleHoverPanelAfterRest = useCallback10(
10773
+ const scheduleHoverPanelAfterRest = useCallback11(
10686
10774
  (entryId, anchorKey) => {
10687
10775
  hoverPanelRestTargetRef.current = { anchorKey, entryId };
10688
10776
  clearHoverPanelOpenTimer();
@@ -10703,7 +10791,7 @@ function WorkbenchHostDock({
10703
10791
  },
10704
10792
  [clearHoverPanelOpenTimer, showHoverPanel]
10705
10793
  );
10706
- const showLabelTooltip = useCallback10(
10794
+ const showLabelTooltip = useCallback11(
10707
10795
  (target, anchorKey, anchorElement) => {
10708
10796
  const dockElement = dockMeasureRef.current;
10709
10797
  if (!dockElement) {
@@ -10728,7 +10816,7 @@ function WorkbenchHostDock({
10728
10816
  },
10729
10817
  [clearLabelTooltipOpenTimer]
10730
10818
  );
10731
- const scheduleLabelTooltipAfterRest = useCallback10(
10819
+ const scheduleLabelTooltipAfterRest = useCallback11(
10732
10820
  (target, anchorKey) => {
10733
10821
  clearLabelTooltipOpenTimer();
10734
10822
  labelTooltipScheduledPointRef.current = null;
@@ -10744,7 +10832,7 @@ function WorkbenchHostDock({
10744
10832
  },
10745
10833
  [clearLabelTooltipOpenTimer, showLabelTooltip]
10746
10834
  );
10747
- const resolveHoverPanelTargetAtPoint = useCallback10(
10835
+ const resolveHoverPanelTargetAtPoint = useCallback11(
10748
10836
  (clientX, clientY) => {
10749
10837
  for (const [anchorKey, slotElement] of slotRefs.current) {
10750
10838
  const entryId = slotElement.dataset.dockHoverPanelEntryId;
@@ -10760,7 +10848,7 @@ function WorkbenchHostDock({
10760
10848
  },
10761
10849
  []
10762
10850
  );
10763
- const resolveLabelTooltipTargetAtPoint = useCallback10(
10851
+ const resolveLabelTooltipTargetAtPoint = useCallback11(
10764
10852
  (clientX, clientY) => {
10765
10853
  for (const [anchorKey, slotElement] of slotRefs.current) {
10766
10854
  if (slotElement.dataset.dockHoverPanelEntryId) {
@@ -10787,7 +10875,7 @@ function WorkbenchHostDock({
10787
10875
  },
10788
10876
  []
10789
10877
  );
10790
- const isPointerInsideActiveHoverPanelRegion = useCallback10(
10878
+ const isPointerInsideActiveHoverPanelRegion = useCallback11(
10791
10879
  (clientX, clientY) => {
10792
10880
  const activeHoverPanel2 = activeHoverPanelRef.current;
10793
10881
  if (!activeHoverPanel2) {
@@ -10819,7 +10907,7 @@ function WorkbenchHostDock({
10819
10907
  },
10820
10908
  []
10821
10909
  );
10822
- const scheduleHoverPanelAtPointAfterRest = useCallback10(
10910
+ const scheduleHoverPanelAtPointAfterRest = useCallback11(
10823
10911
  (clientX, clientY) => {
10824
10912
  const scheduledPoint = hoverPanelScheduledPointRef.current;
10825
10913
  if (hoverPanelOpenTimerRef.current !== null && scheduledPoint && Math.abs(clientX - scheduledPoint.clientX) <= dockHoverPanelPointerRestTolerancePx && Math.abs(clientY - scheduledPoint.clientY) <= dockHoverPanelPointerRestTolerancePx) {
@@ -10847,7 +10935,7 @@ function WorkbenchHostDock({
10847
10935
  },
10848
10936
  [clearHoverPanelOpenTimer, resolveHoverPanelTargetAtPoint, showHoverPanel]
10849
10937
  );
10850
- const scheduleLabelTooltipAtPointAfterRest = useCallback10(
10938
+ const scheduleLabelTooltipAtPointAfterRest = useCallback11(
10851
10939
  (clientX, clientY) => {
10852
10940
  if (activeLabelTooltipRef.current !== null) {
10853
10941
  return;
@@ -10877,7 +10965,7 @@ function WorkbenchHostDock({
10877
10965
  showLabelTooltip
10878
10966
  ]
10879
10967
  );
10880
- const beginDockIconInteraction = useCallback10(
10968
+ const beginDockIconInteraction = useCallback11(
10881
10969
  (anchorKey) => {
10882
10970
  hoverPanelRestTargetRef.current = null;
10883
10971
  clearHoverPanelOpenTimer();
@@ -10892,20 +10980,20 @@ function WorkbenchHostDock({
10892
10980
  triggerDockBounce
10893
10981
  ]
10894
10982
  );
10895
- const isDockEntryClickThrottled = useCallback10(
10983
+ const isDockEntryClickThrottled = useCallback11(
10896
10984
  (anchorKey) => {
10897
10985
  const throttledUntil = dockEntryClickThrottleUntilRef.current.get(anchorKey);
10898
10986
  return throttledUntil !== void 0 && Date.now() < throttledUntil;
10899
10987
  },
10900
10988
  []
10901
10989
  );
10902
- const claimDockEntryClick = useCallback10((anchorKey) => {
10990
+ const claimDockEntryClick = useCallback11((anchorKey) => {
10903
10991
  dockEntryClickThrottleUntilRef.current.set(
10904
10992
  anchorKey,
10905
10993
  Date.now() + DOCK_ENTRY_CLICK_THROTTLE_MS
10906
10994
  );
10907
10995
  }, []);
10908
- const beginDockMinimizedInteraction = useCallback10(
10996
+ const beginDockMinimizedInteraction = useCallback11(
10909
10997
  (anchorKey) => {
10910
10998
  hoverPanelRestTargetRef.current = null;
10911
10999
  clearHoverPanelOpenTimer();
@@ -10945,7 +11033,7 @@ function WorkbenchHostDock({
10945
11033
  pauseDockMagnification
10946
11034
  ]
10947
11035
  );
10948
- const runDockMinimizedLaunchAfterCollapse = useCallback10(
11036
+ const runDockMinimizedLaunchAfterCollapse = useCallback11(
10949
11037
  (intent, launch) => {
10950
11038
  const { anchorKey } = intent;
10951
11039
  beginDockMinimizedInteraction(anchorKey);
@@ -10959,14 +11047,14 @@ function WorkbenchHostDock({
10959
11047
  },
10960
11048
  [beginDockMinimizedInteraction, scheduleCollapsingMinimizedLaunchClear]
10961
11049
  );
10962
- const runDockMinimizedStackLaunch = useCallback10(
11050
+ const runDockMinimizedStackLaunch = useCallback11(
10963
11051
  (intent, launch) => {
10964
11052
  beginDockMinimizedInteraction();
10965
11053
  launch(intent);
10966
11054
  },
10967
11055
  [beginDockMinimizedInteraction]
10968
11056
  );
10969
- const handleDockPointerTravel = useCallback10(
11057
+ const handleDockPointerTravel = useCallback11(
10970
11058
  (clientX, clientY) => {
10971
11059
  if (activeHoverPanelRef.current !== null) {
10972
11060
  closeLabelTooltipImmediate();
@@ -11001,7 +11089,7 @@ function WorkbenchHostDock({
11001
11089
  scheduleLabelTooltipAtPointAfterRest
11002
11090
  ]
11003
11091
  );
11004
- const updateDockScrollState = useCallback10(() => {
11092
+ const updateDockScrollState = useCallback11(() => {
11005
11093
  const scrollElement = dockItemsRef.current;
11006
11094
  const viewportElement = dockMeasureRef.current;
11007
11095
  if (!scrollElement || !viewportElement) {
@@ -11073,13 +11161,29 @@ function WorkbenchHostDock({
11073
11161
  );
11074
11162
  useEffect10(() => {
11075
11163
  const shouldSubscribe = activePopup !== null || hasMinimizedPreviewCapture;
11076
- if (!shouldSubscribe || !externalStateSource?.subscribe) {
11164
+ if (!shouldSubscribe || !externalStateSource?.subscribeNodeState) {
11077
11165
  return void 0;
11078
11166
  }
11079
- return externalStateSource.subscribe(() => {
11080
- setExternalStateRevision((revision) => revision + 1);
11081
- });
11082
- }, [activePopup, externalStateSource, hasMinimizedPreviewCapture]);
11167
+ const nodes = activePopup ? context.nodes : context.minimizedNodes;
11168
+ const disposers = nodes.map(
11169
+ (node) => externalStateSource.subscribeNodeState?.(
11170
+ createWorkbenchHostExternalStateLookupInput({ node, workspaceId }),
11171
+ () => setExternalStateRevision((revision) => revision + 1)
11172
+ )
11173
+ );
11174
+ return () => {
11175
+ for (const dispose of disposers) {
11176
+ dispose?.();
11177
+ }
11178
+ };
11179
+ }, [
11180
+ activePopup,
11181
+ context.minimizedNodes,
11182
+ context.nodes,
11183
+ externalStateSource,
11184
+ hasMinimizedPreviewCapture,
11185
+ workspaceId
11186
+ ]);
11083
11187
  useEffect10(() => {
11084
11188
  const nextAttentionIds = /* @__PURE__ */ new Set();
11085
11189
  for (const entry of renderedDockEntries) {
@@ -11130,7 +11234,7 @@ function WorkbenchHostDock({
11130
11234
  },
11131
11235
  []
11132
11236
  );
11133
- const captureMinimizedNodePreview = useCallback10(
11237
+ const captureMinimizedNodePreview = useCallback11(
11134
11238
  async (node) => {
11135
11239
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11136
11240
  const capturePreview = minimizedDock?.kind === "snapshot" ? minimizedDock.capturePreview : void 0;
@@ -11161,7 +11265,7 @@ function WorkbenchHostDock({
11161
11265
  workspaceId
11162
11266
  ]
11163
11267
  );
11164
- const provideMinimizedNodePreview = useCallback10(
11268
+ const provideMinimizedNodePreview = useCallback11(
11165
11269
  (node) => {
11166
11270
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11167
11271
  if (minimizedDock?.kind !== "component") {
@@ -11190,7 +11294,7 @@ function WorkbenchHostDock({
11190
11294
  workspaceId
11191
11295
  ]
11192
11296
  );
11193
- const provideMinimizedNodePreviewForNode = useCallback10(
11297
+ const provideMinimizedNodePreviewForNode = useCallback11(
11194
11298
  (node) => {
11195
11299
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11196
11300
  return minimizedDock?.kind === "component" ? provideMinimizedNodePreview : void 0;
@@ -11226,7 +11330,7 @@ function WorkbenchHostDock({
11226
11330
  top: isVertical ? delta : 0
11227
11331
  });
11228
11332
  };
11229
- const registerDockSlot = useCallback10((anchorKey) => {
11333
+ const registerDockSlot = useCallback11((anchorKey) => {
11230
11334
  const existing = dockSlotRefCallbacksRef.current.get(anchorKey);
11231
11335
  if (existing) {
11232
11336
  return existing;
@@ -11247,7 +11351,7 @@ function WorkbenchHostDock({
11247
11351
  dockSlotRefCallbacksRef.current.set(anchorKey, callback);
11248
11352
  return callback;
11249
11353
  }, []);
11250
- const runDockEntryAction = useCallback10(
11354
+ const runDockEntryAction = useCallback11(
11251
11355
  (entryId, actionId) => {
11252
11356
  const actionKey = dockActionKey(entryId, actionId);
11253
11357
  if (pendingActionKeys.has(actionKey)) {
@@ -12039,7 +12143,8 @@ function WorkbenchHostDock({
12039
12143
  host,
12040
12144
  isFocused: context.focusedNodeId === node.id,
12041
12145
  isMinimized: minimizedNodeIDs.has(node.id),
12042
- node
12146
+ node,
12147
+ previewViewport: workbenchHostDockPopupPreviewViewport
12043
12148
  };
12044
12149
  const descriptor = popupEntry.entry.resolvePopupItem?.(item) ?? {};
12045
12150
  const descriptorPreview = descriptor.preview ?? popupEntry.entry.providePopupItemPreview?.(item) ?? null;
@@ -13105,7 +13210,7 @@ var DOCK_BOUNCE_MS = 600;
13105
13210
  var DOCK_ENTRY_CLICK_THROTTLE_MS = DOCK_BOUNCE_MS;
13106
13211
  function useDockBounce(slotRefs) {
13107
13212
  const timeoutsRef = useRef8(/* @__PURE__ */ new Map());
13108
- const clearDockBounce = useCallback10(
13213
+ const clearDockBounce = useCallback11(
13109
13214
  (anchorKey) => {
13110
13215
  const timeout = timeoutsRef.current.get(anchorKey);
13111
13216
  const slotElement = slotRefs.current.get(anchorKey);
@@ -13128,7 +13233,7 @@ function useDockBounce(slotRefs) {
13128
13233
  },
13129
13234
  [clearDockBounce]
13130
13235
  );
13131
- const triggerDockBounce = useCallback10(
13236
+ const triggerDockBounce = useCallback11(
13132
13237
  (anchorKey) => {
13133
13238
  const shouldRestartAnimation = clearDockBounce(anchorKey);
13134
13239
  const slotElement = slotRefs.current.get(anchorKey);
@@ -13230,11 +13335,12 @@ function createWorkbenchHostNodeHeaderWindowActions(context, input = {}) {
13230
13335
  // src/host/hostNodeContext.ts
13231
13336
  function createWorkbenchHostNodeBodyContext({
13232
13337
  context,
13338
+ externalState,
13233
13339
  externalStateSource,
13234
13340
  host,
13235
13341
  workspaceId
13236
13342
  }) {
13237
- const externalState = readWorkbenchHostExternalState({
13343
+ const resolvedExternalState = externalState ?? readWorkbenchHostExternalState({
13238
13344
  externalStateSource,
13239
13345
  node: context.node,
13240
13346
  workspaceId
@@ -13242,8 +13348,8 @@ function createWorkbenchHostNodeBodyContext({
13242
13348
  return {
13243
13349
  activation: context.node.data.activation ?? null,
13244
13350
  displayMode: context.node.displayMode,
13245
- externalNodeState: externalState.externalNodeState,
13246
- externalWorkspaceState: externalState.externalWorkspaceState,
13351
+ externalNodeState: resolvedExternalState.externalNodeState,
13352
+ externalWorkspaceState: resolvedExternalState.externalWorkspaceState,
13247
13353
  focus() {
13248
13354
  host.focusNode(context.node.id);
13249
13355
  },
@@ -13265,11 +13371,12 @@ function createWorkbenchHostNodeBodyContext({
13265
13371
  }
13266
13372
  function createWorkbenchHostNodeHeaderContext({
13267
13373
  context,
13374
+ externalState,
13268
13375
  externalStateSource,
13269
13376
  host,
13270
13377
  workspaceId
13271
13378
  }) {
13272
- const externalState = readWorkbenchHostExternalState({
13379
+ const resolvedExternalState = externalState ?? readWorkbenchHostExternalState({
13273
13380
  externalStateSource,
13274
13381
  node: context.node,
13275
13382
  workspaceId
@@ -13279,8 +13386,8 @@ function createWorkbenchHostNodeHeaderContext({
13279
13386
  defaultActions: context.defaultActions,
13280
13387
  displayMode: context.node.displayMode,
13281
13388
  dragHandleProps: context.dragHandleProps,
13282
- externalNodeState: externalState.externalNodeState,
13283
- externalWorkspaceState: externalState.externalWorkspaceState,
13389
+ externalNodeState: resolvedExternalState.externalNodeState,
13390
+ externalWorkspaceState: resolvedExternalState.externalWorkspaceState,
13284
13391
  instanceId: context.node.data.instanceId,
13285
13392
  instanceKey: context.node.data.instanceKey ?? null,
13286
13393
  isFocused: selectFocusedWorkbenchNode(host.getSnapshot())?.id === context.node.id,
@@ -13331,7 +13438,7 @@ function WorkbenchHostWindowActions({
13331
13438
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
13332
13439
  import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
13333
13440
  function useWorkbenchHostSurfaceRenderers(input) {
13334
- const renderBottomChrome = useMemo7(() => {
13441
+ const renderBottomChrome = useMemo8(() => {
13335
13442
  const renderChrome = input.renderBottomChrome;
13336
13443
  return renderChrome ? () => /* @__PURE__ */ jsx14(
13337
13444
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -13359,7 +13466,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13359
13466
  input.renderBottomChrome,
13360
13467
  input.workspaceId
13361
13468
  ]);
13362
- const renderTopChrome = useMemo7(() => {
13469
+ const renderTopChrome = useMemo8(() => {
13363
13470
  const renderChrome = input.renderTopChrome;
13364
13471
  return renderChrome ? () => /* @__PURE__ */ jsx14(
13365
13472
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -13387,7 +13494,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13387
13494
  input.renderTopChrome,
13388
13495
  input.workspaceId
13389
13496
  ]);
13390
- const captureNodePreviewImage = useCallback11(
13497
+ const captureNodePreviewImage = useCallback12(
13391
13498
  async (node) => {
13392
13499
  const definition = input.nodeDefinitionByType.get(node.data.typeId);
13393
13500
  const minimizedDock = definition?.window?.minimizedDock;
@@ -13420,7 +13527,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13420
13527
  input.workspaceId
13421
13528
  ]
13422
13529
  );
13423
- const renderDock = useCallback11(
13530
+ const renderDock = useCallback12(
13424
13531
  (context) => /* @__PURE__ */ jsx14(
13425
13532
  WorkbenchHostSurfaceRenderErrorBoundary,
13426
13533
  {
@@ -13472,7 +13579,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13472
13579
  input.workspaceId
13473
13580
  ]
13474
13581
  );
13475
- const renderNode = useCallback11(
13582
+ const renderNode = useCallback12(
13476
13583
  (context) => {
13477
13584
  const definition = input.nodeDefinitionByType.get(
13478
13585
  context.node.data.typeId
@@ -13480,44 +13587,27 @@ function useWorkbenchHostSurfaceRenderers(input) {
13480
13587
  if (!definition) {
13481
13588
  return null;
13482
13589
  }
13483
- const bodyContext = createWorkbenchHostNodeBodyContext({
13484
- context,
13485
- definition,
13486
- externalStateSource: input.externalStateSource,
13487
- host: input.hostSession,
13488
- workspaceId: input.workspaceId
13489
- });
13490
13590
  return /* @__PURE__ */ jsx14(
13491
- WorkbenchHostNodeRenderErrorBoundary,
13591
+ WorkbenchHostNodeRenderer,
13492
13592
  {
13493
13593
  debugDiagnostics: input.debugDiagnostics,
13494
- node: context.node,
13495
- onErrorChange: (hasError) => definition.onBodyRenderErrorChange?.({
13496
- hasError,
13497
- node: context.node
13498
- }),
13499
- resetKey: `${context.node.id}:${context.node.data.typeId}:${input.externalStateRevision}`,
13500
- workspaceId: input.workspaceId,
13501
- children: /* @__PURE__ */ jsx14(
13502
- WorkbenchHostNodeBodyRenderer,
13503
- {
13504
- context: bodyContext,
13505
- definition
13506
- }
13507
- )
13594
+ context,
13595
+ definition,
13596
+ externalStateSource: input.externalStateSource,
13597
+ host: input.hostSession,
13598
+ workspaceId: input.workspaceId
13508
13599
  }
13509
13600
  );
13510
13601
  },
13511
13602
  [
13512
13603
  input.debugDiagnostics,
13513
13604
  input.externalStateSource,
13514
- input.externalStateRevision,
13515
13605
  input.hostSession,
13516
13606
  input.nodeDefinitionByType,
13517
13607
  input.workspaceId
13518
13608
  ]
13519
13609
  );
13520
- const renderWindowActions = useCallback11(
13610
+ const renderWindowActions = useCallback12(
13521
13611
  (context) => /* @__PURE__ */ jsx14(
13522
13612
  WorkbenchHostWindowActions,
13523
13613
  {
@@ -13529,7 +13619,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13529
13619
  ),
13530
13620
  [input.hostI18n, input.hostSession, input.nodeDefinitionByType]
13531
13621
  );
13532
- const renderWindowHeader = useCallback11(
13622
+ const renderWindowHeader = useCallback12(
13533
13623
  (context) => {
13534
13624
  const definition = input.nodeDefinitionByType.get(
13535
13625
  context.node.data.typeId
@@ -13537,39 +13627,39 @@ function useWorkbenchHostSurfaceRenderers(input) {
13537
13627
  if (!definition?.renderHeader) {
13538
13628
  return null;
13539
13629
  }
13540
- return definition.renderHeader(
13541
- createWorkbenchHostNodeHeaderContext({
13630
+ return /* @__PURE__ */ jsx14(
13631
+ WorkbenchHostNodeHeaderRenderer,
13632
+ {
13542
13633
  context,
13543
13634
  definition,
13544
13635
  externalStateSource: input.externalStateSource,
13545
13636
  host: input.hostSession,
13546
13637
  workspaceId: input.workspaceId
13547
- })
13638
+ }
13548
13639
  );
13549
13640
  },
13550
13641
  [
13551
13642
  input.externalStateSource,
13552
- input.externalStateRevision,
13553
13643
  input.hostSession,
13554
13644
  input.nodeDefinitionByType,
13555
13645
  input.workspaceId
13556
13646
  ]
13557
13647
  );
13558
- const shouldKeepMinimizedNodeMounted = useCallback11(
13648
+ const shouldKeepMinimizedNodeMounted = useCallback12(
13559
13649
  (node) => {
13560
13650
  const capability = input.nodeDefinitionByType.get(node.data.typeId)?.window?.keepMountedWhenMinimized;
13561
13651
  return typeof capability === "function" ? capability(node) : capability === true;
13562
13652
  },
13563
13653
  [input.nodeDefinitionByType]
13564
13654
  );
13565
- const shouldCaptureNodePreviewImage = useCallback11(
13655
+ const shouldCaptureNodePreviewImage = useCallback12(
13566
13656
  (node) => {
13567
13657
  const minimizedDock = input.nodeDefinitionByType.get(node.data.typeId)?.window?.minimizedDock;
13568
13658
  return minimizedDock?.kind !== "component";
13569
13659
  },
13570
13660
  [input.nodeDefinitionByType]
13571
13661
  );
13572
- const renderNodeGeniePreview = useCallback11(
13662
+ const renderNodeGeniePreview = useCallback12(
13573
13663
  (node, {
13574
13664
  previewViewport
13575
13665
  }) => {
@@ -13603,7 +13693,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13603
13693
  input.workspaceId
13604
13694
  ]
13605
13695
  );
13606
- const resolveDockAnchorKey = useCallback11(
13696
+ const resolveDockAnchorKey = useCallback12(
13607
13697
  (node) => {
13608
13698
  if (node.isMinimized && isWorkbenchMinimizedDockEligibleNode({
13609
13699
  node,
@@ -13636,7 +13726,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13636
13726
  },
13637
13727
  [input.dockEntries, input.hostSession, input.nodeDefinitionByType]
13638
13728
  );
13639
- const resolveDockPreviewCacheKey2 = useCallback11(
13729
+ const resolveDockPreviewCacheKey2 = useCallback12(
13640
13730
  (node) => ({
13641
13731
  instanceId: node.data.instanceId,
13642
13732
  instanceKey: node.data.instanceKey ?? null,
@@ -13646,16 +13736,16 @@ function useWorkbenchHostSurfaceRenderers(input) {
13646
13736
  }),
13647
13737
  [input.workspaceId]
13648
13738
  );
13649
- const windowChromeMode = useCallback11(
13739
+ const windowChromeMode = useCallback12(
13650
13740
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.renderHeader ? "custom-header" : "system",
13651
13741
  [input.nodeDefinitionByType]
13652
13742
  );
13653
- const resolveWindowZIndex = useCallback11(({ baseZIndex }) => baseZIndex, []);
13654
- const resolveWindowSurfaceLayer = useCallback11(
13743
+ const resolveWindowZIndex = useCallback12(({ baseZIndex }) => baseZIndex, []);
13744
+ const resolveWindowSurfaceLayer = useCallback12(
13655
13745
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.surfaceLayer ?? "default",
13656
13746
  [input.nodeDefinitionByType]
13657
13747
  );
13658
- const resolveFullscreenHeaderMode = useCallback11(
13748
+ const resolveFullscreenHeaderMode = useCallback12(
13659
13749
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.fullscreenHeaderMode,
13660
13750
  [input.nodeDefinitionByType]
13661
13751
  );
@@ -13678,6 +13768,72 @@ function useWorkbenchHostSurfaceRenderers(input) {
13678
13768
  windowChromeMode
13679
13769
  };
13680
13770
  }
13771
+ function WorkbenchHostNodeRenderer(input) {
13772
+ const externalState = useWorkbenchHostExternalState({
13773
+ externalStateSource: input.externalStateSource,
13774
+ node: input.context.node,
13775
+ workspaceId: input.workspaceId
13776
+ });
13777
+ const bodyContext = createWorkbenchHostNodeBodyContext({
13778
+ context: input.context,
13779
+ definition: input.definition,
13780
+ externalState,
13781
+ externalStateSource: input.externalStateSource,
13782
+ host: input.host,
13783
+ workspaceId: input.workspaceId
13784
+ });
13785
+ const resetKey = useMemo8(
13786
+ () => [
13787
+ input.context.node.id,
13788
+ input.context.node.data.typeId,
13789
+ externalState.externalNodeState,
13790
+ externalState.externalWorkspaceState
13791
+ ],
13792
+ [
13793
+ externalState.externalNodeState,
13794
+ externalState.externalWorkspaceState,
13795
+ input.context.node.data.typeId,
13796
+ input.context.node.id
13797
+ ]
13798
+ );
13799
+ return /* @__PURE__ */ jsx14(
13800
+ WorkbenchHostNodeRenderErrorBoundary,
13801
+ {
13802
+ debugDiagnostics: input.debugDiagnostics,
13803
+ node: input.context.node,
13804
+ onErrorChange: (hasError) => input.definition.onBodyRenderErrorChange?.({
13805
+ hasError,
13806
+ node: input.context.node
13807
+ }),
13808
+ resetKey,
13809
+ workspaceId: input.workspaceId,
13810
+ children: /* @__PURE__ */ jsx14(
13811
+ WorkbenchHostNodeBodyRenderer,
13812
+ {
13813
+ context: bodyContext,
13814
+ definition: input.definition
13815
+ }
13816
+ )
13817
+ }
13818
+ );
13819
+ }
13820
+ function WorkbenchHostNodeHeaderRenderer(input) {
13821
+ const externalState = useWorkbenchHostExternalState({
13822
+ externalStateSource: input.externalStateSource,
13823
+ node: input.context.node,
13824
+ workspaceId: input.workspaceId
13825
+ });
13826
+ return input.definition.renderHeader?.(
13827
+ createWorkbenchHostNodeHeaderContext({
13828
+ context: input.context,
13829
+ definition: input.definition,
13830
+ externalState,
13831
+ externalStateSource: input.externalStateSource,
13832
+ host: input.host,
13833
+ workspaceId: input.workspaceId
13834
+ })
13835
+ );
13836
+ }
13681
13837
  var WorkbenchHostSurfaceRenderErrorBoundary = class extends Component {
13682
13838
  state = {
13683
13839
  hasError: false
@@ -13730,7 +13886,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
13730
13886
  return { hasError: true };
13731
13887
  }
13732
13888
  componentDidUpdate(previousProps) {
13733
- if (this.state.hasError && previousProps.resetKey !== this.props.resetKey) {
13889
+ if (this.state.hasError && !Object.is(previousProps.resetKey, this.props.resetKey)) {
13734
13890
  this.setState({ hasError: false });
13735
13891
  this.props.onErrorChange?.(false);
13736
13892
  }
@@ -13879,7 +14035,7 @@ function WorkbenchHost({
13879
14035
  windowManagement,
13880
14036
  workspaceId
13881
14037
  }) {
13882
- const hostRuntimeConfig = useMemo8(
14038
+ const hostRuntimeConfig = useMemo9(
13883
14039
  () => resolveWorkbenchHostRuntimeConfig({
13884
14040
  contributions,
13885
14041
  externalStateSource,
@@ -13895,7 +14051,7 @@ function WorkbenchHost({
13895
14051
  onNodeCloseRequest
13896
14052
  ]
13897
14053
  );
13898
- const hostDockEntries = useMemo8(
14054
+ const hostDockEntries = useMemo9(
13899
14055
  () => resolveWorkbenchHostDockEntries({
13900
14056
  contributions,
13901
14057
  dockEntryPresentationOverrides,
@@ -13910,7 +14066,6 @@ function WorkbenchHost({
13910
14066
  const missionControlEnabled = missionControlMode !== null || onMissionControlAdapterReady !== void 0;
13911
14067
  const {
13912
14068
  chromeContext,
13913
- externalStateRevision,
13914
14069
  hostI18n,
13915
14070
  hostSession,
13916
14071
  isHydrating,
@@ -13941,7 +14096,6 @@ function WorkbenchHost({
13941
14096
  dockStateSource,
13942
14097
  dockEntries: hostDockEntries,
13943
14098
  externalStateSource: hostRuntimeConfig.externalStateSource,
13944
- externalStateRevision,
13945
14099
  hostI18n,
13946
14100
  hostSession,
13947
14101
  nodeDefinitionByType,
@@ -14012,7 +14166,63 @@ function WorkbenchHost({
14012
14166
  }
14013
14167
  );
14014
14168
  }
14169
+
14170
+ // src/react/WorkbenchDockComponentPreviewFrame.tsx
14171
+ import { jsx as jsx16 } from "react/jsx-runtime";
14172
+ function WorkbenchDockComponentPreviewFrame({
14173
+ children,
14174
+ sourceSize,
14175
+ viewport
14176
+ }) {
14177
+ const sourceHeight = Math.max(1, sourceSize.height);
14178
+ const sourceWidth = Math.max(1, sourceSize.width);
14179
+ const viewportHeight = Math.max(1, viewport.height);
14180
+ const viewportWidth = Math.max(1, viewport.width);
14181
+ const scale = Math.min(
14182
+ viewportWidth / sourceWidth,
14183
+ viewportHeight / sourceHeight
14184
+ );
14185
+ const frameStyle = {
14186
+ background: "transparent",
14187
+ borderRadius: "0.375rem",
14188
+ display: "block",
14189
+ height: `${viewportHeight}px`,
14190
+ overflow: "hidden",
14191
+ pointerEvents: "none",
14192
+ position: "relative",
14193
+ width: `${viewportWidth}px`
14194
+ };
14195
+ const contentStyle = {
14196
+ display: "block",
14197
+ height: `${sourceHeight}px`,
14198
+ left: "50%",
14199
+ overflow: "hidden",
14200
+ pointerEvents: "none",
14201
+ position: "absolute",
14202
+ top: "50%",
14203
+ transform: `translate(-50%, -50%) scale(${scale})`,
14204
+ transformOrigin: "center",
14205
+ width: `${sourceWidth}px`
14206
+ };
14207
+ return /* @__PURE__ */ jsx16(
14208
+ "span",
14209
+ {
14210
+ "aria-hidden": "true",
14211
+ "data-workbench-dock-component-preview-frame": "true",
14212
+ style: frameStyle,
14213
+ children: /* @__PURE__ */ jsx16(
14214
+ "span",
14215
+ {
14216
+ "data-workbench-dock-component-preview-content": "true",
14217
+ style: contentStyle,
14218
+ children
14219
+ }
14220
+ )
14221
+ }
14222
+ );
14223
+ }
14015
14224
  export {
14225
+ WorkbenchDockComponentPreviewFrame,
14016
14226
  WorkbenchHost,
14017
14227
  WorkbenchSurface,
14018
14228
  createWorkbenchController,