@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.
- package/dist/_virtual/_rolldown/runtime.js +1 -2
- package/dist/adapters/GeminiLiveVoiceAdapter.d.ts +26 -0
- package/dist/adapters/GeminiLiveVoiceAdapter.d.ts.map +1 -0
- package/dist/adapters/GeminiLiveVoiceAdapter.js +346 -0
- package/dist/adapters/GeminiLiveVoiceAdapter.js.map +1 -0
- package/dist/adapters/OpenAIRealtimeVoiceAdapter.js +1 -2
- package/dist/adapters/gemini-live/audio.d.ts +27 -0
- package/dist/adapters/gemini-live/audio.d.ts.map +1 -0
- package/dist/adapters/gemini-live/audio.js +291 -0
- package/dist/adapters/gemini-live/audio.js.map +1 -0
- package/dist/assistant-transport.js +1 -2
- package/dist/cloud-renderer/CloudRendererHost.js +1 -2
- package/dist/context/ReadonlyStore.js +1 -2
- package/dist/context/providers/MessageProvider.js +1 -2
- package/dist/context/providers/ThreadViewportProvider.js +1 -2
- package/dist/context/react/ThreadViewportContext.js +1 -2
- package/dist/context/react/utils/createContextHook.js +1 -2
- package/dist/context/react/utils/createContextStoreHook.js +1 -2
- package/dist/context/stores/ThreadViewport.js +2 -3
- package/dist/devtools/DevToolsHooks.js +1 -2
- package/dist/hooks/useMessageQuote.js +1 -2
- package/dist/hooks/useMessageTiming.js +1 -2
- package/dist/hooks/useToolCallElapsed.js +1 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/internal.js +2 -3
- package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -2
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +4 -4
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js +1 -2
- package/dist/mcp-apps/app-frame.js +2 -3
- package/dist/mcp-apps/bridge.js +1 -2
- package/dist/mcp-apps/csp.js +1 -2
- package/dist/mcp-apps/types.js +1 -2
- package/dist/mcp-apps/utils.js +1 -2
- package/dist/model-context/frame/useAssistantFrameHost.js +1 -2
- package/dist/model-context/makeAssistantVisible.js +1 -2
- package/dist/primitives/actionBar/ActionBarCopy.js +1 -2
- package/dist/primitives/actionBar/ActionBarEdit.js +1 -2
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -2
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -2
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -2
- package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -2
- package/dist/primitives/actionBar/ActionBarReload.js +1 -2
- package/dist/primitives/actionBar/ActionBarRoot.js +1 -2
- package/dist/primitives/actionBar/ActionBarSpeak.js +1 -2
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -2
- package/dist/primitives/actionBar/useActionBarFloatStatus.js +1 -2
- package/dist/primitives/actionBar.js +1 -2
- package/dist/primitives/actionBarMore/ActionBarMoreContent.js +1 -2
- package/dist/primitives/actionBarMore/ActionBarMoreItem.js +1 -2
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.js +1 -2
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js +1 -2
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js +1 -2
- package/dist/primitives/actionBarMore/scope.js +1 -2
- package/dist/primitives/actionBarMore.js +1 -2
- package/dist/primitives/assistantModal/AssistantModalAnchor.js +1 -2
- package/dist/primitives/assistantModal/AssistantModalContent.js +1 -2
- package/dist/primitives/assistantModal/AssistantModalRoot.js +1 -2
- package/dist/primitives/assistantModal/AssistantModalTrigger.js +1 -2
- package/dist/primitives/assistantModal/popoverRenderPrimitives.js +1 -2
- package/dist/primitives/assistantModal/scope.js +1 -2
- package/dist/primitives/assistantModal.js +1 -2
- package/dist/primitives/attachment/AttachmentName.js +1 -2
- package/dist/primitives/attachment/AttachmentRemove.js +1 -2
- package/dist/primitives/attachment/AttachmentRoot.js +1 -2
- package/dist/primitives/attachment/AttachmentThumb.js +1 -2
- package/dist/primitives/attachment.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerCount.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerNext.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerPrevious.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -2
- package/dist/primitives/branchPicker.js +1 -2
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +5 -4
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +57 -20
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -2
- package/dist/primitives/chainOfThought.js +1 -2
- package/dist/primitives/composer/ComposerAddAttachment.js +1 -2
- package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -2
- package/dist/primitives/composer/ComposerCancel.js +1 -2
- package/dist/primitives/composer/ComposerCompactContext.js +1 -2
- package/dist/primitives/composer/ComposerDictate.js +1 -2
- package/dist/primitives/composer/ComposerDictationTranscript.js +1 -2
- package/dist/primitives/composer/ComposerInput.js +1 -2
- package/dist/primitives/composer/ComposerInputPluginContext.js +1 -2
- package/dist/primitives/composer/ComposerQuote.js +1 -2
- package/dist/primitives/composer/ComposerResume.js +1 -2
- package/dist/primitives/composer/ComposerRoot.js +1 -2
- package/dist/primitives/composer/ComposerSend.js +1 -2
- package/dist/primitives/composer/ComposerStopDictation.js +1 -2
- package/dist/primitives/composer/composerInputSelector.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopover.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +1 -2
- package/dist/primitives/composer/trigger/detectTrigger.js +1 -2
- package/dist/primitives/composer/trigger/index.js +1 -2
- package/dist/primitives/composer/trigger/matchesTriggerItemQuery.js +1 -2
- package/dist/primitives/composer/trigger/triggerDetectionResource.js +1 -2
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js +1 -2
- package/dist/primitives/composer/trigger/triggerNavigationResource.js +1 -2
- package/dist/primitives/composer/trigger/triggerSelectionResource.js +1 -2
- package/dist/primitives/composer/useComposerCancelWithFocus.js +1 -2
- package/dist/primitives/composer/useComposerInputState.js +1 -2
- package/dist/primitives/composer.js +1 -2
- package/dist/primitives/dropdownMenuRenderPrimitives.js +1 -2
- package/dist/primitives/error/ErrorMessage.js +1 -2
- package/dist/primitives/error/ErrorRoot.js +1 -2
- package/dist/primitives/error.js +1 -2
- package/dist/primitives/message/MessageError.js +1 -2
- package/dist/primitives/message/MessageIf.js +1 -2
- package/dist/primitives/message/MessageParts.js +1 -2
- package/dist/primitives/message/MessagePartsGrouped.js +2 -3
- package/dist/primitives/message/MessageRoot.js +1 -2
- package/dist/primitives/message.js +1 -2
- package/dist/primitives/messagePart/MessagePartImage.js +1 -2
- package/dist/primitives/messagePart/MessagePartText.js +1 -2
- package/dist/primitives/messagePart/useMessagePartData.js +1 -2
- package/dist/primitives/messagePart/useMessagePartFile.js +1 -2
- package/dist/primitives/messagePart/useMessagePartImage.js +1 -2
- package/dist/primitives/messagePart/useMessagePartReasoning.js +1 -2
- package/dist/primitives/messagePart/useMessagePartSource.js +1 -2
- package/dist/primitives/messagePart/useMessagePartText.js +1 -2
- package/dist/primitives/messagePart.js +1 -2
- package/dist/primitives/queueItem/QueueItemRemove.js +1 -2
- package/dist/primitives/queueItem/QueueItemSteer.js +1 -2
- package/dist/primitives/queueItem/QueueItemText.js +1 -2
- package/dist/primitives/queueItem.js +1 -2
- package/dist/primitives/reasoning/useScrollLock.d.ts.map +1 -1
- package/dist/primitives/reasoning/useScrollLock.js +41 -25
- package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -2
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -2
- package/dist/primitives/selectionToolbar.js +1 -2
- package/dist/primitives/suggestion/SuggestionDescription.js +1 -2
- package/dist/primitives/suggestion/SuggestionTitle.js +1 -2
- package/dist/primitives/suggestion/SuggestionTrigger.js +1 -2
- package/dist/primitives/suggestion.js +1 -2
- package/dist/primitives/thread/ThreadEmpty.js +1 -2
- package/dist/primitives/thread/ThreadIf.js +1 -2
- package/dist/primitives/thread/ThreadLoadEarlier.js +1 -2
- package/dist/primitives/thread/ThreadRoot.js +1 -2
- package/dist/primitives/thread/ThreadRootElementContext.js +1 -2
- package/dist/primitives/thread/ThreadScrollToBottom.js +1 -2
- package/dist/primitives/thread/ThreadSuggestion.js +1 -2
- package/dist/primitives/thread/ThreadViewport.js +1 -2
- package/dist/primitives/thread/ThreadViewportFooter.js +1 -2
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js +1 -2
- package/dist/primitives/thread/topAnchor/createReserveObservers.js +1 -2
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +1 -2
- package/dist/primitives/thread/topAnchor/topAnchorTurn.js +1 -2
- package/dist/primitives/thread/topAnchor/topAnchorUtils.js +1 -2
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +1 -2
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +1 -2
- package/dist/primitives/thread.js +1 -2
- package/dist/primitives/threadList/ThreadListLoadMore.js +1 -2
- package/dist/primitives/threadList/ThreadListNew.js +1 -2
- package/dist/primitives/threadList/ThreadListRoot.js +1 -2
- package/dist/primitives/threadList.js +1 -2
- package/dist/primitives/threadListFocusGroup.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemArchive.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemDelete.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js +2 -3
- package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +1 -2
- package/dist/primitives/threadListItem.js +1 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js +1 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js +1 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js +1 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js +1 -2
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js +1 -2
- package/dist/primitives/threadListItemMore/scope.js +1 -2
- package/dist/primitives/threadListItemMore.js +1 -2
- package/dist/sandbox-host/SandboxHost.js +2 -3
- package/dist/unstable/useComposerInput.js +1 -2
- package/dist/unstable/useComposerInputHistory.js +2 -3
- package/dist/unstable/useLiveCompletionAdapter.js +1 -2
- package/dist/unstable/useMentionAdapter.js +1 -2
- package/dist/unstable/useMessageStallDetection.js +1 -2
- package/dist/unstable/useModelContextSnapshot.js +1 -2
- package/dist/unstable/useSlashCommandAdapter.js +1 -2
- package/dist/unstable/webmcp/WebMcpRegistrationResource.js +1 -2
- package/dist/unstable/webmcp/convertTools.js +1 -2
- package/dist/unstable/webmcp/useWebMcpProvider.js +1 -2
- package/dist/unstable/webmcp/webmcp-host.js +1 -2
- package/dist/utils/Primitive.js +1 -2
- package/dist/utils/createActionButton.js +1 -2
- package/dist/utils/getSelectionMessageId.js +1 -2
- package/dist/utils/hooks/useManagedRef.js +1 -2
- package/dist/utils/hooks/useMediaQuery.js +1 -2
- package/dist/utils/hooks/useOnScrollToBottom.js +1 -2
- package/dist/utils/hooks/useSizeHandle.js +1 -2
- package/dist/utils/isCompositionKey.js +1 -2
- package/dist/utils/smooth/SmoothContext.js +1 -2
- package/dist/utils/smooth/useSmooth.d.ts.map +1 -1
- package/dist/utils/smooth/useSmooth.js +11 -4
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/dist/utils/useIsomorphicLayoutEffect.js +0 -1
- package/package.json +8 -8
- package/src/adapters/GeminiLiveVoiceAdapter.test.ts +992 -0
- package/src/adapters/GeminiLiveVoiceAdapter.ts +454 -0
- package/src/adapters/gemini-live/audio.test.ts +880 -0
- package/src/adapters/gemini-live/audio.ts +333 -0
- package/src/index.test.ts +34 -0
- package/src/index.ts +4 -0
- package/src/mcp-apps/McpAppRenderer.composer.test.tsx +111 -0
- package/src/mcp-apps/McpAppRenderer.test.tsx +24 -23
- package/src/mcp-apps/McpAppRenderer.tsx +9 -1
- package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.test.tsx +91 -0
- package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +54 -0
- package/src/primitives/reasoning/useScrollLock.test.tsx +71 -2
- package/src/primitives/reasoning/useScrollLock.ts +78 -51
- package/src/primitives/threadListItem/ThreadListItemRoot.tsx +4 -1
- package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +25 -0
- package/src/utils/smooth/useSmooth.test.tsx +113 -4
- package/src/utils/smooth/useSmooth.ts +16 -2
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/dist/utils/Primitive.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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
|
-
|
|
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,
|
|
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
|
-
|
|
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.
|
|
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.
|
|
59
|
-
"@assistant-ui/store": "^0.3.
|
|
60
|
-
"@assistant-ui/tap": "^0.9.
|
|
61
|
-
"assistant-cloud": "^0.2.
|
|
62
|
-
"assistant-stream": "^0.3.
|
|
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.
|
|
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.
|
|
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",
|