@tutti-os/agent-gui 0.0.75 → 0.0.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1857,6 +1857,37 @@ aside.workspace-agents-status-panel
1857
1857
  white-space: nowrap;
1858
1858
  }
1859
1859
 
1860
+ /* Compact tool-call rows when nested inside a details block (e.g. task STEPS) */
1861
+ .workspace-agents-status-panel__detail-tool-body
1862
+ .workspace-agents-status-panel__detail-tool-row-title,
1863
+ .workspace-agents-status-panel__detail-tool-body
1864
+ .workspace-agents-status-panel__detail-tool-status,
1865
+ .workspace-agents-status-panel__detail-tool-body
1866
+ .workspace-agents-status-panel__detail-tool-diff-stats,
1867
+ .workspace-agents-status-panel__detail-tool-body
1868
+ .workspace-agents-status-panel__detail-tool-row-summary {
1869
+ font-size: 11px;
1870
+ }
1871
+
1872
+ .workspace-agents-status-panel__detail-tool-body
1873
+ .workspace-agents-status-panel__detail-tool-row-icon {
1874
+ width: 14px;
1875
+ height: 14px;
1876
+ }
1877
+
1878
+ .workspace-agents-status-panel__detail-tool-body
1879
+ .workspace-agents-status-panel__detail-tool-row-icon
1880
+ svg {
1881
+ width: 14px;
1882
+ height: 14px;
1883
+ }
1884
+
1885
+ /* Looser vertical rhythm for the nested step rows so they don't feel cramped */
1886
+ .workspace-agents-status-panel__detail-tool-body
1887
+ .workspace-agents-status-panel__detail-tool-stack {
1888
+ gap: 12px;
1889
+ }
1890
+
1860
1891
  .workspace-agents-status-panel__detail-tool-row-head
