@assistant-ui/react 0.15.31 → 0.15.33

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 (228) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -2
  2. package/dist/adapters/GeminiLiveVoiceAdapter.d.ts +26 -0
  3. package/dist/adapters/GeminiLiveVoiceAdapter.d.ts.map +1 -0
  4. package/dist/adapters/GeminiLiveVoiceAdapter.js +346 -0
  5. package/dist/adapters/GeminiLiveVoiceAdapter.js.map +1 -0
  6. package/dist/adapters/OpenAIRealtimeVoiceAdapter.js +1 -2
  7. package/dist/adapters/gemini-live/audio.d.ts +27 -0
  8. package/dist/adapters/gemini-live/audio.d.ts.map +1 -0
  9. package/dist/adapters/gemini-live/audio.js +291 -0
  10. package/dist/adapters/gemini-live/audio.js.map +1 -0
  11. package/dist/assistant-transport.js +1 -2
  12. package/dist/cloud-renderer/CloudRendererHost.js +1 -2
  13. package/dist/context/ReadonlyStore.js +1 -2
  14. package/dist/context/providers/MessageProvider.js +1 -2
  15. package/dist/context/providers/ThreadViewportProvider.js +1 -2
  16. package/dist/context/react/ThreadViewportContext.js +1 -2
  17. package/dist/context/react/utils/createContextHook.js +1 -2
  18. package/dist/context/react/utils/createContextStoreHook.js +1 -2
  19. package/dist/context/stores/ThreadViewport.js +2 -3
  20. package/dist/devtools/DevToolsHooks.js +1 -2
  21. package/dist/hooks/useMessageQuote.js +1 -2
  22. package/dist/hooks/useMessageTiming.js +1 -2
  23. package/dist/hooks/useToolCallElapsed.js +1 -2
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/internal.js +2 -3
  28. package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -2
  29. package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  30. package/dist/mcp-apps/McpAppRenderer.js +4 -4
  31. package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
  32. package/dist/mcp-apps/McpAppsRemoteHost.js +1 -2
  33. package/dist/mcp-apps/app-frame.js +2 -3
  34. package/dist/mcp-apps/bridge.js +1 -2
  35. package/dist/mcp-apps/csp.js +1 -2
  36. package/dist/mcp-apps/types.js +1 -2
  37. package/dist/mcp-apps/utils.js +1 -2
  38. package/dist/model-context/frame/useAssistantFrameHost.js +1 -2
  39. package/dist/model-context/makeAssistantVisible.js +1 -2
  40. package/dist/primitives/actionBar/ActionBarCopy.js +1 -2
  41. package/dist/primitives/actionBar/ActionBarEdit.js +1 -2
  42. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -2
  43. package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -2
  44. package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -2
  45. package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -2
  46. package/dist/primitives/actionBar/ActionBarReload.js +1 -2
  47. package/dist/primitives/actionBar/ActionBarRoot.js +1 -2
  48. package/dist/primitives/actionBar/ActionBarSpeak.js +1 -2
  49. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -2
  50. package/dist/primitives/actionBar/useActionBarFloatStatus.js +1 -2
  51. package/dist/primitives/actionBar.js +1 -2
  52. package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -2
  53. package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -2
  54. package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -2
  55. package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -2
  56. package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -2
  57. package/dist/primitives/actionBarMore/scope.js +1 -2
  58. package/dist/primitives/actionBarMore.js +1 -2
  59. package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -2
  60. package/dist/primitives/assistantModal/AssistantModalContent.js +1 -2
  61. package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -2
  62. package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -2
  63. package/dist/primitives/assistantModal/popoverRenderPrimitives.js +1 -2
  64. package/dist/primitives/assistantModal/scope.js +1 -2
  65. package/dist/primitives/assistantModal.js +1 -2
  66. package/dist/primitives/attachment/AttachmentName.js +1 -2
  67. package/dist/primitives/attachment/AttachmentRemove.js +1 -2
  68. package/dist/primitives/attachment/AttachmentRoot.js +1 -2
  69. package/dist/primitives/attachment/AttachmentThumb.js +1 -2
  70. package/dist/primitives/attachment.js +1 -2
  71. package/dist/primitives/branchPicker/BranchPickerCount.js +1 -2
  72. package/dist/primitives/branchPicker/BranchPickerNext.js +1 -2
  73. package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -2
  74. package/dist/primitives/branchPicker/BranchPickerPrevious.js +1 -2
  75. package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -2
  76. package/dist/primitives/branchPicker.js +1 -2
  77. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +5 -4
  78. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  79. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +57 -20
  80. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  81. package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -2
  82. package/dist/primitives/chainOfThought.js +1 -2
  83. package/dist/primitives/composer/ComposerAddAttachment.js +1 -2
  84. package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -2
  85. package/dist/primitives/composer/ComposerCancel.js +1 -2
  86. package/dist/primitives/composer/ComposerCompactContext.js +1 -2
  87. package/dist/primitives/composer/ComposerDictate.js +1 -2
  88. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -2
  89. package/dist/primitives/composer/ComposerInput.js +1 -2
  90. package/dist/primitives/composer/ComposerInputPluginContext.js +1 -2
  91. package/dist/primitives/composer/ComposerQuote.js +1 -2
  92. package/dist/primitives/composer/ComposerResume.js +1 -2
  93. package/dist/primitives/composer/ComposerRoot.js +1 -2
  94. package/dist/primitives/composer/ComposerSend.js +1 -2
  95. package/dist/primitives/composer/ComposerStopDictation.js +1 -2
  96. package/dist/primitives/composer/composerInputSelector.js +1 -2
  97. package/dist/primitives/composer/trigger/TriggerPopover.js +1 -2
  98. package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -2
  99. package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -2
  100. package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -2
  101. package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -2
  102. package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -2
  103. package/dist/primitives/composer/trigger/TriggerPopoverResource.js +1 -2
  104. package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -2
  105. package/dist/primitives/composer/trigger/detectTrigger.js +1 -2
  106. package/dist/primitives/composer/trigger/index.js +1 -2
  107. package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js +1 -2
  108. package/dist/primitives/composer/trigger/triggerDetectionResource.js +1 -2
  109. package/dist/primitives/composer/trigger/triggerKeyboardResource.js +1 -2
  110. package/dist/primitives/composer/trigger/triggerNavigationResource.js +1 -2
  111. package/dist/primitives/composer/trigger/triggerSelectionResource.js +1 -2
  112. package/dist/primitives/composer/useComposerCancelWithFocus.js +1 -2
  113. package/dist/primitives/composer/useComposerInputState.js +1 -2
  114. package/dist/primitives/composer.js +1 -2
  115. package/dist/primitives/dropdownMenuRenderPrimitives.js +1 -2
  116. package/dist/primitives/error/ErrorMessage.js +1 -2
  117. package/dist/primitives/error/ErrorRoot.js +1 -2
  118. package/dist/primitives/error.js +1 -2
  119. package/dist/primitives/message/MessageError.js +1 -2
  120. package/dist/primitives/message/MessageIf.js +1 -2
  121. package/dist/primitives/message/MessageParts.js +1 -2
  122. package/dist/primitives/message/MessagePartsGrouped.js +2 -3
  123. package/dist/primitives/message/MessageRoot.js +1 -2
  124. package/dist/primitives/message.js +1 -2
  125. package/dist/primitives/messagePart/MessagePartImage.js +1 -2
  126. package/dist/primitives/messagePart/MessagePartText.js +1 -2
  127. package/dist/primitives/messagePart/useMessagePartData.js +1 -2
  128. package/dist/primitives/messagePart/useMessagePartFile.js +1 -2
  129. package/dist/primitives/messagePart/useMessagePartImage.js +1 -2
  130. package/dist/primitives/messagePart/useMessagePartReasoning.js +1 -2
  131. package/dist/primitives/messagePart/useMessagePartSource.js +1 -2
  132. package/dist/primitives/messagePart/useMessagePartText.js +1 -2
  133. package/dist/primitives/messagePart.js +1 -2
  134. package/dist/primitives/queueItem/QueueItemRemove.js +1 -2
  135. package/dist/primitives/queueItem/QueueItemSteer.js +1 -2
  136. package/dist/primitives/queueItem/QueueItemText.js +1 -2
  137. package/dist/primitives/queueItem.js +1 -2
  138. package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
  139. package/dist/primitives/reasoning/useScrollLock.js +41 -25
  140. package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
  141. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -2
  142. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -2
  143. package/dist/primitives/selectionToolbar.js +1 -2
  144. package/dist/primitives/suggestion/SuggestionDescription.js +1 -2
  145. package/dist/primitives/suggestion/SuggestionTitle.js +1 -2
  146. package/dist/primitives/suggestion/SuggestionTrigger.js +1 -2
  147. package/dist/primitives/suggestion.js +1 -2
  148. package/dist/primitives/thread/ThreadEmpty.js +1 -2
  149. package/dist/primitives/thread/ThreadIf.js +1 -2
  150. package/dist/primitives/thread/ThreadLoadEarlier.js +1 -2
  151. package/dist/primitives/thread/ThreadRoot.js +1 -2
  152. package/dist/primitives/thread/ThreadRootElementContext.js +1 -2
  153. package/dist/primitives/thread/ThreadScrollToBottom.js +1 -2
  154. package/dist/primitives/thread/ThreadSuggestion.js +1 -2
  155. package/dist/primitives/thread/ThreadViewport.js +1 -2
  156. package/dist/primitives/thread/ThreadViewportFooter.js +1 -2
  157. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js +1 -2
  158. package/dist/primitives/thread/topAnchor/createReserveObservers.js +1 -2
  159. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +1 -2
  160. package/dist/primitives/thread/topAnchor/topAnchorTurn.js +1 -2
  161. package/dist/primitives/thread/topAnchor/topAnchorUtils.js +1 -2
  162. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -2
  163. package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -2
  164. package/dist/primitives/thread.js +1 -2
  165. package/dist/primitives/threadList/ThreadListLoadMore.js +1 -2
  166. package/dist/primitives/threadList/ThreadListNew.js +1 -2
  167. package/dist/primitives/threadList/ThreadListRoot.js +1 -2
  168. package/dist/primitives/threadList.js +1 -2
  169. package/dist/primitives/threadListFocusGroup.js +1 -2
  170. package/dist/primitives/threadListItem/ThreadListItemArchive.js +1 -2
  171. package/dist/primitives/threadListItem/ThreadListItemDelete.js +1 -2
  172. package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
  173. package/dist/primitives/threadListItem/ThreadListItemRoot.js +2 -3
  174. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  175. package/dist/primitives/threadListItem/ThreadListItemTrigger.js +1 -2
  176. package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +1 -2
  177. package/dist/primitives/threadListItem.js +1 -2
  178. package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -2
  179. package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -2
  180. package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +1 -2
  181. package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -2
  182. package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -2
  183. package/dist/primitives/threadListItemMore/scope.js +1 -2
  184. package/dist/primitives/threadListItemMore.js +1 -2
  185. package/dist/sandbox-host/SandboxHost.js +2 -3
  186. package/dist/unstable/useComposerInput.js +1 -2
  187. package/dist/unstable/useComposerInputHistory.js +2 -3
  188. package/dist/unstable/useLiveCompletionAdapter.js +1 -2
  189. package/dist/unstable/useMentionAdapter.js +1 -2
  190. package/dist/unstable/useMessageStallDetection.js +1 -2
  191. package/dist/unstable/useModelContextSnapshot.js +1 -2
  192. package/dist/unstable/useSlashCommandAdapter.js +1 -2
  193. package/dist/unstable/webmcp/WebMcpRegistrationResource.js +1 -2
  194. package/dist/unstable/webmcp/convertTools.js +1 -2
  195. package/dist/unstable/webmcp/useWebMcpProvider.js +1 -2
  196. package/dist/unstable/webmcp/webmcp-host.js +1 -2
  197. package/dist/utils/Primitive.js +1 -2
  198. package/dist/utils/createActionButton.js +1 -2
  199. package/dist/utils/getSelectionMessageId.js +1 -2
  200. package/dist/utils/hooks/useManagedRef.js +1 -2
  201. package/dist/utils/hooks/useMediaQuery.js +1 -2
  202. package/dist/utils/hooks/useOnScrollToBottom.js +1 -2
  203. package/dist/utils/hooks/useSizeHandle.js +1 -2
  204. package/dist/utils/isCompositionKey.js +1 -2
  205. package/dist/utils/smooth/SmoothContext.js +1 -2
  206. package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
  207. package/dist/utils/smooth/useSmooth.js +11 -4
  208. package/dist/utils/smooth/useSmooth.js.map +1 -1
  209. package/dist/utils/useIsomorphicLayoutEffect.js +0 -1
  210. package/package.json +8 -8
  211. package/src/adapters/GeminiLiveVoiceAdapter.test.ts +992 -0
  212. package/src/adapters/GeminiLiveVoiceAdapter.ts +454 -0
  213. package/src/adapters/gemini-live/audio.test.ts +880 -0
  214. package/src/adapters/gemini-live/audio.ts +333 -0
  215. package/src/index.test.ts +34 -0
  216. package/src/index.ts +4 -0
  217. package/src/mcp-apps/McpAppRenderer.composer.test.tsx +111 -0
  218. package/src/mcp-apps/McpAppRenderer.test.tsx +24 -23
  219. package/src/mcp-apps/McpAppRenderer.tsx +9 -1
  220. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.test.tsx +91 -0
  221. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +54 -0
  222. package/src/primitives/reasoning/useScrollLock.test.tsx +71 -2
  223. package/src/primitives/reasoning/useScrollLock.ts +78 -51
  224. package/src/primitives/threadListItem/ThreadListItemRoot.tsx +4 -1
  225. package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +25 -0
  226. package/src/utils/smooth/useSmooth.test.tsx +113 -4
  227. package/src/utils/smooth/useSmooth.ts +16 -2
  228. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.ts +0 -49
