@tutti-os/workbench-surface 0.0.152 → 0.0.154

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,17 +7585,50 @@ 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);
7625
+ }
7626
+ }
7627
+ disposeExternalStatePersistenceSubscriptions() {
7628
+ for (const subscription of this.externalStatePersistenceSubscriptions.values()) {
7629
+ subscription.unsubscribe();
7542
7630
  }
7631
+ this.externalStatePersistenceSubscriptions.clear();
7543
7632
  }
7544
7633
  disposeNodeLeases() {
7545
7634
  for (const lease of this.nodeLeases.values()) {
@@ -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,
@@ -9375,7 +9457,7 @@ function WorkbenchHostDockPopup({
9375
9457
  popupCenterY,
9376
9458
  popupDiagnosticKey
9377
9459
  ]);
9378
- const registerCard = useCallback9((nodeId) => {
9460
+ const registerCard = useCallback10((nodeId) => {
9379
9461
  const existing = cardRefCallbacksRef.current.get(nodeId);
9380
9462
  if (existing) {
9381
9463
  return existing;
@@ -10117,7 +10199,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
10117
10199
  },
10118
10200
  []
10119
10201
  );
10120
- const handleSelect = useCallback9(() => {
10202
+ const handleSelect = useCallback10(() => {
10121
10203
  if (!isMinimizedStack) {
10122
10204
  onSelectNode(item.node.id);
10123
10205
  return;
@@ -10131,7 +10213,7 @@ var WorkbenchHostDockPopupCard = forwardRef(function WorkbenchHostDockPopupCard2
10131
10213
  onSelectNode(item.node.id);
10132
10214
  }, dockPopupMinimizedStackLaunchDisappearMs);
10133
10215
  }, [isMinimizedStack, item.node.id, onSelectNode]);
10134
- const handleSelectKeyDown = useCallback9(
10216
+ const handleSelectKeyDown = useCallback10(
10135
10217
  (event) => {
10136
10218
  if (event.key !== "Enter" && event.key !== " ") {
10137
10219
  return;
@@ -10316,7 +10398,7 @@ function WorkbenchHostDock({
10316
10398
  onMissionControlRequestOpen,
10317
10399
  workspaceId
10318
10400
  }) {
10319
- const minimizedNodeIDs = useMemo6(
10401
+ const minimizedNodeIDs = useMemo7(
10320
10402
  () => new Set(context.minimizedNodes.map((node) => node.id)),
10321
10403
  [context.minimizedNodes]
10322
10404
  );
@@ -10374,14 +10456,14 @@ function WorkbenchHostDock({
10374
10456
  const collapsingMinimizedLaunchTimerRef = useRef8(
10375
10457
  /* @__PURE__ */ new Map()
10376
10458
  );
10377
- const clearHoverPanelCloseTimer = useCallback10(() => {
10459
+ const clearHoverPanelCloseTimer = useCallback11(() => {
10378
10460
  if (hoverPanelCloseTimerRef.current === null) {
10379
10461
  return;
10380
10462
  }
10381
10463
  clearTimeout(hoverPanelCloseTimerRef.current);
10382
10464
  hoverPanelCloseTimerRef.current = null;
10383
10465
  }, []);
10384
- const clearHoverPanelOpenTimer = useCallback10(() => {
10466
+ const clearHoverPanelOpenTimer = useCallback11(() => {
10385
10467
  if (hoverPanelOpenTimerRef.current === null) {
10386
10468
  return;
10387
10469
  }
@@ -10389,7 +10471,7 @@ function WorkbenchHostDock({
10389
10471
  hoverPanelOpenTimerRef.current = null;
10390
10472
  hoverPanelScheduledPointRef.current = null;
10391
10473
  }, []);
10392
- const clearLabelTooltipOpenTimer = useCallback10(() => {
10474
+ const clearLabelTooltipOpenTimer = useCallback11(() => {
10393
10475
  if (labelTooltipOpenTimerRef.current === null) {
10394
10476
  return;
10395
10477
  }
@@ -10413,7 +10495,7 @@ function WorkbenchHostDock({
10413
10495
  clearLabelTooltipOpenTimer
10414
10496
  ]
10415
10497
  );
10416
- const clearCollapsingMinimizedLaunch = useCallback10((anchorKey) => {
10498
+ const clearCollapsingMinimizedLaunch = useCallback11((anchorKey) => {
10417
10499
  const timer = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
10418
10500
  if (timer) {
10419
10501
  clearTimeout(timer);
@@ -10432,7 +10514,7 @@ function WorkbenchHostDock({
10432
10514
  return next;
10433
10515
  });
10434
10516
  }, []);
10435
- const scheduleCollapsingMinimizedLaunchClear = useCallback10(
10517
+ const scheduleCollapsingMinimizedLaunchClear = useCallback11(
10436
10518
  (anchorKey) => {
10437
10519
  const existing = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
10438
10520
  if (existing) {
@@ -10484,7 +10566,7 @@ function WorkbenchHostDock({
10484
10566
  window.removeEventListener("resize", scheduleUpdate);
10485
10567
  };
10486
10568
  }, [dockPlacement]);
10487
- const flushPendingDockStateRefresh = useCallback10(() => {
10569
+ const flushPendingDockStateRefresh = useCallback11(() => {
10488
10570
  if (!pendingDockStateRefreshRef.current) {
10489
10571
  return;
10490
10572
  }
@@ -10503,14 +10585,14 @@ function WorkbenchHostDock({
10503
10585
  setDockStateRevision((revision) => revision + 1);
10504
10586
  });
10505
10587
  }, [dockStateSource]);
10506
- const renderedDockEntries = useMemo6(
10588
+ const renderedDockEntries = useMemo7(
10507
10589
  () => dockEntries.map((entry) => {
10508
10590
  const dynamicState = dockStateSource?.getEntryState(entry.id);
10509
10591
  return dynamicState ? { ...entry, ...dynamicState } : entry;
10510
10592
  }),
10511
10593
  [dockEntries, dockStateRevision, dockStateSource]
10512
10594
  );
10513
- const resolvedEntries = useMemo6(
10595
+ const resolvedEntries = useMemo7(
10514
10596
  () => resolveWorkbenchDockEntries({
10515
10597
  dockEntries: renderedDockEntries,
10516
10598
  minimizedNodeIds: minimizedNodeIDs,
@@ -10518,7 +10600,7 @@ function WorkbenchHostDock({
10518
10600
  }),
10519
10601
  [context.nodes, minimizedNodeIDs, renderedDockEntries]
10520
10602
  );
10521
- const minimizedDockSlots = useMemo6(
10603
+ const minimizedDockSlots = useMemo7(
10522
10604
  () => resolveWorkbenchMinimizedDockSlots({
10523
10605
  nodeDefinitions,
10524
10606
  nodes: context.minimizedNodes
@@ -10526,7 +10608,7 @@ function WorkbenchHostDock({
10526
10608
  [context.minimizedNodes, nodeDefinitions]
10527
10609
  );
10528
10610
  const { promotedNodeId, stackDispatching } = useMinimizedDockStackPromotion(minimizedDockSlots);
10529
- const dockItems = useMemo6(
10611
+ const dockItems = useMemo7(
10530
10612
  () => createWorkbenchHostDockItems({
10531
10613
  minimizedDockSlots,
10532
10614
  resolvedEntries
@@ -10537,7 +10619,7 @@ function WorkbenchHostDock({
10537
10619
  dockItems,
10538
10620
  (nodeId) => context.genie.shouldAnimateMinimizedDockEnter(nodeId)
10539
10621
  );
10540
- const presentDockItemKeys = useMemo6(
10622
+ const presentDockItemKeys = useMemo7(
10541
10623
  () => presentDockItems.map((item) => item.key).join("\n"),
10542
10624
  [presentDockItems]
10543
10625
  );
@@ -10546,7 +10628,7 @@ function WorkbenchHostDock({
10546
10628
  elementRefs: wallpaperToneElementRefs,
10547
10629
  itemKeys: presentDockItemKeys
10548
10630
  });
10549
- const dockWidth = useMemo6(
10631
+ const dockWidth = useMemo7(
10550
10632
  () => resolveWorkbenchHostDockItemsWidth(dockItems),
10551
10633
  [dockItems]
10552
10634
  );
@@ -10576,7 +10658,7 @@ function WorkbenchHostDock({
10576
10658
  registerDockAnchorRef.current = (anchorKey, element) => {
10577
10659
  context.genie.registerDockAnchor(anchorKey, element);
10578
10660
  };
10579
- const registerWallpaperToneElement = useCallback10(
10661
+ const registerWallpaperToneElement = useCallback11(
10580
10662
  (key) => (element) => {
10581
10663
  if (element) {
10582
10664
  wallpaperToneElementRefs.current.set(key, element);
@@ -10586,7 +10668,7 @@ function WorkbenchHostDock({
10586
10668
  },
10587
10669
  []
10588
10670
  );
10589
- const setDockHoverPanelOpen = useCallback10((open) => {
10671
+ const setDockHoverPanelOpen = useCallback11((open) => {
10590
10672
  if (open) {
10591
10673
  dockMeasureRef.current?.setAttribute(
10592
10674
  "data-dock-hover-panel-open",
@@ -10602,7 +10684,7 @@ function WorkbenchHostDock({
10602
10684
  useEffect10(() => {
10603
10685
  activeLabelTooltipRef.current = activeLabelTooltip;
10604
10686
  }, [activeLabelTooltip]);
10605
- const closeLabelTooltipImmediate = useCallback10(
10687
+ const closeLabelTooltipImmediate = useCallback11(
10606
10688
  (targetKey) => {
10607
10689
  clearLabelTooltipOpenTimer();
10608
10690
  if (targetKey !== void 0 && activeLabelTooltipRef.current?.key !== targetKey) {
@@ -10616,7 +10698,7 @@ function WorkbenchHostDock({
10616
10698
  },
10617
10699
  [clearLabelTooltipOpenTimer]
10618
10700
  );
10619
- const closeHoverPanelImmediate = useCallback10(
10701
+ const closeHoverPanelImmediate = useCallback11(
10620
10702
  (entryId) => {
10621
10703
  clearHoverPanelOpenTimer();
10622
10704
  clearHoverPanelCloseTimer();
@@ -10639,7 +10721,7 @@ function WorkbenchHostDock({
10639
10721
  setDockHoverPanelOpen
10640
10722
  ]
10641
10723
  );
10642
- const scheduleHoverPanelClose = useCallback10(
10724
+ const scheduleHoverPanelClose = useCallback11(
10643
10725
  (entryId) => {
10644
10726
  clearHoverPanelOpenTimer();
10645
10727
  clearHoverPanelCloseTimer();
@@ -10656,7 +10738,7 @@ function WorkbenchHostDock({
10656
10738
  handleDockPointerLeave
10657
10739
  ]
10658
10740
  );
10659
- const showHoverPanel = useCallback10(
10741
+ const showHoverPanel = useCallback11(
10660
10742
  (entryId, anchorKey, anchorElement) => {
10661
10743
  const dockElement = dockMeasureRef.current;
10662
10744
  if (!dockElement) {
@@ -10682,7 +10764,7 @@ function WorkbenchHostDock({
10682
10764
  },
10683
10765
  [clearHoverPanelCloseTimer, pauseDockMagnification, setDockHoverPanelOpen]
10684
10766
  );
10685
- const scheduleHoverPanelAfterRest = useCallback10(
10767
+ const scheduleHoverPanelAfterRest = useCallback11(
10686
10768
  (entryId, anchorKey) => {
10687
10769
  hoverPanelRestTargetRef.current = { anchorKey, entryId };
10688
10770
  clearHoverPanelOpenTimer();
@@ -10703,7 +10785,7 @@ function WorkbenchHostDock({
10703
10785
  },
10704
10786
  [clearHoverPanelOpenTimer, showHoverPanel]
10705
10787
  );
10706
- const showLabelTooltip = useCallback10(
10788
+ const showLabelTooltip = useCallback11(
10707
10789
  (target, anchorKey, anchorElement) => {
10708
10790
  const dockElement = dockMeasureRef.current;
10709
10791
  if (!dockElement) {
@@ -10728,7 +10810,7 @@ function WorkbenchHostDock({
10728
10810
  },
10729
10811
  [clearLabelTooltipOpenTimer]
10730
10812
  );
10731
- const scheduleLabelTooltipAfterRest = useCallback10(
10813
+ const scheduleLabelTooltipAfterRest = useCallback11(
10732
10814
  (target, anchorKey) => {
10733
10815
  clearLabelTooltipOpenTimer();
10734
10816
  labelTooltipScheduledPointRef.current = null;
@@ -10744,7 +10826,7 @@ function WorkbenchHostDock({
10744
10826
  },
10745
10827
  [clearLabelTooltipOpenTimer, showLabelTooltip]
10746
10828
  );
10747
- const resolveHoverPanelTargetAtPoint = useCallback10(
10829
+ const resolveHoverPanelTargetAtPoint = useCallback11(
10748
10830
  (clientX, clientY) => {
10749
10831
  for (const [anchorKey, slotElement] of slotRefs.current) {
10750
10832
  const entryId = slotElement.dataset.dockHoverPanelEntryId;
@@ -10760,7 +10842,7 @@ function WorkbenchHostDock({
10760
10842
  },
10761
10843
  []
10762
10844
  );
10763
- const resolveLabelTooltipTargetAtPoint = useCallback10(
10845
+ const resolveLabelTooltipTargetAtPoint = useCallback11(
10764
10846
  (clientX, clientY) => {
10765
10847
  for (const [anchorKey, slotElement] of slotRefs.current) {
10766
10848
  if (slotElement.dataset.dockHoverPanelEntryId) {
@@ -10787,7 +10869,7 @@ function WorkbenchHostDock({
10787
10869
  },
10788
10870
  []
10789
10871
  );
10790
- const isPointerInsideActiveHoverPanelRegion = useCallback10(
10872
+ const isPointerInsideActiveHoverPanelRegion = useCallback11(
10791
10873
  (clientX, clientY) => {
10792
10874
  const activeHoverPanel2 = activeHoverPanelRef.current;
10793
10875
  if (!activeHoverPanel2) {
@@ -10819,7 +10901,7 @@ function WorkbenchHostDock({
10819
10901
  },
10820
10902
  []
10821
10903
  );
10822
- const scheduleHoverPanelAtPointAfterRest = useCallback10(
10904
+ const scheduleHoverPanelAtPointAfterRest = useCallback11(
10823
10905
  (clientX, clientY) => {
10824
10906
  const scheduledPoint = hoverPanelScheduledPointRef.current;
10825
10907
  if (hoverPanelOpenTimerRef.current !== null && scheduledPoint && Math.abs(clientX - scheduledPoint.clientX) <= dockHoverPanelPointerRestTolerancePx && Math.abs(clientY - scheduledPoint.clientY) <= dockHoverPanelPointerRestTolerancePx) {
@@ -10847,7 +10929,7 @@ function WorkbenchHostDock({
10847
10929
  },
10848
10930
  [clearHoverPanelOpenTimer, resolveHoverPanelTargetAtPoint, showHoverPanel]
10849
10931
  );
10850
- const scheduleLabelTooltipAtPointAfterRest = useCallback10(
10932
+ const scheduleLabelTooltipAtPointAfterRest = useCallback11(
10851
10933
  (clientX, clientY) => {
10852
10934
  if (activeLabelTooltipRef.current !== null) {
10853
10935
  return;
@@ -10877,7 +10959,7 @@ function WorkbenchHostDock({
10877
10959
  showLabelTooltip
10878
10960
  ]
10879
10961
  );
10880
- const beginDockIconInteraction = useCallback10(
10962
+ const beginDockIconInteraction = useCallback11(
10881
10963
  (anchorKey) => {
10882
10964
  hoverPanelRestTargetRef.current = null;
10883
10965
  clearHoverPanelOpenTimer();
@@ -10892,20 +10974,20 @@ function WorkbenchHostDock({
10892
10974
  triggerDockBounce
10893
10975
  ]
10894
10976
  );
10895
- const isDockEntryClickThrottled = useCallback10(
10977
+ const isDockEntryClickThrottled = useCallback11(
10896
10978
  (anchorKey) => {
10897
10979
  const throttledUntil = dockEntryClickThrottleUntilRef.current.get(anchorKey);
10898
10980
  return throttledUntil !== void 0 && Date.now() < throttledUntil;
10899
10981
  },
10900
10982
  []
10901
10983
  );
10902
- const claimDockEntryClick = useCallback10((anchorKey) => {
10984
+ const claimDockEntryClick = useCallback11((anchorKey) => {
10903
10985
  dockEntryClickThrottleUntilRef.current.set(
10904
10986
  anchorKey,
10905
10987
  Date.now() + DOCK_ENTRY_CLICK_THROTTLE_MS
10906
10988
  );
10907
10989
  }, []);
10908
- const beginDockMinimizedInteraction = useCallback10(
10990
+ const beginDockMinimizedInteraction = useCallback11(
10909
10991
  (anchorKey) => {
10910
10992
  hoverPanelRestTargetRef.current = null;
10911
10993
  clearHoverPanelOpenTimer();
@@ -10945,7 +11027,7 @@ function WorkbenchHostDock({
10945
11027
  pauseDockMagnification
10946
11028
  ]
10947
11029
  );
10948
- const runDockMinimizedLaunchAfterCollapse = useCallback10(
11030
+ const runDockMinimizedLaunchAfterCollapse = useCallback11(
10949
11031
  (intent, launch) => {
10950
11032
  const { anchorKey } = intent;
10951
11033
  beginDockMinimizedInteraction(anchorKey);
@@ -10959,14 +11041,14 @@ function WorkbenchHostDock({
10959
11041
  },
10960
11042
  [beginDockMinimizedInteraction, scheduleCollapsingMinimizedLaunchClear]
10961
11043
  );
10962
- const runDockMinimizedStackLaunch = useCallback10(
11044
+ const runDockMinimizedStackLaunch = useCallback11(
10963
11045
  (intent, launch) => {
10964
11046
  beginDockMinimizedInteraction();
10965
11047
  launch(intent);
10966
11048
  },
10967
11049
  [beginDockMinimizedInteraction]
10968
11050
  );
10969
- const handleDockPointerTravel = useCallback10(
11051
+ const handleDockPointerTravel = useCallback11(
10970
11052
  (clientX, clientY) => {
10971
11053
  if (activeHoverPanelRef.current !== null) {
10972
11054
  closeLabelTooltipImmediate();
@@ -11001,7 +11083,7 @@ function WorkbenchHostDock({
11001
11083
  scheduleLabelTooltipAtPointAfterRest
11002
11084
  ]
11003
11085
  );
11004
- const updateDockScrollState = useCallback10(() => {
11086
+ const updateDockScrollState = useCallback11(() => {
11005
11087
  const scrollElement = dockItemsRef.current;
11006
11088
  const viewportElement = dockMeasureRef.current;
11007
11089
  if (!scrollElement || !viewportElement) {
@@ -11073,13 +11155,29 @@ function WorkbenchHostDock({
11073
11155
  );
11074
11156
  useEffect10(() => {
11075
11157
  const shouldSubscribe = activePopup !== null || hasMinimizedPreviewCapture;
11076
- if (!shouldSubscribe || !externalStateSource?.subscribe) {
11158
+ if (!shouldSubscribe || !externalStateSource?.subscribeNodeState) {
11077
11159
  return void 0;
11078
11160
  }
11079
- return externalStateSource.subscribe(() => {
11080
- setExternalStateRevision((revision) => revision + 1);
11081
- });
11082
- }, [activePopup, externalStateSource, hasMinimizedPreviewCapture]);
11161
+ const nodes = activePopup ? context.nodes : context.minimizedNodes;
11162
+ const disposers = nodes.map(
11163
+ (node) => externalStateSource.subscribeNodeState?.(
11164
+ createWorkbenchHostExternalStateLookupInput({ node, workspaceId }),
11165
+ () => setExternalStateRevision((revision) => revision + 1)
11166
+ )
11167
+ );
11168
+ return () => {
11169
+ for (const dispose of disposers) {
11170
+ dispose?.();
11171
+ }
11172
+ };
11173
+ }, [
11174
+ activePopup,
11175
+ context.minimizedNodes,
11176
+ context.nodes,
11177
+ externalStateSource,
11178
+ hasMinimizedPreviewCapture,
11179
+ workspaceId
11180
+ ]);
11083
11181
  useEffect10(() => {
11084
11182
  const nextAttentionIds = /* @__PURE__ */ new Set();
11085
11183
  for (const entry of renderedDockEntries) {
@@ -11130,7 +11228,7 @@ function WorkbenchHostDock({
11130
11228
  },
11131
11229
  []
11132
11230
  );
11133
- const captureMinimizedNodePreview = useCallback10(
11231
+ const captureMinimizedNodePreview = useCallback11(
11134
11232
  async (node) => {
11135
11233
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11136
11234
  const capturePreview = minimizedDock?.kind === "snapshot" ? minimizedDock.capturePreview : void 0;
@@ -11161,7 +11259,7 @@ function WorkbenchHostDock({
11161
11259
  workspaceId
11162
11260
  ]
11163
11261
  );
11164
- const provideMinimizedNodePreview = useCallback10(
11262
+ const provideMinimizedNodePreview = useCallback11(
11165
11263
  (node) => {
11166
11264
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11167
11265
  if (minimizedDock?.kind !== "component") {
@@ -11190,7 +11288,7 @@ function WorkbenchHostDock({
11190
11288
  workspaceId
11191
11289
  ]
11192
11290
  );
11193
- const provideMinimizedNodePreviewForNode = useCallback10(
11291
+ const provideMinimizedNodePreviewForNode = useCallback11(
11194
11292
  (node) => {
11195
11293
  const minimizedDock = nodeDefinitions.get(node.data.typeId)?.window?.minimizedDock;
11196
11294
  return minimizedDock?.kind === "component" ? provideMinimizedNodePreview : void 0;
@@ -11226,7 +11324,7 @@ function WorkbenchHostDock({
11226
11324
  top: isVertical ? delta : 0
11227
11325
  });
11228
11326
  };
11229
- const registerDockSlot = useCallback10((anchorKey) => {
11327
+ const registerDockSlot = useCallback11((anchorKey) => {
11230
11328
  const existing = dockSlotRefCallbacksRef.current.get(anchorKey);
11231
11329
  if (existing) {
11232
11330
  return existing;
@@ -11247,7 +11345,7 @@ function WorkbenchHostDock({
11247
11345
  dockSlotRefCallbacksRef.current.set(anchorKey, callback);
11248
11346
  return callback;
11249
11347
  }, []);
11250
- const runDockEntryAction = useCallback10(
11348
+ const runDockEntryAction = useCallback11(
11251
11349
  (entryId, actionId) => {
11252
11350
  const actionKey = dockActionKey(entryId, actionId);
11253
11351
  if (pendingActionKeys.has(actionKey)) {
@@ -13105,7 +13203,7 @@ var DOCK_BOUNCE_MS = 600;
13105
13203
  var DOCK_ENTRY_CLICK_THROTTLE_MS = DOCK_BOUNCE_MS;
13106
13204
  function useDockBounce(slotRefs) {
13107
13205
  const timeoutsRef = useRef8(/* @__PURE__ */ new Map());
13108
- const clearDockBounce = useCallback10(
13206
+ const clearDockBounce = useCallback11(
13109
13207
  (anchorKey) => {
13110
13208
  const timeout = timeoutsRef.current.get(anchorKey);
13111
13209
  const slotElement = slotRefs.current.get(anchorKey);
@@ -13128,7 +13226,7 @@ function useDockBounce(slotRefs) {
13128
13226
  },
13129
13227
  [clearDockBounce]
13130
13228
  );
13131
- const triggerDockBounce = useCallback10(
13229
+ const triggerDockBounce = useCallback11(
13132
13230
  (anchorKey) => {
13133
13231
  const shouldRestartAnimation = clearDockBounce(anchorKey);
13134
13232
  const slotElement = slotRefs.current.get(anchorKey);
@@ -13230,11 +13328,12 @@ function createWorkbenchHostNodeHeaderWindowActions(context, input = {}) {
13230
13328
  // src/host/hostNodeContext.ts
13231
13329
  function createWorkbenchHostNodeBodyContext({
13232
13330
  context,
13331
+ externalState,
13233
13332
  externalStateSource,
13234
13333
  host,
13235
13334
  workspaceId
13236
13335
  }) {
13237
- const externalState = readWorkbenchHostExternalState({
13336
+ const resolvedExternalState = externalState ?? readWorkbenchHostExternalState({
13238
13337
  externalStateSource,
13239
13338
  node: context.node,
13240
13339
  workspaceId
@@ -13242,8 +13341,8 @@ function createWorkbenchHostNodeBodyContext({
13242
13341
  return {
13243
13342
  activation: context.node.data.activation ?? null,
13244
13343
  displayMode: context.node.displayMode,
13245
- externalNodeState: externalState.externalNodeState,
13246
- externalWorkspaceState: externalState.externalWorkspaceState,
13344
+ externalNodeState: resolvedExternalState.externalNodeState,
13345
+ externalWorkspaceState: resolvedExternalState.externalWorkspaceState,
13247
13346
  focus() {
13248
13347
  host.focusNode(context.node.id);
13249
13348
  },
@@ -13265,11 +13364,12 @@ function createWorkbenchHostNodeBodyContext({
13265
13364
  }
13266
13365
  function createWorkbenchHostNodeHeaderContext({
13267
13366
  context,
13367
+ externalState,
13268
13368
  externalStateSource,
13269
13369
  host,
13270
13370
  workspaceId
13271
13371
  }) {
13272
- const externalState = readWorkbenchHostExternalState({
13372
+ const resolvedExternalState = externalState ?? readWorkbenchHostExternalState({
13273
13373
  externalStateSource,
13274
13374
  node: context.node,
13275
13375
  workspaceId
@@ -13279,8 +13379,8 @@ function createWorkbenchHostNodeHeaderContext({
13279
13379
  defaultActions: context.defaultActions,
13280
13380
  displayMode: context.node.displayMode,
13281
13381
  dragHandleProps: context.dragHandleProps,
13282
- externalNodeState: externalState.externalNodeState,
13283
- externalWorkspaceState: externalState.externalWorkspaceState,
13382
+ externalNodeState: resolvedExternalState.externalNodeState,
13383
+ externalWorkspaceState: resolvedExternalState.externalWorkspaceState,
13284
13384
  instanceId: context.node.data.instanceId,
13285
13385
  instanceKey: context.node.data.instanceKey ?? null,
13286
13386
  isFocused: selectFocusedWorkbenchNode(host.getSnapshot())?.id === context.node.id,
@@ -13331,7 +13431,7 @@ function WorkbenchHostWindowActions({
13331
13431
  // src/host/useWorkbenchHostSurfaceRenderers.tsx
13332
13432
  import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
13333
13433
  function useWorkbenchHostSurfaceRenderers(input) {
13334
- const renderBottomChrome = useMemo7(() => {
13434
+ const renderBottomChrome = useMemo8(() => {
13335
13435
  const renderChrome = input.renderBottomChrome;
13336
13436
  return renderChrome ? () => /* @__PURE__ */ jsx14(
13337
13437
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -13359,7 +13459,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13359
13459
  input.renderBottomChrome,
13360
13460
  input.workspaceId
13361
13461
  ]);
13362
- const renderTopChrome = useMemo7(() => {
13462
+ const renderTopChrome = useMemo8(() => {
13363
13463
  const renderChrome = input.renderTopChrome;
13364
13464
  return renderChrome ? () => /* @__PURE__ */ jsx14(
13365
13465
  WorkbenchHostSurfaceRenderErrorBoundary,
@@ -13387,7 +13487,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13387
13487
  input.renderTopChrome,
13388
13488
  input.workspaceId
13389
13489
  ]);
13390
- const captureNodePreviewImage = useCallback11(
13490
+ const captureNodePreviewImage = useCallback12(
13391
13491
  async (node) => {
13392
13492
  const definition = input.nodeDefinitionByType.get(node.data.typeId);
13393
13493
  const minimizedDock = definition?.window?.minimizedDock;
@@ -13420,7 +13520,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13420
13520
  input.workspaceId
13421
13521
  ]
13422
13522
  );
13423
- const renderDock = useCallback11(
13523
+ const renderDock = useCallback12(
13424
13524
  (context) => /* @__PURE__ */ jsx14(
13425
13525
  WorkbenchHostSurfaceRenderErrorBoundary,
13426
13526
  {
@@ -13472,7 +13572,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13472
13572
  input.workspaceId
13473
13573
  ]
13474
13574
  );
13475
- const renderNode = useCallback11(
13575
+ const renderNode = useCallback12(
13476
13576
  (context) => {
13477
13577
  const definition = input.nodeDefinitionByType.get(
13478
13578
  context.node.data.typeId
@@ -13480,44 +13580,27 @@ function useWorkbenchHostSurfaceRenderers(input) {
13480
13580
  if (!definition) {
13481
13581
  return null;
13482
13582
  }
13483
- const bodyContext = createWorkbenchHostNodeBodyContext({
13484
- context,
13485
- definition,
13486
- externalStateSource: input.externalStateSource,
13487
- host: input.hostSession,
13488
- workspaceId: input.workspaceId
13489
- });
13490
13583
  return /* @__PURE__ */ jsx14(
13491
- WorkbenchHostNodeRenderErrorBoundary,
13584
+ WorkbenchHostNodeRenderer,
13492
13585
  {
13493
13586
  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
- )
13587
+ context,
13588
+ definition,
13589
+ externalStateSource: input.externalStateSource,
13590
+ host: input.hostSession,
13591
+ workspaceId: input.workspaceId
13508
13592
  }
13509
13593
  );
13510
13594
  },
13511
13595
  [
13512
13596
  input.debugDiagnostics,
13513
13597
  input.externalStateSource,
13514
- input.externalStateRevision,
13515
13598
  input.hostSession,
13516
13599
  input.nodeDefinitionByType,
13517
13600
  input.workspaceId
13518
13601
  ]
13519
13602
  );
13520
- const renderWindowActions = useCallback11(
13603
+ const renderWindowActions = useCallback12(
13521
13604
  (context) => /* @__PURE__ */ jsx14(
13522
13605
  WorkbenchHostWindowActions,
13523
13606
  {
@@ -13529,7 +13612,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13529
13612
  ),
13530
13613
  [input.hostI18n, input.hostSession, input.nodeDefinitionByType]
13531
13614
  );
13532
- const renderWindowHeader = useCallback11(
13615
+ const renderWindowHeader = useCallback12(
13533
13616
  (context) => {
13534
13617
  const definition = input.nodeDefinitionByType.get(
13535
13618
  context.node.data.typeId
@@ -13537,39 +13620,39 @@ function useWorkbenchHostSurfaceRenderers(input) {
13537
13620
  if (!definition?.renderHeader) {
13538
13621
  return null;
13539
13622
  }
13540
- return definition.renderHeader(
13541
- createWorkbenchHostNodeHeaderContext({
13623
+ return /* @__PURE__ */ jsx14(
13624
+ WorkbenchHostNodeHeaderRenderer,
13625
+ {
13542
13626
  context,
13543
13627
  definition,
13544
13628
  externalStateSource: input.externalStateSource,
13545
13629
  host: input.hostSession,
13546
13630
  workspaceId: input.workspaceId
13547
- })
13631
+ }
13548
13632
  );
13549
13633
  },
13550
13634
  [
13551
13635
  input.externalStateSource,
13552
- input.externalStateRevision,
13553
13636
  input.hostSession,
13554
13637
  input.nodeDefinitionByType,
13555
13638
  input.workspaceId
13556
13639
  ]
13557
13640
  );
13558
- const shouldKeepMinimizedNodeMounted = useCallback11(
13641
+ const shouldKeepMinimizedNodeMounted = useCallback12(
13559
13642
  (node) => {
13560
13643
  const capability = input.nodeDefinitionByType.get(node.data.typeId)?.window?.keepMountedWhenMinimized;
13561
13644
  return typeof capability === "function" ? capability(node) : capability === true;
13562
13645
  },
13563
13646
  [input.nodeDefinitionByType]
13564
13647
  );
13565
- const shouldCaptureNodePreviewImage = useCallback11(
13648
+ const shouldCaptureNodePreviewImage = useCallback12(
13566
13649
  (node) => {
13567
13650
  const minimizedDock = input.nodeDefinitionByType.get(node.data.typeId)?.window?.minimizedDock;
13568
13651
  return minimizedDock?.kind !== "component";
13569
13652
  },
13570
13653
  [input.nodeDefinitionByType]
13571
13654
  );
13572
- const renderNodeGeniePreview = useCallback11(
13655
+ const renderNodeGeniePreview = useCallback12(
13573
13656
  (node, {
13574
13657
  previewViewport
13575
13658
  }) => {
@@ -13603,7 +13686,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13603
13686
  input.workspaceId
13604
13687
  ]
13605
13688
  );
13606
- const resolveDockAnchorKey = useCallback11(
13689
+ const resolveDockAnchorKey = useCallback12(
13607
13690
  (node) => {
13608
13691
  if (node.isMinimized && isWorkbenchMinimizedDockEligibleNode({
13609
13692
  node,
@@ -13636,7 +13719,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
13636
13719
  },
13637
13720
  [input.dockEntries, input.hostSession, input.nodeDefinitionByType]
13638
13721
  );
13639
- const resolveDockPreviewCacheKey2 = useCallback11(
13722
+ const resolveDockPreviewCacheKey2 = useCallback12(
13640
13723
  (node) => ({
13641
13724
  instanceId: node.data.instanceId,
13642
13725
  instanceKey: node.data.instanceKey ?? null,
@@ -13646,16 +13729,16 @@ function useWorkbenchHostSurfaceRenderers(input) {
13646
13729
  }),
13647
13730
  [input.workspaceId]
13648
13731
  );
13649
- const windowChromeMode = useCallback11(
13732
+ const windowChromeMode = useCallback12(
13650
13733
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.renderHeader ? "custom-header" : "system",
13651
13734
  [input.nodeDefinitionByType]
13652
13735
  );
13653
- const resolveWindowZIndex = useCallback11(({ baseZIndex }) => baseZIndex, []);
13654
- const resolveWindowSurfaceLayer = useCallback11(
13736
+ const resolveWindowZIndex = useCallback12(({ baseZIndex }) => baseZIndex, []);
13737
+ const resolveWindowSurfaceLayer = useCallback12(
13655
13738
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.surfaceLayer ?? "default",
13656
13739
  [input.nodeDefinitionByType]
13657
13740
  );
13658
- const resolveFullscreenHeaderMode = useCallback11(
13741
+ const resolveFullscreenHeaderMode = useCallback12(
13659
13742
  ({ node }) => input.nodeDefinitionByType.get(node.data.typeId)?.window?.fullscreenHeaderMode,
13660
13743
  [input.nodeDefinitionByType]
13661
13744
  );
@@ -13678,6 +13761,72 @@ function useWorkbenchHostSurfaceRenderers(input) {
13678
13761
  windowChromeMode
13679
13762
  };
13680
13763
  }
13764
+ function WorkbenchHostNodeRenderer(input) {
13765
+ const externalState = useWorkbenchHostExternalState({
13766
+ externalStateSource: input.externalStateSource,
13767
+ node: input.context.node,
13768
+ workspaceId: input.workspaceId
13769
+ });
13770
+ const bodyContext = createWorkbenchHostNodeBodyContext({
13771
+ context: input.context,
13772
+ definition: input.definition,
13773
+ externalState,
13774
+ externalStateSource: input.externalStateSource,
13775
+ host: input.host,
13776
+ workspaceId: input.workspaceId
13777
+ });
13778
+ const resetKey = useMemo8(
13779
+ () => [
13780
+ input.context.node.id,
13781
+ input.context.node.data.typeId,
13782
+ externalState.externalNodeState,
13783
+ externalState.externalWorkspaceState
13784
+ ],
13785
+ [
13786
+ externalState.externalNodeState,
13787
+ externalState.externalWorkspaceState,
13788
+ input.context.node.data.typeId,
13789
+ input.context.node.id
13790
+ ]
13791
+ );
13792
+ return /* @__PURE__ */ jsx14(
13793
+ WorkbenchHostNodeRenderErrorBoundary,
13794
+ {
13795
+ debugDiagnostics: input.debugDiagnostics,
13796
+ node: input.context.node,
13797
+ onErrorChange: (hasError) => input.definition.onBodyRenderErrorChange?.({
13798
+ hasError,
13799
+ node: input.context.node
13800
+ }),
13801
+ resetKey,
13802
+ workspaceId: input.workspaceId,
13803
+ children: /* @__PURE__ */ jsx14(
13804
+ WorkbenchHostNodeBodyRenderer,
13805
+ {
13806
+ context: bodyContext,
13807
+ definition: input.definition
13808
+ }
13809
+ )
13810
+ }
13811
+ );
13812
+ }
13813
+ function WorkbenchHostNodeHeaderRenderer(input) {
13814
+ const externalState = useWorkbenchHostExternalState({
13815
+ externalStateSource: input.externalStateSource,
13816
+ node: input.context.node,
13817
+ workspaceId: input.workspaceId
13818
+ });
13819
+ return input.definition.renderHeader?.(
13820
+ createWorkbenchHostNodeHeaderContext({
13821
+ context: input.context,
13822
+ definition: input.definition,
13823
+ externalState,
13824
+ externalStateSource: input.externalStateSource,
13825
+ host: input.host,
13826
+ workspaceId: input.workspaceId
13827
+ })
13828
+ );
13829
+ }
13681
13830
  var WorkbenchHostSurfaceRenderErrorBoundary = class extends Component {
13682
13831
  state = {
13683
13832
  hasError: false
@@ -13730,7 +13879,7 @@ var WorkbenchHostNodeRenderErrorBoundary = class extends Component {
13730
13879
  return { hasError: true };
13731
13880
  }
13732
13881
  componentDidUpdate(previousProps) {
13733
- if (this.state.hasError && previousProps.resetKey !== this.props.resetKey) {
13882
+ if (this.state.hasError && !Object.is(previousProps.resetKey, this.props.resetKey)) {
13734
13883
  this.setState({ hasError: false });
13735
13884
  this.props.onErrorChange?.(false);
13736
13885
  }
@@ -13879,7 +14028,7 @@ function WorkbenchHost({
13879
14028
  windowManagement,
13880
14029
  workspaceId
13881
14030
  }) {
13882
- const hostRuntimeConfig = useMemo8(
14031
+ const hostRuntimeConfig = useMemo9(
13883
14032
  () => resolveWorkbenchHostRuntimeConfig({
13884
14033
  contributions,
13885
14034
  externalStateSource,
@@ -13895,7 +14044,7 @@ function WorkbenchHost({
13895
14044
  onNodeCloseRequest
13896
14045
  ]
13897
14046
  );
13898
- const hostDockEntries = useMemo8(
14047
+ const hostDockEntries = useMemo9(
13899
14048
  () => resolveWorkbenchHostDockEntries({
13900
14049
  contributions,
13901
14050
  dockEntryPresentationOverrides,
@@ -13910,7 +14059,6 @@ function WorkbenchHost({
13910
14059
  const missionControlEnabled = missionControlMode !== null || onMissionControlAdapterReady !== void 0;
13911
14060
  const {
13912
14061
  chromeContext,
13913
- externalStateRevision,
13914
14062
  hostI18n,
13915
14063
  hostSession,
13916
14064
  isHydrating,
@@ -13941,7 +14089,6 @@ function WorkbenchHost({
13941
14089
  dockStateSource,
13942
14090
  dockEntries: hostDockEntries,
13943
14091
  externalStateSource: hostRuntimeConfig.externalStateSource,
13944
- externalStateRevision,
13945
14092
  hostI18n,
13946
14093
  hostSession,
13947
14094
  nodeDefinitionByType,