@assistant-ui/react 0.15.31 → 0.15.32

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.
Files changed (211) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -2
  2. package/dist/adapters/OpenAIRealtimeVoiceAdapter.js +1 -2
  3. package/dist/assistant-transport.js +1 -2
  4. package/dist/cloud-renderer/CloudRendererHost.js +1 -2
  5. package/dist/context/ReadonlyStore.js +1 -2
  6. package/dist/context/providers/MessageProvider.js +1 -2
  7. package/dist/context/providers/ThreadViewportProvider.js +1 -2
  8. package/dist/context/react/ThreadViewportContext.js +1 -2
  9. package/dist/context/react/utils/createContextHook.js +1 -2
  10. package/dist/context/react/utils/createContextStoreHook.js +1 -2
  11. package/dist/context/stores/ThreadViewport.js +1 -2
  12. package/dist/devtools/DevToolsHooks.js +1 -2
  13. package/dist/hooks/useMessageQuote.js +1 -2
  14. package/dist/hooks/useMessageTiming.js +1 -2
  15. package/dist/hooks/useToolCallElapsed.js +1 -2
  16. package/dist/internal.js +1 -2
  17. package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -2
  18. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  19. package/dist/mcp-apps/McpAppRenderer.js +3 -3
  20. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  21. package/dist/mcp-apps/McpAppsRemoteHost.js +1 -2
  22. package/dist/mcp-apps/app-frame.js +1 -2
  23. package/dist/mcp-apps/bridge.js +1 -2
  24. package/dist/mcp-apps/csp.js +1 -2
  25. package/dist/mcp-apps/types.js +1 -2
  26. package/dist/mcp-apps/utils.js +1 -2
  27. package/dist/model-context/frame/useAssistantFrameHost.js +1 -2
  28. package/dist/model-context/makeAssistantVisible.js +1 -2
  29. package/dist/primitives/actionBar/ActionBarCopy.js +1 -2
  30. package/dist/primitives/actionBar/ActionBarEdit.js +1 -2
  31. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -2
  32. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -2
  33. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -2
  34. package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -2
  35. package/dist/primitives/actionBar/ActionBarReload.js +1 -2
  36. package/dist/primitives/actionBar/ActionBarRoot.js +1 -2
  37. package/dist/primitives/actionBar/ActionBarSpeak.js +1 -2
  38. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -2
  39. package/dist/primitives/actionBar/useActionBarFloatStatus.js +1 -2
  40. package/dist/primitives/actionBar.js +1 -2
  41. package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -2
  42. package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -2
  43. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -2
  44. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -2
  45. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -2
  46. package/dist/primitives/actionBarMore/scope.js +1 -2
  47. package/dist/primitives/actionBarMore.js +1 -2
  48. package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -2
  49. package/dist/primitives/assistantModal/AssistantModalContent.js +1 -2
  50. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -2
  51. package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -2
  52. package/dist/primitives/assistantModal/popoverRenderPrimitives.js +1 -2
  53. package/dist/primitives/assistantModal/scope.js +1 -2
  54. package/dist/primitives/assistantModal.js +1 -2
  55. package/dist/primitives/attachment/AttachmentName.js +1 -2
  56. package/dist/primitives/attachment/AttachmentRemove.js +1 -2
  57. package/dist/primitives/attachment/AttachmentRoot.js +1 -2
  58. package/dist/primitives/attachment/AttachmentThumb.js +1 -2
  59. package/dist/primitives/attachment.js +1 -2
  60. package/dist/primitives/branchPicker/BranchPickerCount.js +1 -2
  61. package/dist/primitives/branchPicker/BranchPickerNext.js +1 -2
  62. package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -2
  63. package/dist/primitives/branchPicker/BranchPickerPrevious.js +1 -2
  64. package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -2
  65. package/dist/primitives/branchPicker.js +1 -2
  66. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +5 -4
  67. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  68. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +57 -20
  69. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  70. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -2
  71. package/dist/primitives/chainOfThought.js +1 -2
  72. package/dist/primitives/composer/ComposerAddAttachment.js +1 -2
  73. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -2
  74. package/dist/primitives/composer/ComposerCancel.js +1 -2
  75. package/dist/primitives/composer/ComposerCompactContext.js +1 -2
  76. package/dist/primitives/composer/ComposerDictate.js +1 -2
  77. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -2
  78. package/dist/primitives/composer/ComposerInput.js +1 -2
  79. package/dist/primitives/composer/ComposerInputPluginContext.js +1 -2
  80. package/dist/primitives/composer/ComposerQuote.js +1 -2
  81. package/dist/primitives/composer/ComposerResume.js +1 -2
  82. package/dist/primitives/composer/ComposerRoot.js +1 -2
  83. package/dist/primitives/composer/ComposerSend.js +1 -2
  84. package/dist/primitives/composer/ComposerStopDictation.js +1 -2
  85. package/dist/primitives/composer/composerInputSelector.js +1 -2
  86. package/dist/primitives/composer/trigger/TriggerPopover.js +1 -2
  87. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -2
  88. package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -2
  89. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -2
  90. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -2
  91. package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -2
  92. package/dist/primitives/composer/trigger/TriggerPopoverResource.js +1 -2
  93. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -2
  94. package/dist/primitives/composer/trigger/detectTrigger.js +1 -2
  95. package/dist/primitives/composer/trigger/index.js +1 -2
  96. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js +1 -2
  97. package/dist/primitives/composer/trigger/triggerDetectionResource.js +1 -2
  98. package/dist/primitives/composer/trigger/triggerKeyboardResource.js +1 -2
  99. package/dist/primitives/composer/trigger/triggerNavigationResource.js +1 -2
  100. package/dist/primitives/composer/trigger/triggerSelectionResource.js +1 -2
  101. package/dist/primitives/composer/useComposerCancelWithFocus.js +1 -2
  102. package/dist/primitives/composer/useComposerInputState.js +1 -2
  103. package/dist/primitives/composer.js +1 -2
  104. package/dist/primitives/dropdownMenuRenderPrimitives.js +1 -2
  105. package/dist/primitives/error/ErrorMessage.js +1 -2
  106. package/dist/primitives/error/ErrorRoot.js +1 -2
  107. package/dist/primitives/error.js +1 -2
  108. package/dist/primitives/message/MessageError.js +1 -2
  109. package/dist/primitives/message/MessageIf.js +1 -2
  110. package/dist/primitives/message/MessageParts.js +1 -2
  111. package/dist/primitives/message/MessagePartsGrouped.js +1 -2
  112. package/dist/primitives/message/MessageRoot.js +1 -2
  113. package/dist/primitives/message.js +1 -2
  114. package/dist/primitives/messagePart/MessagePartImage.js +1 -2
  115. package/dist/primitives/messagePart/MessagePartText.js +1 -2
  116. package/dist/primitives/messagePart/useMessagePartData.js +1 -2
  117. package/dist/primitives/messagePart/useMessagePartFile.js +1 -2
  118. package/dist/primitives/messagePart/useMessagePartImage.js +1 -2
  119. package/dist/primitives/messagePart/useMessagePartReasoning.js +1 -2
  120. package/dist/primitives/messagePart/useMessagePartSource.js +1 -2
  121. package/dist/primitives/messagePart/useMessagePartText.js +1 -2
  122. package/dist/primitives/messagePart.js +1 -2
  123. package/dist/primitives/queueItem/QueueItemRemove.js +1 -2
  124. package/dist/primitives/queueItem/QueueItemSteer.js +1 -2
  125. package/dist/primitives/queueItem/QueueItemText.js +1 -2
  126. package/dist/primitives/queueItem.js +1 -2
  127. package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
  128. package/dist/primitives/reasoning/useScrollLock.js +41 -25
  129. package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
  130. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -2
  131. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -2
  132. package/dist/primitives/selectionToolbar.js +1 -2
  133. package/dist/primitives/suggestion/SuggestionDescription.js +1 -2
  134. package/dist/primitives/suggestion/SuggestionTitle.js +1 -2
  135. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -2
  136. package/dist/primitives/suggestion.js +1 -2
  137. package/dist/primitives/thread/ThreadEmpty.js +1 -2
  138. package/dist/primitives/thread/ThreadIf.js +1 -2
  139. package/dist/primitives/thread/ThreadLoadEarlier.js +1 -2
  140. package/dist/primitives/thread/ThreadRoot.js +1 -2
  141. package/dist/primitives/thread/ThreadRootElementContext.js +1 -2
  142. package/dist/primitives/thread/ThreadScrollToBottom.js +1 -2
  143. package/dist/primitives/thread/ThreadSuggestion.js +1 -2
  144. package/dist/primitives/thread/ThreadViewport.js +1 -2
  145. package/dist/primitives/thread/ThreadViewportFooter.js +1 -2
  146. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js +1 -2
  147. package/dist/primitives/thread/topAnchor/createReserveObservers.js +1 -2
  148. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +1 -2
  149. package/dist/primitives/thread/topAnchor/topAnchorTurn.js +1 -2
  150. package/dist/primitives/thread/topAnchor/topAnchorUtils.js +1 -2
  151. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -2
  152. package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -2
  153. package/dist/primitives/thread.js +1 -2
  154. package/dist/primitives/threadList/ThreadListLoadMore.js +1 -2
  155. package/dist/primitives/threadList/ThreadListNew.js +1 -2
  156. package/dist/primitives/threadList/ThreadListRoot.js +1 -2
  157. package/dist/primitives/threadList.js +1 -2
  158. package/dist/primitives/threadListFocusGroup.js +1 -2
  159. package/dist/primitives/threadListItem/ThreadListItemArchive.js +1 -2
  160. package/dist/primitives/threadListItem/ThreadListItemDelete.js +1 -2
  161. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
  162. package/dist/primitives/threadListItem/ThreadListItemRoot.js +2 -3
  163. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  164. package/dist/primitives/threadListItem/ThreadListItemTrigger.js +1 -2
  165. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +1 -2
  166. package/dist/primitives/threadListItem.js +1 -2
  167. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -2
  168. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -2
  169. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +1 -2
  170. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -2
  171. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -2
  172. package/dist/primitives/threadListItemMore/scope.js +1 -2
  173. package/dist/primitives/threadListItemMore.js +1 -2
  174. package/dist/sandbox-host/SandboxHost.js +1 -2
  175. package/dist/unstable/useComposerInput.js +1 -2
  176. package/dist/unstable/useComposerInputHistory.js +1 -2
  177. package/dist/unstable/useLiveCompletionAdapter.js +1 -2
  178. package/dist/unstable/useMentionAdapter.js +1 -2
  179. package/dist/unstable/useMessageStallDetection.js +1 -2
  180. package/dist/unstable/useModelContextSnapshot.js +1 -2
  181. package/dist/unstable/useSlashCommandAdapter.js +1 -2
  182. package/dist/unstable/webmcp/WebMcpRegistrationResource.js +1 -2
  183. package/dist/unstable/webmcp/convertTools.js +1 -2
  184. package/dist/unstable/webmcp/useWebMcpProvider.js +1 -2
  185. package/dist/unstable/webmcp/webmcp-host.js +1 -2
  186. package/dist/utils/Primitive.js +1 -2
  187. package/dist/utils/createActionButton.js +1 -2
  188. package/dist/utils/getSelectionMessageId.js +1 -2
  189. package/dist/utils/hooks/useManagedRef.js +1 -2
  190. package/dist/utils/hooks/useMediaQuery.js +1 -2
  191. package/dist/utils/hooks/useOnScrollToBottom.js +1 -2
  192. package/dist/utils/hooks/useSizeHandle.js +1 -2
  193. package/dist/utils/isCompositionKey.js +1 -2
  194. package/dist/utils/smooth/SmoothContext.js +1 -2
  195. package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
  196. package/dist/utils/smooth/useSmooth.js +11 -4
  197. package/dist/utils/smooth/useSmooth.js.map +1 -1
  198. package/dist/utils/useIsomorphicLayoutEffect.js +0 -1
  199. package/package.json +6 -6
  200. package/src/mcp-apps/McpAppRenderer.composer.test.tsx +111 -0
  201. package/src/mcp-apps/McpAppRenderer.test.tsx +24 -23
  202. package/src/mcp-apps/McpAppRenderer.tsx +9 -1
  203. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.test.tsx +91 -0
  204. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +54 -0
  205. package/src/primitives/reasoning/useScrollLock.test.tsx +71 -2
  206. package/src/primitives/reasoning/useScrollLock.ts +78 -51
  207. package/src/primitives/threadListItem/ThreadListItemRoot.tsx +4 -1
  208. package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +25 -0
  209. package/src/utils/smooth/useSmooth.test.tsx +113 -4
  210. package/src/utils/smooth/useSmooth.ts +16 -2
  211. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.ts +0 -49