@@ -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":"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"}
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.15.31",
3
+ "version": "0.15.33",
4
4
  "description": "Open-source TypeScript/React library for building production-grade AI chat experiences",
5
5
  "keywords": [
6
6
  "ai",
@@ -55,16 +55,16 @@
55
55
  ],
56
56
  "sideEffects": false,
57
57
  "dependencies": {
58
- "@assistant-ui/core": "^0.3.31",
59
- "@assistant-ui/store": "^0.3.22",
60
- "@assistant-ui/tap": "^0.9.24",
61
- "assistant-cloud": "^0.2.8",
62
- "assistant-stream": "^0.3.54",
58
+ "@assistant-ui/core": "^0.3.33",
59
+ "@assistant-ui/store": "^0.3.23",
60
+ "@assistant-ui/tap": "^0.9.25",
61
+ "assistant-cloud": "^0.2.10",
62
+ "assistant-stream": "^0.3.56",
63
63
  "radix-ui": "^1.8.1",
64
64
  "react-textarea-autosize": "^8.5.9",
65
65
  "safe-content-frame": "^0.0.34",
66
66
  "zod": "^4.6.7",
67
- "zustand": "^5.0.15"
67
+ "zustand": "^5.0.16"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "@types/react": "*",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  "devDependencies": {
84
84
  "@assistant-ui/vite": "0.0.21",
85
- "@assistant-ui/x-buildutils": "0.0.31",
85
+ "@assistant-ui/x-buildutils": "0.0.32",
86
86
  "@assistant-ui/x-react18": "0.0.0",
87
87
  "@testing-library/react": "^16.3.3",
88
88
  "@types/json-schema": "^7.0.15",