1861
1892
  .workspace-agents-status-panel__detail-tool-row-chevron {
1862
1893
  flex: 0 0 auto;
@@ -1915,7 +1946,7 @@ aside.workspace-agents-status-panel
1915
1946
  .workspace-agents-status-panel__detail-tool-body {
1916
1947
  display: flex;
1917
1948
  flex-direction: column;
1918
- gap: 10px;
1949
+ gap: 16px;
1919
1950
  box-sizing: border-box;
1920
1951
  width: 100%;
1921
1952
  min-width: 0;
@@ -6487,7 +6518,7 @@ button.agent-gui-node__conversation-section-toggle:hover
6487
6518
  box-sizing: border-box;
6488
6519
  width: 100%;
6489
6520
  min-width: 0;
6490
- padding-bottom: 24px;
6521
+ padding-bottom: 16px;
6491
6522
  will-change: transform;
6492
6523
  }
6493
6524
 
@@ -6497,7 +6528,7 @@ button.agent-gui-node__conversation-section-toggle:hover
6497
6528
  .agent-gui-transcript-virtual-item
6498
6529
  > [data-testid="agent-transcript-turn-divider"]
6499
6530
  + .agent-gui-transcript-row {
6500
- margin-top: 24px;
6531
+ margin-top: 16px;
6501
6532
  }
6502
6533
 
6503
6534
  .agent-gui-transcript-row[data-agent-transcript-row-enter="true"] {
@@ -8953,6 +8984,30 @@ html[data-theme="light"] [data-message-center-item-id].agent-gui-edge-glow {
8953
8984
  box-shadow: 0 0 0 1.5px var(--tutti-purple);
8954
8985
  }
8955
8986
 
8987
+ /* Clickable agent switchers: reset native button chrome, keep the same box, and
8988
+ give a hover/focus affordance so the strip reads as interactive. */
8989
+ button.agent-gui-node__provider-rail-launchpad-item {
8990
+ padding: 0;
8991
+ border: 0;
8992
+ cursor: pointer;
8993
+ appearance: none;
8994
+ -webkit-appearance: none;
8995
+ }
8996
+
8997
+ .agent-gui-node__empty-hero-launchpad-icon
8998
+ button.agent-gui-node__provider-rail-launchpad-item:hover:not(
8999
+ [data-provider-active="true"]
9000
+ ) {
9001
+ opacity: 1 !important;
9002
+ transform: scale(1.08);
9003
+ }
9004
+
9005
+ .agent-gui-node__empty-hero-launchpad-icon
9006
+ button.agent-gui-node__provider-rail-launchpad-item:focus-visible {
9007
+ outline: none;
9008
+ box-shadow: 0 0 0 1.5px var(--tutti-purple);
9009
+ }
9010
+
8956
9011
  .agent-gui-node__provider-rail-tile[data-loading="true"]
8957
9012
  .agent-gui-node__provider-rail-avatar {
8958
9013
  background: linear-gradient(
package/dist/index.js CHANGED
@@ -15159,8 +15159,6 @@ function useAgentGUINodeController({
15159
15159
  const activeConversationCreatePending = Boolean(activeConversationId) && isCreatingConversation && startingConversationIdRef.current === activeConversationId;
15160
15160
  const canQueueWhileBusy = Boolean(activeConversationId) && (activeConversationCreatePending || activeConversationBusy || isSubmitting || Boolean(activeSessionState?.pendingInteractive));
15161
15161
  useEffect4(() => {
15162
- const firstVersion = minFiniteMessageVersion(activeMessages);
15163
- const lastVersion = maxFiniteMessageVersion(activeMessages);
15164
15162
  const diagnosticKey = [
15165
15163
  activeConversationId ?? "",
15166
15164
  activeConversation?.status ?? "",
@@ -15182,10 +15180,9 @@ function useAgentGUINodeController({
15182
15180
  activeSubmitBlocked ? "submit-blocked" : "submit-open",
15183
15181
  pendingApproval?.requestId ?? "",
15184
15182
  promptRequestId(pendingInteractivePrompt) ?? "",
15185
- conversation?.rows.length ?? "",
15186
- conversation?.sourceDetail.turns.length ?? "",
15187
- firstVersion ?? "",
15188
- lastVersion ?? "",
15183
+ conversation?.activity.status ?? "",
15184
+ conversation?.pendingApproval?.requestId ?? "",
15185
+ promptRequestId(conversation?.pendingInteractivePrompt ?? null) ?? "",
15189
15186
  isCreatingConversation ? "creating" : "",
15190
15187
  isLoadingMessages ? "loading-messages" : "",
15191
15188
  isSubmitting ? "submitting" : "",
@@ -15224,7 +15221,6 @@ function useAgentGUINodeController({
15224
15221
  activeConversationId,
15225
15222
  activeHasPendingSubmittedTurn,
15226
15223
  activeLiveState,
15227
- activeMessages,
15228
15224
  activeRuntimeSession,
15229
15225
  activeSessionState,
15230
15226
  activeSubmitBlocked,
@@ -25739,6 +25735,7 @@ var AGENT_GUI_TOP_HISTORY_PREFETCH_THRESHOLD_PX = 240;
25739
25735
  var AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX = 1;
25740
25736
  var AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
25741
25737
  var AGENT_GUI_CONVERSATION_RAIL_LOADING_SKELETON_DELAY_MS = 300;
25738
+ var AGENT_GUI_CONVERSATION_RAIL_VISIBILITY_EPSILON_PX = 1;
25742
25739
  var AGENT_GUI_CONVERSATION_RAIL_PROJECTION_PROVIDER = "codex";
25743
25740
  var AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE = {
25744
25741
  width: "100%",
@@ -25750,6 +25747,18 @@ var AGENT_GUI_TIMELINE_SCROLL_AREA_CONTENT_STYLE = {
25750
25747
  var EMPTY_WORKSPACE_APP_ICONS3 = [];
25751
25748
  var AGENT_GUI_CONFIRMATION_DIALOG_CLASS_NAME = "nodrag tsh-desktop-no-drag [-webkit-app-region:no-drag]";
25752
25749
  var AGENT_GUI_CONFIRMATION_DIALOG_OVERLAY_CLASS_NAME = "nodrag tsh-desktop-no-drag [-webkit-app-region:no-drag]";
25750
+ function isElementFullyVisibleWithin(element, viewport) {
25751
+ const elementRect = element.getBoundingClientRect();
25752
+ const viewportRect = viewport.getBoundingClientRect();
25753
+ return elementRect.top >= viewportRect.top - AGENT_GUI_CONVERSATION_RAIL_VISIBILITY_EPSILON_PX && elementRect.bottom <= viewportRect.bottom + AGENT_GUI_CONVERSATION_RAIL_VISIBILITY_EPSILON_PX;
25754
+ }
25755
+ function setBooleanStateIfChanged(stateRef, setState, nextState) {
25756
+ if (stateRef.current === nextState) {
25757
+ return;
25758
+ }
25759
+ stateRef.current = nextState;
25760
+ setState(nextState);
25761
+ }
25753
25762
  function resolveAgentGUIHeroIconUrl(provider) {
25754
25763
  const normalizedProvider = normalizeManagedAgentProvider(provider);
25755
25764
  return MANAGED_AGENT_ICON_URLS[normalizedProvider] ?? MANAGED_AGENT_ICON_FALLBACK_URL;
@@ -26977,6 +26986,8 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
26977
26986
  const pendingRestoreScrollRef = useRef12(null);
26978
26987
  const [isTimelineScrolledToTop, setIsTimelineScrolledToTop] = useState14(true);
26979
26988
  const [isTimelineScrolledToBottom, setIsTimelineScrolledToBottom] = useState14(true);
26989
+ const isTimelineScrolledToTopRef = useRef12(true);
26990
+ const isTimelineScrolledToBottomRef = useRef12(true);
26980
26991
  const [
26981
26992
  bottomDockDismissedPromptRequestId,
26982
26993
  setBottomDockDismissedPromptRequestId
@@ -27783,8 +27794,16 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27783
27794
  timelineScrollAnchorRef.current = null;
27784
27795
  pendingPrependScrollAnchorRef.current = null;
27785
27796
  submittedPromptScrollConversationRef.current = null;
27786
- setIsTimelineScrolledToTop(true);
27787
- setIsTimelineScrolledToBottom(true);
27797
+ setBooleanStateIfChanged(
27798
+ isTimelineScrolledToTopRef,
27799
+ setIsTimelineScrolledToTop,
27800
+ true
27801
+ );
27802
+ setBooleanStateIfChanged(
27803
+ isTimelineScrolledToBottomRef,
27804
+ setIsTimelineScrolledToBottom,
27805
+ true
27806
+ );
27788
27807
  return;
27789
27808
  }
27790
27809
  const maxScrollTop = Math.max(
@@ -27859,10 +27878,14 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27859
27878
  scrollTop: nextScrollTop,
27860
27879
  clientHeight: timeline.clientHeight
27861
27880
  };
27862
- setIsTimelineScrolledToTop(
27881
+ setBooleanStateIfChanged(
27882
+ isTimelineScrolledToTopRef,
27883
+ setIsTimelineScrolledToTop,
27863
27884
  nextScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
27864
27885
  );
27865
- setIsTimelineScrolledToBottom(
27886
+ setBooleanStateIfChanged(
27887
+ isTimelineScrolledToBottomRef,
27888
+ setIsTimelineScrolledToBottom,
27866
27889
  maxScrollTop - nextScrollTop <= AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX
27867
27890
  );
27868
27891
  }, [
@@ -27930,10 +27953,16 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27930
27953
  scrollTop: maxScrollTop,
27931
27954
  clientHeight: timeline.clientHeight
27932
27955
  };
27933
- setIsTimelineScrolledToTop(
27956
+ setBooleanStateIfChanged(
27957
+ isTimelineScrolledToTopRef,
27958
+ setIsTimelineScrolledToTop,
27934
27959
  maxScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
27935
27960
  );
27936
- setIsTimelineScrolledToBottom(true);
27961
+ setBooleanStateIfChanged(
27962
+ isTimelineScrolledToBottomRef,
27963
+ setIsTimelineScrolledToBottom,
27964
+ true
27965
+ );
27937
27966
  });
27938
27967
  };
27939
27968
  syncBottomDockSpace();
@@ -27982,10 +28011,16 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
27982
28011
  clientHeight: timeline.clientHeight
27983
28012
  };
27984
28013
  const atBottom = timeline.scrollHeight - scrollTop - timeline.clientHeight <= AGENT_GUI_STICK_TO_BOTTOM_THRESHOLD_PX;
27985
- setIsTimelineScrolledToTop(
28014
+ setBooleanStateIfChanged(
28015
+ isTimelineScrolledToTopRef,
28016
+ setIsTimelineScrolledToTop,
27986
28017
  scrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
27987
28018
  );
27988
- setIsTimelineScrolledToBottom(atBottom);
28019
+ setBooleanStateIfChanged(
28020
+ isTimelineScrolledToBottomRef,
28021
+ setIsTimelineScrolledToBottom,
28022
+ atBottom
28023
+ );
27989
28024
  if (pendingRestoreScrollRef.current?.conversationId !== activeConversationId) {
27990
28025
  timelineScrollPositionsRef.current.set(activeConversationId, {
27991
28026
  scrollTop,
@@ -28001,9 +28036,17 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
28001
28036
  actions.loadOlderConversationMessages();
28002
28037
  }
28003
28038
  };
28004
- captureScrollAnchor();
28039
+ let initialCaptureFrameId = window.requestAnimationFrame(
28040
+ () => {
28041
+ initialCaptureFrameId = null;
28042
+ captureScrollAnchor();
28043
+ }
28044
+ );
28005
28045
  timeline.addEventListener("scroll", captureScrollAnchor, { passive: true });
28006
28046
  return () => {
28047
+ if (initialCaptureFrameId !== null) {
28048
+ window.cancelAnimationFrame(initialCaptureFrameId);
28049
+ }
28007
28050
  timeline.removeEventListener("scroll", captureScrollAnchor);
28008
28051
  };
28009
28052
  }, [
@@ -28029,10 +28072,16 @@ var AgentGUIDetailPane = memo2(function AgentGUIDetailPane2({
28029
28072
  scrollTop: maxScrollTop,
28030
28073
  clientHeight: timeline.clientHeight
28031
28074
  };
28032
- setIsTimelineScrolledToTop(
28075
+ setBooleanStateIfChanged(
28076
+ isTimelineScrolledToTopRef,
28077
+ setIsTimelineScrolledToTop,
28033
28078
  maxScrollTop <= AGENT_GUI_TOP_MASK_SCROLL_EPSILON_PX
28034
28079
  );
28035
- setIsTimelineScrolledToBottom(true);
28080
+ setBooleanStateIfChanged(
28081
+ isTimelineScrolledToBottomRef,
28082
+ setIsTimelineScrolledToBottom,
28083
+ true
28084
+ );
28036
28085
  }, [viewModel.activeConversationId]);
28037
28086
  return /* @__PURE__ */ jsxs21("main", { className: AgentGUINode_styles_default.detail, children: [
28038
28087
  /* @__PURE__ */ jsx34(
@@ -28316,7 +28365,10 @@ var AgentGUIEmptyHeroPane = memo2(function AgentGUIEmptyHeroPane2({
28316
28365
  {
28317
28366
  activeProvider: provider,
28318
28367
  className: AgentGUINode_styles_default.emptyHeroLaunchpadIcon,
28319
- icons: heroIconPresentations
28368
+ icons: heroIconPresentations,
28369
+ providerTargets,
28370
+ onProviderSelect,
28371
+ providerSelectLabel
28320
28372
  },
28321
28373
  heroIconAnimationKey
28322
28374
  ) : /* @__PURE__ */ jsx34(
@@ -28403,7 +28455,10 @@ var AgentGUIProviderReadinessGatePane = memo2(
28403
28455
  {
28404
28456
  activeProvider: provider,
28405
28457
  className: AgentGUINode_styles_default.emptyHeroLaunchpadIcon,
28406
- icons: launchpadIconPresentations
28458
+ icons: launchpadIconPresentations,
28459
+ providerTargets,
28460
+ onProviderSelect,
28461
+ providerSelectLabel
28407
28462
  }
28408
28463
  ) : /* @__PURE__ */ jsx34(
28409
28464
  "img",
@@ -28529,18 +28584,25 @@ function providerGateAction(status) {
28529
28584
  function AgentGUIAllProviderGridIcon({
28530
28585
  activeProvider,
28531
28586
  className,
28532
- icons
28587
+ icons,
28588
+ providerTargets,
28589
+ onProviderSelect,
28590
+ providerSelectLabel
28533
28591
  }) {
28592
+ const interactive = onProviderSelect != null && (providerTargets?.length ?? 0) > 0;
28534
28593
  return /* @__PURE__ */ jsx34(
28535
28594
  "span",
28536
28595
  {
28537
- "aria-hidden": "true",
28596
+ "aria-hidden": interactive ? void 0 : "true",
28538
28597
  className: [AgentGUINode_styles_default.providerRailAvatar, className].filter(Boolean).join(" "),
28539
28598
  children: /* @__PURE__ */ jsx34(
28540
28599
  AgentGUILaunchpadIconGrid,
28541
28600
  {
28542
28601
  activeProvider,
28543
- icons
28602
+ icons,
28603
+ providerTargets,
28604
+ onProviderSelect,
28605
+ providerSelectLabel
28544
28606
  }
28545
28607
  )
28546
28608
  }
@@ -28560,36 +28622,82 @@ function AgentGUIUnifiedProviderIcon({
28560
28622
  }
28561
28623
  ) });
28562
28624
  }
28563
- function agentGUIHeroStripOpacity(distance) {
28564
- if (distance <= 0) {
28565
- return 1;
28566
- }
28567
- return Math.max(0.15, 1 - distance * 0.4);
28625
+ var AGENT_GUI_HERO_STRIP_INACTIVE_OPACITY = 0.4;
28626
+ function agentGUIHeroStripOpacity(isActive) {
28627
+ return isActive ? 1 : AGENT_GUI_HERO_STRIP_INACTIVE_OPACITY;
28628
+ }
28629
+ function agentGUILaunchpadProviderTarget(providerTargets, provider) {
28630
+ const normalized = normalizeManagedAgentProvider(provider);
28631
+ return providerTargets.find(
28632
+ (target) => target.disabled !== true && normalizeManagedAgentProvider(target.provider) === normalized
28633
+ ) ?? null;
28568
28634
  }
28569
28635
  function AgentGUILaunchpadIconGrid({
28570
28636
  activeProvider,
28571
- icons
28637
+ icons,
28638
+ providerTargets,
28639
+ onProviderSelect,
28640
+ providerSelectLabel
28572
28641
  }) {
28573
28642
  const normalizedActiveProvider = activeProvider ? normalizeManagedAgentProvider(activeProvider) : null;
28574
28643
  const activeIndex = normalizedActiveProvider === null ? -1 : icons.findIndex(
28575
28644
  (icon) => normalizeManagedAgentProvider(icon.provider) === normalizedActiveProvider
28576
28645
  );
28577
- const renderItem = (icon, distance, isActive) => /* @__PURE__ */ jsx34(
28646
+ const interactive = onProviderSelect != null && (providerTargets?.length ?? 0) > 0;
28647
+ const renderItem = (icon, isActive) => {
28648
+ const key = `${icon.provider}:${icon.iconUrl}`;
28649
+ const style = { opacity: agentGUIHeroStripOpacity(isActive) };
28650
+ const dataActive = normalizedActiveProvider === null ? void 0 : isActive;
28651
+ const target = interactive ? agentGUILaunchpadProviderTarget(providerTargets ?? [], icon.provider) : null;
28652
+ if (target && onProviderSelect) {
28653
+ const label = providerSelectLabel ? `${providerSelectLabel}: ${target.label}` : target.label;
28654
+ return /* @__PURE__ */ jsx34(
28655
+ "button",
28656
+ {
28657
+ type: "button",
28658
+ className: AgentGUINode_styles_default.providerRailLaunchpadItem,
28659
+ "data-provider-active": dataActive,
28660
+ "aria-label": label,
28661
+ "aria-pressed": isActive,
28662
+ title: target.label,
28663
+ style,
28664
+ onClick: () => onProviderSelect({
28665
+ provider: target.provider,
28666
+ providerTargetId: target.targetId
28667
+ }),
28668
+ children: /* @__PURE__ */ jsx34(
28669
+ AgentGUIProviderIconVisual,
28670
+ {
28671
+ ariaHidden: true,
28672
+ imageClassName: "",
28673
+ icon
28674
+ }
28675
+ )
28676
+ },
28677
+ key
28678
+ );
28679
+ }
28680
+ return /* @__PURE__ */ jsx34(
28681
+ "span",
28682
+ {
28683
+ className: AgentGUINode_styles_default.providerRailLaunchpadItem,
28684
+ "data-provider-active": dataActive,
28685
+ style,
28686
+ children: /* @__PURE__ */ jsx34(AgentGUIProviderIconVisual, { imageClassName: "", icon })
28687
+ },
28688
+ key
28689
+ );
28690
+ };
28691
+ return /* @__PURE__ */ jsx34(
28578
28692
  "span",
28579
28693
  {
28580
- className: AgentGUINode_styles_default.providerRailLaunchpadItem,
28581
- "data-provider-active": normalizedActiveProvider === null ? void 0 : isActive,
28582
- style: { opacity: agentGUIHeroStripOpacity(distance) },
28583
- children: /* @__PURE__ */ jsx34(AgentGUIProviderIconVisual, { imageClassName: "", icon })
28584
- },
28585
- `${icon.provider}:${icon.iconUrl}`
28694
+ "aria-hidden": interactive ? void 0 : "true",
28695
+ className: AgentGUINode_styles_default.providerRailLaunchpadIcon,
28696
+ children: icons.map(
28697
+ (icon, index) => renderItem(icon, activeIndex < 0 ? true : index === activeIndex)
28698
+ )
28699
+ }
28586
28700
  );
28587
- if (activeIndex < 0) {
28588
- return /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: AgentGUINode_styles_default.providerRailLaunchpadIcon, children: icons.map((icon) => renderItem(icon, 0, false)) });
28589
- }
28590
- return /* @__PURE__ */ jsx34("span", { "aria-hidden": "true", className: AgentGUINode_styles_default.providerRailLaunchpadIcon, children: icons.map(
28591
- (icon, index) => renderItem(icon, Math.abs(index - activeIndex), index === activeIndex)
28592
- ) });
28593
28701
  }
28594
28702
  function AgentGUIProviderIconVisual({
28595
28703
  ariaHidden = false,
@@ -30579,6 +30687,7 @@ var AgentGUIConversationRailPane = memo2(
30579
30687
  /* @__PURE__ */ new Map()
30580
30688
  );
30581
30689
  const activeConversationScrollCompletedRef = useRef12(null);
30690
+ const activeConversationScrollFrameRef = useRef12(null);
30582
30691
  const previousActiveConversationIdRef = useRef12(null);
30583
30692
  const groupedConversationsRef = useRef12(null);
30584
30693
  const {
@@ -30700,6 +30809,10 @@ var AgentGUIConversationRailPane = memo2(
30700
30809
  if (!activeId) {
30701
30810
  previousActiveConversationIdRef.current = null;
30702
30811
  activeConversationScrollCompletedRef.current = null;
30812
+ if (activeConversationScrollFrameRef.current !== null) {
30813
+ window.cancelAnimationFrame(activeConversationScrollFrameRef.current);
30814
+ activeConversationScrollFrameRef.current = null;
30815
+ }
30703
30816
  return;
30704
30817
  }
30705
30818
  if (previousActiveConversationIdRef.current !== activeId) {
@@ -30713,8 +30826,35 @@ var AgentGUIConversationRailPane = memo2(
30713
30826
  if (!activeElement) {
30714
30827
  return;
30715
30828
  }
30716
- activeElement.scrollIntoView({ block: "nearest" });
30717
- activeConversationScrollCompletedRef.current = activeId;
30829
+ const viewport = conversationListRef.current ?? railElementRef.current;
30830
+ if (!viewport || isElementFullyVisibleWithin(activeElement, viewport)) {
30831
+ activeConversationScrollCompletedRef.current = activeId;
30832
+ return;
30833
+ }
30834
+ const animationFrameId = window.requestAnimationFrame(() => {
30835
+ activeConversationScrollFrameRef.current = null;
30836
+ if (previousActiveConversationIdRef.current !== activeId) {
30837
+ return;
30838
+ }
30839
+ const nextActiveElement = conversationItemElementsRef.current.get(activeId);
30840
+ if (!nextActiveElement) {
30841
+ return;
30842
+ }
30843
+ const nextViewport = conversationListRef.current ?? railElementRef.current;
30844
+ if (nextViewport && isElementFullyVisibleWithin(nextActiveElement, nextViewport)) {
30845
+ activeConversationScrollCompletedRef.current = activeId;
30846
+ return;
30847
+ }
30848
+ nextActiveElement.scrollIntoView({ block: "nearest" });
30849
+ activeConversationScrollCompletedRef.current = activeId;
30850
+ });
30851
+ activeConversationScrollFrameRef.current = animationFrameId;
30852
+ return () => {
30853
+ if (activeConversationScrollFrameRef.current === animationFrameId) {
30854
+ window.cancelAnimationFrame(animationFrameId);
30855
+ activeConversationScrollFrameRef.current = null;
30856
+ }
30857
+ };
30718
30858
  }, [activeConversationId, groupedConversationIdentityKey]);
30719
30859
  return /* @__PURE__ */ jsxs21(
30720
30860
  "aside",