@@ -5,7 +5,7 @@ import { ThreadListItemPrimitiveUnarchive } from "./threadListItem/ThreadListIte
5
5
  import { ThreadListItemPrimitiveDelete } from "./threadListItem/ThreadListItemDelete.js";
6
6
  import { ThreadListItemPrimitiveTrigger } from "./threadListItem/ThreadListItemTrigger.js";
7
7
  import { ThreadListItemPrimitiveTitle } from "./threadListItem/ThreadListItemTitle.js";
8
- //#region src/primitives/threadListItem.ts
8
+ // src/primitives/threadListItem.ts
9
9
  var threadListItem_exports = /* @__PURE__ */ __exportAll({
10
10
  Archive: () => ThreadListItemPrimitiveArchive,
11
11
  Delete: () => ThreadListItemPrimitiveDelete,
@@ -14,7 +14,6 @@ var threadListItem_exports = /* @__PURE__ */ __exportAll({
14
14
  Trigger: () => ThreadListItemPrimitiveTrigger,
15
15
  Unarchive: () => ThreadListItemPrimitiveUnarchive
16
16
  });
17
- //#endregion
18
17
  export { ThreadListItemPrimitiveArchive as Archive, ThreadListItemPrimitiveDelete as Delete, ThreadListItemPrimitiveRoot as Root, ThreadListItemPrimitiveTitle as Title, ThreadListItemPrimitiveTrigger as Trigger, ThreadListItemPrimitiveUnarchive as Unarchive, threadListItem_exports };
19
18
 
20
19
  //# sourceMappingURL=threadListItem.js.map
@@ -8,7 +8,7 @@ import { forwardRef } from "@assistant-ui/tap/react-shim";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
  import { composeEventHandlers } from "radix-ui/internal";
10
10
  import { Direction, DropdownMenu } from "radix-ui";
11
- //#region src/primitives/threadListItemMore/ThreadListItemMoreContent.tsx
11
+ // src/primitives/threadListItemMore/ThreadListItemMoreContent.tsx
12
12
  const ThreadListItemMorePrimitiveContent = forwardRef((t0, forwardedRef) => {
13
13
  const $ = c(21);
14
14
  const { __scopeThreadListItemMore, portalProps, sideOffset: t1, ...props } = t0;
@@ -82,7 +82,6 @@ const ThreadListItemMorePrimitiveContent = forwardRef((t0, forwardedRef) => {
82
82
  return t8;
83
83
  });
84
84
  ThreadListItemMorePrimitiveContent.displayName = "ThreadListItemMorePrimitive.Content";
85
- //#endregion
86
85
  export { ThreadListItemMorePrimitiveContent };
87
86
 
88
87
  //# sourceMappingURL=ThreadListItemMoreContent.js.map
@@ -4,7 +4,7 @@ import { useDropdownMenuScope } from "./scope.js";
4
4
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
5
5
  import { forwardRef } from "@assistant-ui/tap/react-shim";
6
6
  import { jsx } from "react/jsx-runtime";
7
- //#region src/primitives/threadListItemMore/ThreadListItemMoreItem.tsx
7
+ // src/primitives/threadListItemMore/ThreadListItemMoreItem.tsx
8
8
  const ThreadListItemMorePrimitiveItem = forwardRef((t0, ref) => {
9
9
  const $ = c(7);
10
10
  let __scopeThreadListItemMore;
@@ -34,7 +34,6 @@ const ThreadListItemMorePrimitiveItem = forwardRef((t0, ref) => {
34
34
  return t1;
35
35
  });
36
36
  ThreadListItemMorePrimitiveItem.displayName = "ThreadListItemMorePrimitive.Item";
37
- //#endregion
38
37
  export { ThreadListItemMorePrimitiveItem };
39
38
 
40
39
  //# sourceMappingURL=ThreadListItemMoreItem.js.map
@@ -5,7 +5,7 @@ import { createContext, useContext } from "@assistant-ui/tap/react-shim";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { useControllableState } from "radix-ui/internal";
7
7
  import { DropdownMenu } from "radix-ui";
8
- //#region src/primitives/threadListItemMore/ThreadListItemMoreRoot.tsx
8
+ // src/primitives/threadListItemMore/ThreadListItemMoreRoot.tsx
9
9
  const ThreadListItemMoreSetOpenContext = createContext(() => {});
10
10
  const useThreadListItemMoreSetOpen = () => {
11
11
  return useContext(ThreadListItemMoreSetOpenContext);
@@ -112,7 +112,6 @@ const ThreadListItemMorePrimitiveRoot = (t0) => {
112
112
  return t7;
113
113
  };
114
114
  ThreadListItemMorePrimitiveRoot.displayName = "ThreadListItemMorePrimitive.Root";
115
- //#endregion
116
115
  export { ThreadListItemMorePrimitiveRoot, useThreadListItemMoreSetOpen, useThreadListItemMoreSharedFocusGroup };
117
116
 
118
117
  //# sourceMappingURL=ThreadListItemMoreRoot.js.map
@@ -4,7 +4,7 @@ import { useDropdownMenuScope } from "./scope.js";
4
4
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
5
5
  import { forwardRef } from "@assistant-ui/tap/react-shim";
6
6
  import { jsx } from "react/jsx-runtime";
7
- //#region src/primitives/threadListItemMore/ThreadListItemMoreSeparator.tsx
7
+ // src/primitives/threadListItemMore/ThreadListItemMoreSeparator.tsx
8
8
  const ThreadListItemMorePrimitiveSeparator = forwardRef((t0, ref) => {
9
9
  const $ = c(7);
10
10
  let __scopeThreadListItemMore;
@@ -34,7 +34,6 @@ const ThreadListItemMorePrimitiveSeparator = forwardRef((t0, ref) => {
34
34
  return t1;
35
35
  });
36
36
  ThreadListItemMorePrimitiveSeparator.displayName = "ThreadListItemMorePrimitive.Separator";
37
- //#endregion
38
37
  export { ThreadListItemMorePrimitiveSeparator };
39
38
 
40
39
  //# sourceMappingURL=ThreadListItemMoreSeparator.js.map
@@ -8,7 +8,7 @@ import { forwardRef } from "@assistant-ui/tap/react-shim";
8
8
  import { jsx } from "react/jsx-runtime";
9
9
  import { composeEventHandlers, useComposedRefs } from "radix-ui/internal";
10
10
  import { Direction } from "radix-ui";
11
- //#region src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx
11
+ // src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx
12
12
  const ThreadListItemMorePrimitiveTrigger = forwardRef((t0, ref) => {
13
13
  const $ = c(10);
14
14
  const { __scopeThreadListItemMore, ...rest } = t0;
@@ -51,7 +51,6 @@ const ThreadListItemMorePrimitiveTrigger = forwardRef((t0, ref) => {
51
51
  return t3;
52
52
  });
53
53
  ThreadListItemMorePrimitiveTrigger.displayName = "ThreadListItemMorePrimitive.Trigger";
54
- //#endregion
55
54
  export { ThreadListItemMorePrimitiveTrigger };
56
55
 
57
56
  //# sourceMappingURL=ThreadListItemMoreTrigger.js.map
@@ -1,7 +1,6 @@
1
1
  import { DropdownMenu } from "radix-ui";
2
- //#region src/primitives/threadListItemMore/scope.ts
2
+ // src/primitives/threadListItemMore/scope.ts
3
3
  const useDropdownMenuScope = DropdownMenu.createDropdownMenuScope();
4
- //#endregion
5
4
  export { useDropdownMenuScope };
6
5
 
7
6
  //# sourceMappingURL=scope.js.map
@@ -4,7 +4,7 @@ import { ThreadListItemMorePrimitiveTrigger } from "./threadListItemMore/ThreadL
4
4
  import { ThreadListItemMorePrimitiveContent } from "./threadListItemMore/ThreadListItemMoreContent.js";
5
5
  import { ThreadListItemMorePrimitiveItem } from "./threadListItemMore/ThreadListItemMoreItem.js";
6
6
  import { ThreadListItemMorePrimitiveSeparator } from "./threadListItemMore/ThreadListItemMoreSeparator.js";
7
- //#region src/primitives/threadListItemMore.ts
7
+ // src/primitives/threadListItemMore.ts
8
8
  var threadListItemMore_exports = /* @__PURE__ */ __exportAll({
9
9
  Content: () => ThreadListItemMorePrimitiveContent,
10
10
  Item: () => ThreadListItemMorePrimitiveItem,
@@ -12,7 +12,6 @@ var threadListItemMore_exports = /* @__PURE__ */ __exportAll({
12
12
  Separator: () => ThreadListItemMorePrimitiveSeparator,
13
13
  Trigger: () => ThreadListItemMorePrimitiveTrigger
14
14
  });
15
- //#endregion
16
15
  export { ThreadListItemMorePrimitiveContent as Content, ThreadListItemMorePrimitiveItem as Item, ThreadListItemMorePrimitiveRoot as Root, ThreadListItemMorePrimitiveSeparator as Separator, ThreadListItemMorePrimitiveTrigger as Trigger, threadListItemMore_exports };
17
16
 
18
17
  //# sourceMappingURL=threadListItemMore.js.map
@@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
5
5
  import { invokeUserCallback } from "@assistant-ui/core/internal";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { SafeContentFrame, isShimLoadError } from "safe-content-frame";
8
- //#region src/sandbox-host/SandboxHost.tsx
8
+ // src/sandbox-host/SandboxHost.tsx
9
9
  const DEFAULT_PRODUCT = "assistant-ui-sandbox";
10
10
  const DEFAULT_MAX_HEIGHT = 800;
11
11
  const LOAD_TIMEOUT_MS = 1e4;
@@ -184,7 +184,6 @@ function SandboxHost(t0) {
184
184
  } else t9 = $[20];
185
185
  return t9;
186
186
  }
187
- //#endregion
188
187
  export { SandboxHost, isSandboxFrameMessage };
189
188
 
190
189
  //# sourceMappingURL=SandboxHost.js.map
@@ -4,7 +4,7 @@ import { useComposerSend } from "@assistant-ui/core/react";
4
4
  import { useCallback } from "@assistant-ui/tap/react-shim";
5
5
  import { useAui } from "@assistant-ui/store";
6
6
  import { flushTapSync } from "@assistant-ui/tap";
7
- //#region src/unstable/useComposerInput.ts
7
+ // src/unstable/useComposerInput.ts
8
8
  /**
9
9
  * Headless bridge to the composer's text value and send action, for building a
10
10
  * custom composer input without `ComposerPrimitive.Input`. It is a thin bridge,
@@ -74,7 +74,6 @@ function unstable_useComposerInput(options) {
74
74
  function unstable_useTriggerPopoverAriaProps() {
75
75
  return useTriggerPopoverAriaProps();
76
76
  }
77
- //#endregion
78
77
  export { unstable_useComposerInput, unstable_useTriggerPopoverAriaProps };
79
78
 
80
79
  //# sourceMappingURL=useComposerInput.js.map
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef } from "@assistant-ui/tap/react
4
4
  import { useAui } from "@assistant-ui/store";
5
5
  import { flushTapSync } from "@assistant-ui/tap";
6
6
  import { getThreadMessageText } from "@assistant-ui/core/internal";
7
- //#region src/unstable/useComposerInputHistory.ts
7
+ // src/unstable/useComposerInputHistory.ts
8
8
  const deriveHistory = (messages) => {
9
9
  const entries = [];
10
10
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -111,7 +111,6 @@ function unstable_useComposerInputHistory() {
111
111
  }, [aui, popoverCtx]);
112
112
  return useMemo(() => ({ onKeyDown }), [onKeyDown]);
113
113
  }
114
- //#endregion
115
114
  export { unstable_useComposerInputHistory };
116
115
 
117
116
  //# sourceMappingURL=useComposerInputHistory.js.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useIsomorphicLayoutEffect } from "../utils/useIsomorphicLayoutEffect.js";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
4
- //#region src/unstable/useLiveCompletionAdapter.ts
4
+ // src/unstable/useLiveCompletionAdapter.ts
5
5
  /** Sentinel that no real query (including the empty string) equals, so the first query always fetches. */
6
6
  const NO_QUERY = "\0";
7
7
  /**
@@ -174,7 +174,6 @@ function unstable_useLiveCompletionAdapter(options) {
174
174
  isLoading
175
175
  };
176
176
  }
177
- //#endregion
178
177
  export { unstable_useLiveCompletionAdapter };
179
178
 
180
179
  //# sourceMappingURL=useLiveCompletionAdapter.js.map
@@ -4,7 +4,7 @@ import { shallowEqualRecords, useModelContextSnapshot } from "./useModelContextS
4
4
  import { unstable_defaultDirectiveFormatter } from "@assistant-ui/core";
5
5
  import { useMemo } from "@assistant-ui/tap/react-shim";
6
6
  import { useAui } from "@assistant-ui/store";
7
- //#region src/unstable/useMentionAdapter.ts
7
+ // src/unstable/useMentionAdapter.ts
8
8
  const EMPTY_TOOL_MENTIONS = Object.freeze({});
9
9
  const toolMentionSource = {
10
10
  empty: EMPTY_TOOL_MENTIONS,
@@ -126,7 +126,6 @@ function toTriggerItem(m) {
126
126
  ...metadata !== void 0 ? { metadata } : {}
127
127
  };
128
128
  }
129
- //#endregion
130
129
  export { unstable_useMentionAdapter };
131
130
 
132
131
  //# sourceMappingURL=useMentionAdapter.js.map
@@ -2,7 +2,7 @@
2
2
  import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
3
3
  import { useAuiState } from "@assistant-ui/store";
4
4
  import { useShallowSelector } from "@assistant-ui/store/internal";
5
- //#region src/unstable/useMessageStallDetection.ts
5
+ // src/unstable/useMessageStallDetection.ts
6
6
  /**
7
7
  * Detects mid-run output stalls on the current message: while the message is
8
8
  * running, watches its text, reasoning, and tool-argument values plus tool-result
@@ -68,7 +68,6 @@ function unstable_useMessageStallDetection(options) {
68
68
  stalledForMs: Math.max(0, now - lastActivityRef.current)
69
69
  };
70
70
  }
71
- //#endregion
72
71
  export { unstable_useMessageStallDetection };
73
72
 
74
73
  //# sourceMappingURL=useMessageStallDetection.js.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { useEffect, useState } from "@assistant-ui/tap/react-shim";
4
- //#region src/unstable/useModelContextSnapshot.ts
4
+ // src/unstable/useModelContextSnapshot.ts
5
5
  /**
6
6
  * `getModelContext()` rebuilds its result on every call, so a projection of the
7
7
  * fields a consumer observes is held in state and refreshed on notification
@@ -55,7 +55,6 @@ const shallowEqualRecords = (previous, next) => {
55
55
  if (keys.length !== Object.keys(next).length) return false;
56
56
  return keys.every((key) => Object.hasOwn(next, key) && previous[key] === next[key]);
57
57
  };
58
- //#endregion
59
58
  export { shallowEqualRecords, useModelContextSnapshot };
60
59
 
61
60
  //# sourceMappingURL=useModelContextSnapshot.js.map
@@ -2,7 +2,7 @@
2
2
  import { useIsomorphicLayoutEffect } from "../utils/useIsomorphicLayoutEffect.js";
3
3
  import { matchesTriggerItemQuery } from "../primitives/composer/trigger/matchesTriggerItemQuery.js";
4
4
  import { useMemo, useRef } from "@assistant-ui/tap/react-shim";
5
- //#region src/unstable/useSlashCommandAdapter.ts
5
+ // src/unstable/useSlashCommandAdapter.ts
6
6
  /**
7
7
  * Bundles slash command definitions (with inline `execute` callbacks) into
8
8
  * `{adapter, action}` that plug directly into `ComposerTriggerPopover`.
@@ -75,7 +75,6 @@ function areTriggerItemsEqual(previous, next) {
75
75
  return nextItem !== void 0 && item.id === nextItem.id && item.label === nextItem.label && item.description === nextItem.description && item.metadata?.icon === nextItem.metadata?.icon;
76
76
  });
77
77
  }
78
- //#endregion
79
78
  export { unstable_useSlashCommandAdapter };
80
79
 
81
80
  //# sourceMappingURL=useSlashCommandAdapter.js.map
@@ -2,7 +2,7 @@ import { toWebMcpTool } from "./convertTools.js";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
4
4
  import { resource } from "@assistant-ui/tap";
5
- //#region src/unstable/webmcp/WebMcpRegistrationResource.ts
5
+ // src/unstable/webmcp/WebMcpRegistrationResource.ts
6
6
  const notPermitted = (error) => error?.name === "NotAllowedError";
7
7
  const notPermittedMessage = (name) => `[assistant-ui] WebMCP registration for tool "${name}" was not permitted; the page's tools permission is disabled.`;
8
8
  const useWebMcpRegistration = (t0) => {
@@ -67,7 +67,6 @@ const useWebMcpRegistration = (t0) => {
67
67
  return refused ? null : name;
68
68
  };
69
69
  const WebMcpRegistrationResource = resource(useWebMcpRegistration);
70
- //#endregion
71
70
  export { WebMcpRegistrationResource };
72
71
 
73
72
  //# sourceMappingURL=WebMcpRegistrationResource.js.map
@@ -1,6 +1,6 @@
1
1
  import { generateId } from "@assistant-ui/core/internal";
2
2
  import { ToolResponse, toJSONSchema } from "assistant-stream";
3
- //#region src/unstable/webmcp/convertTools.ts
3
+ // src/unstable/webmcp/convertTools.ts
4
4
  /**
5
5
  * The predicate the WebMCP provider uses when no `filter` is passed: an enabled
6
6
  * frontend tool with a client-side `execute`. A tool authored without a `type`
@@ -155,7 +155,6 @@ const toWebMcpTool = (name, getTool, lifecycleSignal) => ({
155
155
  }
156
156
  }
157
157
  });
158
- //#endregion
159
158
  export { defaultWebMcpFilter, toMcpContent, toWebMcpInputSchema, toWebMcpTool };
160
159
 
161
160
  //# sourceMappingURL=convertTools.js.map
@@ -8,7 +8,7 @@ import { useCallback, useEffect, useInsertionEffect, useRef, useState, useSyncEx
8
8
  import { useAui } from "@assistant-ui/store";
9
9
  import { useResources, useTapRoot, withKey } from "@assistant-ui/tap";
10
10
  import { shallowEqual } from "@assistant-ui/store/internal";
11
- //#region src/unstable/webmcp/useWebMcpProvider.ts
11
+ // src/unstable/webmcp/useWebMcpProvider.ts
12
12
  const EMPTY_NAMES = Object.freeze([]);
13
13
  const EMPTY_TOOLS = Object.freeze({});
14
14
  const warned = /* @__PURE__ */ new WeakSet();
@@ -111,7 +111,6 @@ const unstable_useWebMcpProvider = (options = {}) => {
111
111
  registeredToolNames
112
112
  };
113
113
  };
114
- //#endregion
115
114
  export { unstable_useWebMcpProvider };
116
115
 
117
116
  //# sourceMappingURL=useWebMcpProvider.js.map
@@ -1,4 +1,4 @@
1
- //#region src/unstable/webmcp/webmcp-host.ts
1
+ // src/unstable/webmcp/webmcp-host.ts
2
2
  const isThenable = (value) => typeof value?.then === "function";
3
3
  const resolveModelContext = () => {
4
4
  const context = globalThis.document?.modelContext ?? globalThis.navigator?.modelContext;
@@ -23,7 +23,6 @@ const getDefaultWebMcpHost = () => {
23
23
  };
24
24
  return createHost(context);
25
25
  };
26
- //#endregion
27
26
  export { getDefaultWebMcpHost };
28
27
 
29
28
  //# sourceMappingURL=webmcp-host.js.map
@@ -3,7 +3,7 @@ import { cloneElement, forwardRef, isValidElement } from "@assistant-ui/tap/reac
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { Primitive as Primitive$1 } from "radix-ui/internal";
5
5
  import { Slot } from "radix-ui";
6
- //#region src/utils/Primitive.tsx
6
+ // src/utils/Primitive.tsx
7
7
  /**
8
8
  * Thin wrapper around Radix `Primitive` that adds `render` prop support.
9
9
  *
@@ -126,7 +126,6 @@ const Primitive = NODES.reduce((acc, node) => {
126
126
  acc[node] = createPrimitive(node);
127
127
  return acc;
128
128
  }, {});
129
- //#endregion
130
129
  export { Primitive, renderSlot, withRenderProp };
131
130
 
132
131
  //# sourceMappingURL=Primitive.js.map
@@ -3,7 +3,7 @@ import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { forwardRef } from "@assistant-ui/tap/react-shim";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { composeEventHandlers } from "radix-ui/internal";
6
- //#region src/utils/createActionButton.tsx
6
+ // src/utils/createActionButton.tsx
7
7
  const createActionButton = (displayName, useActionButton, forwardProps = []) => {
8
8
  const ActionButton = forwardRef((props, forwardedRef) => {
9
9
  const $ = c(6);
@@ -39,7 +39,6 @@ const createActionButton = (displayName, useActionButton, forwardProps = []) =>
39
39
  ActionButton.displayName = displayName;
40
40
  return ActionButton;
41
41
  };
42
- //#endregion
43
42
  export { createActionButton };
44
43
 
45
44
  //# sourceMappingURL=createActionButton.js.map
@@ -1,4 +1,4 @@
1
- //#region src/utils/getSelectionMessageId.ts
1
+ // src/utils/getSelectionMessageId.ts
2
2
  const QUOTE_SELECTABLE_SELECTOR = "[data-aui-quote-selectable]";
3
3
  const getElement = (node) => {
4
4
  return node instanceof HTMLElement ? node : node?.parentElement ?? null;
@@ -79,7 +79,6 @@ const getSelectionMessageId = (selection, root) => {
79
79
  for (const { commonAncestorContainer } of ranges) if (!scope.contains(commonAncestorContainer)) return null;
80
80
  return intersectsExcluded(scope, ranges) ? null : messageId;
81
81
  };
82
- //#endregion
83
82
  export { getSelectionMessageId };
84
83
 
85
84
  //# sourceMappingURL=getSelectionMessageId.js.map
@@ -1,6 +1,6 @@
1
1
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
2
2
  import { useRef } from "@assistant-ui/tap/react-shim";
3
- //#region src/utils/hooks/useManagedRef.ts
3
+ // src/utils/hooks/useManagedRef.ts
4
4
  const useManagedRef = (callback) => {
5
5
  const $ = c(2);
6
6
  const cleanupRef = useRef(void 0);
@@ -18,7 +18,6 @@ const useManagedRef = (callback) => {
18
18
  } else t0 = $[1];
19
19
  return t0;
20
20
  };
21
- //#endregion
22
21
  export { useManagedRef };
23
22
 
24
23
  //# sourceMappingURL=useManagedRef.js.map
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
3
3
  import { useSyncExternalStore } from "@assistant-ui/tap/react-shim";
4
- //#region src/utils/hooks/useMediaQuery.ts
4
+ // src/utils/hooks/useMediaQuery.ts
5
5
  const getServerSnapshot = () => false;
6
6
  const noopUnsubscribe = () => {};
7
7
  const useMediaQuery = (query) => {
@@ -29,7 +29,6 @@ const useMediaQuery = (query) => {
29
29
  } else t1 = $[3];
30
30
  return useSyncExternalStore(subscribe, t1, getServerSnapshot);
31
31
  };
32
- //#endregion
33
32
  export { useMediaQuery };
34
33
 
35
34
  //# sourceMappingURL=useMediaQuery.js.map
@@ -3,7 +3,7 @@ import { useThreadViewport } from "../../context/react/ThreadViewportContext.js"
3
3
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
4
4
  import { useEffect } from "@assistant-ui/tap/react-shim";
5
5
  import { useCallbackRef } from "radix-ui/internal";
6
- //#region src/utils/hooks/useOnScrollToBottom.ts
6
+ // src/utils/hooks/useOnScrollToBottom.ts
7
7
  const useOnScrollToBottom = (callback) => {
8
8
  const $ = c(4);
9
9
  const callbackRef = useCallbackRef(callback);
@@ -26,7 +26,6 @@ const useOnScrollToBottom = (callback) => {
26
26
  function _temp(vp) {
27
27
  return vp.onScrollToBottom;
28
28
  }
29
- //#endregion
30
29
  export { useOnScrollToBottom };
31
30
 
32
31
  //# sourceMappingURL=useOnScrollToBottom.js.map
@@ -2,7 +2,7 @@
2
2
  import { useManagedRef } from "./useManagedRef.js";
3
3
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
4
4
  import "@assistant-ui/tap/react-shim";
5
- //#region src/utils/hooks/useSizeHandle.ts
5
+ // src/utils/hooks/useSizeHandle.ts
6
6
  /**
7
7
  * Hook that creates a ref for tracking element size via a SizeHandle.
8
8
  * Automatically sets up ResizeObserver and reports height changes.
@@ -36,7 +36,6 @@ const useSizeHandle = (register, getHeight) => {
36
36
  } else t0 = $[2];
37
37
  return useManagedRef(t0);
38
38
  };
39
- //#endregion
40
39
  export { useSizeHandle };
41
40
 
42
41
  //# sourceMappingURL=useSizeHandle.js.map
@@ -1,6 +1,5 @@
1
- //#region src/utils/isCompositionKey.ts
1
+ // src/utils/isCompositionKey.ts
2
2
  const isCompositionKey = (event) => event.isComposing || event.keyCode === 229;
3
- //#endregion
4
3
  export { isCompositionKey };
5
4
 
6
5
  //# sourceMappingURL=isCompositionKey.js.map
@@ -5,7 +5,7 @@ import { createContext, forwardRef, useContext, useState } from "@assistant-ui/t
5
5
  import { useAui } from "@assistant-ui/store";
6
6
  import { create } from "zustand";
7
7
  import { jsx } from "react/jsx-runtime";
8
- //#region src/utils/smooth/SmoothContext.tsx
8
+ // src/utils/smooth/SmoothContext.tsx
9
9
  const SmoothContext = createContext(null);
10
10
  const makeSmoothContext = (initialState) => {
11
11
  return { useSmoothStatus: create(() => initialState) };
@@ -65,7 +65,6 @@ function useSmoothContext(options) {
65
65
  return context;
66
66
  }
67
67
  const { useSmoothStatus, useSmoothStatusStore } = createContextStoreHook(useSmoothContext, "useSmoothStatus");
68
- //#endregion
69
68
  export { SmoothContextProvider, useSmoothStatus, useSmoothStatusStore, withSmoothContextProvider };
70
69
 
71
70
  //# sourceMappingURL=SmoothContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSmooth.d.ts","sourceRoot":"","sources":["../../../src/utils/smooth/useSmooth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAM5B;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAwFF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,SAAS,GACpB,OAAO,gBAAgB,GAAG,CAAC,eAAe,GAAG,oBAAoB,CAAC,EAClE,SAAQ,OAAO,GAAG,aAAqB,KACtC,gBAAgB,GAAG,CAAC,eAAe,GAAG,oBAAoB,CAiI5D,CAAC"}
1
+ {"version":3,"file":"useSmooth.d.ts","sourceRoot":"","sources":["../../../src/utils/smooth/useSmooth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AAM5B;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAwFF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,SAAS,GACpB,OAAO,gBAAgB,GAAG,CAAC,eAAe,GAAG,oBAAoB,CAAC,EAClE,SAAQ,OAAO,GAAG,aAAqB,KACtC,gBAAgB,GAAG,CAAC,eAAe,GAAG,oBAAoB,CA+I5D,CAAC"}
@@ -5,7 +5,7 @@ import { useSmoothStatusStore } from "./SmoothContext.js";
5
5
  import { useEffect, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
6
6
  import { useAui, useAuiState } from "@assistant-ui/store";
7
7
  import { useCallbackRef } from "radix-ui/internal";
8
- //#region src/utils/smooth/useSmooth.ts
8
+ // src/utils/smooth/useSmooth.ts
9
9
  const DEFAULT_DRAIN_MS = 250;
10
10
  const DEFAULT_MAX_CHAR_INTERVAL_MS = 5;
11
11
  var TextStreamAnimator = class {
@@ -120,6 +120,11 @@ const useSmooth = (state, smooth = false) => {
120
120
  state.status
121
121
  ]);
122
122
  const [animatorRef] = useState(() => new TextStreamAnimator(displayedText, setText));
123
+ const [prevEnabled, setPrevEnabled] = useState(enabled);
124
+ if (enabled !== prevEnabled) {
125
+ setPrevEnabled(enabled);
126
+ if (enabled && part === prevPart && text.startsWith(animatorRef.currentText)) setDisplayedText(animatorRef.currentText);
127
+ }
123
128
  useEffect(() => {
124
129
  animatorRef.drainMs = drainMs;
125
130
  animatorRef.maxCharIntervalMs = maxCharIntervalMs;
@@ -134,12 +139,15 @@ const useSmooth = (state, smooth = false) => {
134
139
  ]);
135
140
  const animatorPartRef = useRef(part);
136
141
  useEffect(() => {
142
+ const partChanged = animatorPartRef.current !== part;
143
+ animatorPartRef.current = part;
137
144
  if (!enabled) {
138
145
  animatorRef.stop();
146
+ animatorRef.currentText = text;
147
+ animatorRef.targetText = text;
148
+ animatorRef.lastCommitTime = -Infinity;
139
149
  return;
140
150
  }
141
- const partChanged = animatorPartRef.current !== part;
142
- animatorPartRef.current = part;
143
151
  if (partChanged || !text.startsWith(animatorRef.targetText)) {
144
152
  if (state.status.type === "running") {
145
153
  animatorRef.currentText = "";
@@ -190,7 +198,6 @@ const useSmooth = (state, smooth = false) => {
190
198
  text
191
199
  ]);
192
200
  };
193
- //#endregion
194
201
  export { useSmooth };
195
202
 
196
203
  //# sourceMappingURL=useSmooth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useMediaQuery","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","lastCommitTime","Infinity","targetText","currentText","setText","newText","constructor","start","performance","now","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","reduceMotion","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"radix-ui/internal\";\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = 0;\n public lastCommitTime: number = -Infinity;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n public currentText: string;\n private setText: (newText: string) => void;\n\n constructor(currentText: string, setText: (newText: string) => void) {\n this.currentText = currentText;\n this.setText = setText;\n }\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = performance.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = performance.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n * If the source settles before any character has been revealed, the text\n * is committed immediately so a missed animation frame cannot leave an\n * empty bubble.\n *\n * The reveal auto-disables under `prefers-reduced-motion: reduce`,\n * committing the full text immediately; this takes precedence over an\n * explicit `smooth={true}`.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const reduceMotion = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null && !reduceMotion;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part);\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState(\n () => new TextStreamAnimator(displayedText, setText),\n );\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n if (!enabled) {\n animatorRef.stop();\n return;\n }\n\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n // A new part whose text shares a prefix with the previous target would\n // keep the stale cursor and flicker without this reset.\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = -Infinity;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n setText(text);\n }\n return;\n }\n\n animatorRef.targetText = text;\n if (state.status.type !== \"running\") {\n // No character has painted. A pending frame that never runs would\n // leave an empty bubble after settle.\n if (animatorRef.currentText === \"\") {\n animatorRef.currentText = text;\n animatorRef.stop();\n setText(text);\n return;\n }\n animatorRef.start();\n return;\n }\n\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part, setText]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":";;;;;;;;AA8CA,MAAMmB,mBAAmB;AACzB,MAAMC,+BAA+B;AAErC,IAAMC,qBAAN,MAAyB;CACvB,mBAA0C;CAC1C,iBAAiC;CACjC,iBAAgC;CAEhC,aAA4B;CAC5B,UAAyBF;CACzB,oBAAmCC;CACnC,mBAAkCK;CAClC,cAA6B;CAE7B;CACA;CAEAK,YAAYH,aAAqBC,SAAoC;EACnE,KAAKD,cAAcA;EACnB,KAAKC,UAAUA;CACjB;CAEAG,QAAQ;EACN,IAAI,KAAKT,qBAAqB,MAAM;EACpC,KAAKC,iBAAiBS,YAAYC,IAAI;EACtC,KAAKC,QAAQ;CACf;CAEAC,OAAO;EACL,IAAI,KAAKb,qBAAqB,MAAM;GAClCc,qBAAqB,KAAKd,gBAAgB;GAC1C,KAAKA,mBAAmB;EAC1B;CACF;CAEA,gBAAwB;EACtB,MAAMe,cAAcL,YAAYC,IAAI;EAEpC,IAAIM,gBADcF,cAAc,KAAKd;EAGrC,MAAMiB,iBAAiB,KAAKd,WAAWe,SAAS,KAAKd,YAAYc;EACjE,MAAMC,kBAAkBC,KAAKC,IAC3B,KAAK5B,mBACL,KAAKD,UAAUyB,cACjB;EAEA,MAAMK,aAAaF,KAAKC,IAAIJ,gBAAgB,KAAKvB,gBAAgB;EACjE,IAAI6B,aAAa;EACjB,OAAOP,iBAAiBG,mBAAmBI,aAAaD,YAAY;GAClEC;GACAP,iBAAiBG;EACnB;EAGA,IAAII,eAAeD,cAAcA,eAAe,KAAK5B,kBACnDsB,gBAAgB;EAGlB,IAAIO,eAAeN,gBACjB,KAAKlB,mBAAmByB,sBAAsB,KAAKb,OAAO;OAE1D,KAAKZ,mBAAmB;EAE1B,IAAIwB,eAAe,GAAG;EAEtB,KAAKnB,cAAc,KAAKD,WAAWsB,MACjC,GACA,KAAKrB,YAAYc,SAASK,UAC5B;EACA,KAAKvB,iBAAiBc,cAAcE;EAGpC,IADmBO,eAAeN,kBAChBH,cAAc,KAAKb,kBAAkB,KAAKN,aAAa;GACvE,KAAKM,iBAAiBa;GACtB,KAAKT,QAAQ,KAAKD,WAAW;EAC/B;CACF;AACF;AAEA,MAAMuB,gBAAmCC,OAAOC,OAAO,EACrDC,MAAM,UACR,CAAC;AAED,MAAMC,cAAcC,OAA2BC,aAC7CD,UAAUE,KAAAA,KAAaF,QAAQ,IAAIA,QAAQC;;;;;;;;;;;;;;;;;;;;;;;;AAyB7C,MAAaE,aACXC,OACAC,SAAkC,UAC8B;CAChE,MAAM,EAAEC,SAASF;CACjB,MAAMG,eAAenD,cAAc,kCAAkC;CACrE,MAAMoD,UACJ,OAAOH,WAAW,YAAYA,WAAW,OAAOA,SAASH,KAAAA;CAC3D,MAAMO,UAAUJ,WAAW,SAASA,WAAW,QAAQ,CAACE;CACxD,MAAM/C,UAAUuC,WAAWS,SAAShD,SAASI,gBAAgB;CAC7D,MAAMH,oBAAoBsC,WACxBS,SAAS/C,mBACTI,4BACF;CACA,MAAMH,mBAAmBqC,WAAWS,SAAS9C,kBAAkBQ,QAAQ;CACvE,MAAMP,cAAcoC,WAAWS,SAAS7C,aAAa,CAAC;CAEtD,MAAM,CAAC+C,eAAeC,oBAAoB/D,SACxCwD,MAAMQ,OAAOd,SAAS,YAAY,KAAKQ,IACzC;CAWA,MAAMO,MAAMhE,OAAO;CACnB,MAAMiE,OAAOhE,kBAAkB+D,IAAIC,IAAI;CACvC,MAAM,CAACC,UAAUC,eAAepE,SAASkE,IAAI;CAC7C,IAAIA,SAASC,YAAY,CAACT,KAAKW,WAAWP,aAAa,GAAG;EACxDM,YAAYF,IAAI;EAChBH,iBAAiBP,MAAMQ,OAAOd,SAAS,YAAY,KAAKQ,IAAI;CAC9D;CAEA,MAAMY,oBAAoB7D,qBAAqB,EAAE8D,UAAU,KAAK,CAAC;CACjE,MAAM9C,UAAUlB,gBAAgBmD,WAAiB;EAC/CK,iBAAiBL,MAAI;EACrB,IAAIY,mBAAmB;GACrB,MAAME,SACJV,kBAAkBJ,UAAQF,MAAMQ,OAAOd,SAAS,YAC5CH,gBACAS,MAAMQ;GACZtD,cAAc4D,iBAAiB,CAAC,CAACG,SAASD,QAAQ,IAAI;EACxD;CACF,CAAC;CAGD3E,gBAAgB;EACd,IAAIyE,mBAAmB;GACrB,MAAME,WACJX,YAAYC,kBAAkBJ,QAAQF,MAAMQ,OAAOd,SAAS,aACxDH,gBACAS,MAAMQ;GACZtD,cAAc4D,iBAAiB,CAAC,CAACG,SAASD,UAAQ,IAAI;EACxD;CACF,GAAG;EAACF;EAAmBT;EAASH;EAAMI;EAAeN,MAAMQ;CAAM,CAAC;CAElE,MAAM,CAACU,eAAe1E,eACd,IAAIkB,mBAAmB4C,eAAerC,OAAO,CACrD;CAEA5B,gBAAgB;EACd6E,YAAY9D,UAAUA;EACtB8D,YAAY7D,oBAAoBA;EAChC6D,YAAY5D,mBAAmBA;EAC/B4D,YAAY3D,cAAcA;CAC5B,GAAG;EAAC2D;EAAa9D;EAASC;EAAmBC;EAAkBC;CAAW,CAAC;CAE3E,MAAM4D,kBAAkB5E,OAAOmE,IAAI;CACnCrE,gBAAgB;EACd,IAAI,CAACgE,SAAS;GACZa,YAAY1C,KAAK;GACjB;EACF;EAEA,MAAM4C,cAAcD,gBAAgBE,YAAYX;EAChDS,gBAAgBE,UAAUX;EAG1B,IAAIU,eAAe,CAAClB,KAAKW,WAAWK,YAAYnD,UAAU,GAAG;GAC3D,IAAIiC,MAAMQ,OAAOd,SAAS,WAAW;IACnCwB,YAAYlD,cAAc;IAC1BkD,YAAYnD,aAAamC;IACzBgB,YAAYrD,iBAAiB;IAC7BqD,YAAY9C,MAAM;GACpB,OAAO;IACL8C,YAAYlD,cAAckC;IAC1BgB,YAAYnD,aAAamC;IACzBgB,YAAY1C,KAAK;IACjBP,QAAQiC,IAAI;GACd;GACA;EACF;EAEAgB,YAAYnD,aAAamC;EACzB,IAAIF,MAAMQ,OAAOd,SAAS,WAAW;GAGnC,IAAIwB,YAAYlD,gBAAgB,IAAI;IAClCkD,YAAYlD,cAAckC;IAC1BgB,YAAY1C,KAAK;IACjBP,QAAQiC,IAAI;IACZ;GACF;GACAgB,YAAY9C,MAAM;GAClB;EACF;EAEA8C,YAAY9C,MAAM;CACpB,GAAG;EAAC8C;EAAab;EAASH;EAAMF,MAAMQ,OAAOd;EAAMgB;EAAMzC;CAAO,CAAC;CAEjE5B,gBAAgB;EACd,aAAa;GACX6E,YAAY1C,KAAK;EACnB;CACF,GAAG,CAAC0C,WAAW,CAAC;CAEhB,OAAO5E,cAEH+D,UACI;EACE,GAAGL;EACHE,MAAMI;EACNE,QAAQN,SAASI,gBAAgBN,MAAMQ,SAASjB;CAClD,IACAS,OACN;EAACK;EAASC;EAAeN;EAAOE;CAAI,CACtC;AACF"}
1
+ {"version":3,"file":"useSmooth.js","names":["useEffect","useMemo","useRef","useState","useAui","useAuiState","MessagePartStatus","ReasoningMessagePart","TextMessagePart","MessagePartState","useCallbackRef","useMediaQuery","useSmoothStatusStore","writableStore","SmoothOptions","drainMs","maxCharIntervalMs","maxCharsPerFrame","minCommitMs","DEFAULT_DRAIN_MS","DEFAULT_MAX_CHAR_INTERVAL_MS","TextStreamAnimator","animationFrameId","lastUpdateTime","lastCommitTime","Infinity","targetText","currentText","setText","newText","constructor","start","performance","now","animate","stop","cancelAnimationFrame","currentTime","deltaTime","timeToConsume","remainingChars","length","baseTimePerChar","Math","min","frameLimit","charsToAdd","requestAnimationFrame","slice","isComplete","SMOOTH_STATUS","Object","freeze","type","positiveOr","value","fallback","undefined","useSmooth","state","smooth","text","reduceMotion","options","enabled","displayedText","setDisplayedText","status","aui","part","prevPart","setPrevPart","startsWith","smoothStatusStore","optional","target","setState","animatorRef","prevEnabled","setPrevEnabled","animatorPartRef","partChanged","current"],"sources":["../../../src/utils/smooth/useSmooth.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type {\n MessagePartStatus,\n ReasoningMessagePart,\n TextMessagePart,\n MessagePartState,\n} from \"@assistant-ui/core\";\nimport { useCallbackRef } from \"radix-ui/internal\";\nimport { useMediaQuery } from \"../hooks/useMediaQuery\";\nimport { useSmoothStatusStore } from \"./SmoothContext\";\nimport { writableStore } from \"../../context/ReadonlyStore\";\n\n/**\n * Tuning options for the smooth text streaming animation.\n */\nexport type SmoothOptions = {\n /**\n * Target time in milliseconds to drain the backlog of unrevealed\n * characters. Larger values reveal long backlogs more gradually.\n * @default 250\n */\n drainMs?: number | undefined;\n /**\n * Maximum time in milliseconds between revealed characters, i.e. the\n * slowest reveal rate when the backlog is short.\n * @default 5\n */\n maxCharIntervalMs?: number | undefined;\n /**\n * Maximum number of characters revealed per animation frame.\n * @default Infinity\n */\n maxCharsPerFrame?: number | undefined;\n /**\n * Minimum time in milliseconds between committed updates. The reveal keeps\n * advancing every frame, but the visible text (and the downstream re-render\n * and markdown re-parse it triggers) is committed at most once per interval.\n * The final frame always commits. `0` commits every frame.\n * @default 0\n */\n minCommitMs?: number | undefined;\n};\n\nconst DEFAULT_DRAIN_MS = 250;\nconst DEFAULT_MAX_CHAR_INTERVAL_MS = 5;\n\nclass TextStreamAnimator {\n private animationFrameId: number | null = null;\n private lastUpdateTime: number = 0;\n public lastCommitTime: number = -Infinity;\n\n public targetText: string = \"\";\n public drainMs: number = DEFAULT_DRAIN_MS;\n public maxCharIntervalMs: number = DEFAULT_MAX_CHAR_INTERVAL_MS;\n public maxCharsPerFrame: number = Infinity;\n public minCommitMs: number = 0;\n\n public currentText: string;\n private setText: (newText: string) => void;\n\n constructor(currentText: string, setText: (newText: string) => void) {\n this.currentText = currentText;\n this.setText = setText;\n }\n\n start() {\n if (this.animationFrameId !== null) return;\n this.lastUpdateTime = performance.now();\n this.animate();\n }\n\n stop() {\n if (this.animationFrameId !== null) {\n cancelAnimationFrame(this.animationFrameId);\n this.animationFrameId = null;\n }\n }\n\n private animate = () => {\n const currentTime = performance.now();\n const deltaTime = currentTime - this.lastUpdateTime;\n let timeToConsume = deltaTime;\n\n const remainingChars = this.targetText.length - this.currentText.length;\n const baseTimePerChar = Math.min(\n this.maxCharIntervalMs,\n this.drainMs / remainingChars,\n );\n\n const frameLimit = Math.min(remainingChars, this.maxCharsPerFrame);\n let charsToAdd = 0;\n while (timeToConsume >= baseTimePerChar && charsToAdd < frameLimit) {\n charsToAdd++;\n timeToConsume -= baseTimePerChar;\n }\n // A cap-limited frame must not bank its surplus time, or the next\n // frame would burst past the cap.\n if (charsToAdd === frameLimit && frameLimit === this.maxCharsPerFrame) {\n timeToConsume = 0;\n }\n\n if (charsToAdd !== remainingChars) {\n this.animationFrameId = requestAnimationFrame(this.animate);\n } else {\n this.animationFrameId = null;\n }\n if (charsToAdd === 0) return;\n\n this.currentText = this.targetText.slice(\n 0,\n this.currentText.length + charsToAdd,\n );\n this.lastUpdateTime = currentTime - timeToConsume;\n\n const isComplete = charsToAdd === remainingChars;\n if (isComplete || currentTime - this.lastCommitTime >= this.minCommitMs) {\n this.lastCommitTime = currentTime;\n this.setText(this.currentText);\n }\n };\n}\n\nconst SMOOTH_STATUS: MessagePartStatus = Object.freeze({\n type: \"running\",\n});\n\nconst positiveOr = (value: number | undefined, fallback: number): number =>\n value !== undefined && value > 0 ? value : fallback;\n\n/**\n * Animates streamed message part text with a typewriter-style reveal.\n *\n * Takes the current part state and a `smooth` argument: `false` disables,\n * `true` uses the default rate, and a {@link SmoothOptions} object tunes\n * the reveal. Returns the part state with `text` replaced by the revealed\n * prefix and `status` reporting `running` until the reveal catches up.\n * If the source settles before any character has been revealed, the text\n * is committed immediately so a missed animation frame cannot leave an\n * empty bubble.\n *\n * The reveal auto-disables under `prefers-reduced-motion: reduce`,\n * committing the full text immediately; this takes precedence over an\n * explicit `smooth={true}`.\n *\n * @example\n * ```tsx\n * const { text, status } = useSmooth(useMessagePartText(), {\n * drainMs: 500,\n * maxCharsPerFrame: 30,\n * });\n * ```\n */\nexport const useSmooth = (\n state: MessagePartState & (TextMessagePart | ReasoningMessagePart),\n smooth: boolean | SmoothOptions = false,\n): MessagePartState & (TextMessagePart | ReasoningMessagePart) => {\n const { text } = state;\n const reduceMotion = useMediaQuery(\"(prefers-reduced-motion: reduce)\");\n const options =\n typeof smooth === \"object\" && smooth !== null ? smooth : undefined;\n const enabled = smooth !== false && smooth !== null && !reduceMotion;\n const drainMs = positiveOr(options?.drainMs, DEFAULT_DRAIN_MS);\n const maxCharIntervalMs = positiveOr(\n options?.maxCharIntervalMs,\n DEFAULT_MAX_CHAR_INTERVAL_MS,\n );\n const maxCharsPerFrame = positiveOr(options?.maxCharsPerFrame, Infinity);\n const minCommitMs = positiveOr(options?.minCommitMs, 0);\n\n const [displayedText, setDisplayedText] = useState(\n state.status.type === \"running\" ? \"\" : text,\n );\n\n // Render-phase resync on part flip or text discontinuity, so the\n // first paint after a thread switch never shows the previous\n // part's text (#4051). `displayedText` is already a prefix of\n // `text` during normal streaming, so use it as the previous-text\n // reference instead of carrying separate state — avoids the\n // double render per streaming token. Read part identity through\n // `useAuiState` so we actually subscribe to its changes instead\n // of relying on a render-time proxy reference that may be stable\n // across thread swaps.\n const aui = useAui();\n const part = useAuiState(() => aui.part);\n const [prevPart, setPrevPart] = useState(part);\n if (part !== prevPart || !text.startsWith(displayedText)) {\n setPrevPart(part);\n setDisplayedText(state.status.type === \"running\" ? \"\" : text);\n }\n\n const smoothStatusStore = useSmoothStatusStore({ optional: true });\n const setText = useCallbackRef((text: string) => {\n setDisplayedText(text);\n if (smoothStatusStore) {\n const target =\n displayedText !== text || state.status.type === \"running\"\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n });\n\n // TODO this is hacky\n useEffect(() => {\n if (smoothStatusStore) {\n const target =\n enabled && (displayedText !== text || state.status.type === \"running\")\n ? SMOOTH_STATUS\n : state.status;\n writableStore(smoothStatusStore).setState(target, true);\n }\n }, [smoothStatusStore, enabled, text, displayedText, state.status]);\n\n const [animatorRef] = useState(\n () => new TextStreamAnimator(displayedText, setText),\n );\n const [prevEnabled, setPrevEnabled] = useState(enabled);\n if (enabled !== prevEnabled) {\n setPrevEnabled(enabled);\n if (\n enabled &&\n part === prevPart &&\n text.startsWith(animatorRef.currentText)\n ) {\n setDisplayedText(animatorRef.currentText);\n }\n }\n\n useEffect(() => {\n animatorRef.drainMs = drainMs;\n animatorRef.maxCharIntervalMs = maxCharIntervalMs;\n animatorRef.maxCharsPerFrame = maxCharsPerFrame;\n animatorRef.minCommitMs = minCommitMs;\n }, [animatorRef, drainMs, maxCharIntervalMs, maxCharsPerFrame, minCommitMs]);\n\n const animatorPartRef = useRef(part);\n useEffect(() => {\n const partChanged = animatorPartRef.current !== part;\n animatorPartRef.current = part;\n if (!enabled) {\n animatorRef.stop();\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = -Infinity;\n return;\n }\n\n // A new part whose text shares a prefix with the previous target would\n // keep the stale cursor and flicker without this reset.\n if (partChanged || !text.startsWith(animatorRef.targetText)) {\n if (state.status.type === \"running\") {\n animatorRef.currentText = \"\";\n animatorRef.targetText = text;\n animatorRef.lastCommitTime = -Infinity;\n animatorRef.start();\n } else {\n animatorRef.currentText = text;\n animatorRef.targetText = text;\n animatorRef.stop();\n setText(text);\n }\n return;\n }\n\n animatorRef.targetText = text;\n if (state.status.type !== \"running\") {\n // No character has painted. A pending frame that never runs would\n // leave an empty bubble after settle.\n if (animatorRef.currentText === \"\") {\n animatorRef.currentText = text;\n animatorRef.stop();\n setText(text);\n return;\n }\n animatorRef.start();\n return;\n }\n\n animatorRef.start();\n }, [animatorRef, enabled, text, state.status.type, part, setText]);\n\n useEffect(() => {\n return () => {\n animatorRef.stop();\n };\n }, [animatorRef]);\n\n return useMemo(\n () =>\n enabled\n ? {\n ...state,\n text: displayedText,\n status: text === displayedText ? state.status : SMOOTH_STATUS,\n }\n : state,\n [enabled, displayedText, state, text],\n );\n};\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { useEffect, useLayoutEffect } from "@assistant-ui/tap/react-shim";
2
2
  const useIsomorphicLayoutEffect = typeof globalThis.window !== "undefined" ? useLayoutEffect : useEffect;
3
- //#endregion
4
3
  export { useIsomorphicLayoutEffect };
5
4
 
6
5
  //# sourceMappingURL=useIsomorphicLayoutEffect.js.map