@assistant-ui/react 0.15.30 → 0.15.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.js +1 -2
- package/dist/adapters/OpenAIRealtimeVoiceAdapter.js +1 -2
- package/dist/assistant-transport.js +1 -2
- package/dist/cloud-renderer/CloudRendererHost.d.ts.map +1 -1
- package/dist/cloud-renderer/CloudRendererHost.js +2 -4
- package/dist/cloud-renderer/CloudRendererHost.js.map +1 -1
- package/dist/context/ReadonlyStore.js +1 -2
- package/dist/context/providers/AttachmentByIndexProvider.js +1 -2
- package/dist/context/providers/ChainOfThoughtByIndicesProvider.js +1 -2
- package/dist/context/providers/MessageByIndexProvider.js +1 -2
- package/dist/context/providers/MessageProvider.js +1 -2
- package/dist/context/providers/PartByIndexProvider.js +1 -2
- package/dist/context/providers/SuggestionByIndexProvider.js +1 -2
- package/dist/context/providers/TextMessagePartProvider.js +1 -2
- package/dist/context/providers/ThreadListItemProvider.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 +1 -2
- 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 +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -3
- package/dist/internal.js.map +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -2
- package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.js +3 -3
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/mcp-apps/McpAppsRemoteHost.js +1 -2
- package/dist/mcp-apps/app-frame.js +1 -2
- 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.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js +1 -2
- package/dist/primitives/actionBar/ActionBarEdit.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js +1 -2
- package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js +1 -2
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js +1 -2
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js +1 -2
- package/dist/primitives/actionBar/ActionBarInteractionContext.js +1 -2
- package/dist/primitives/actionBar/ActionBarReload.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js +1 -2
- package/dist/primitives/actionBar/ActionBarRoot.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarRoot.js +1 -2
- package/dist/primitives/actionBar/ActionBarSpeak.d.ts +1 -1
- package/dist/primitives/actionBar/ActionBarSpeak.js +1 -2
- package/dist/primitives/actionBar/ActionBarStopSpeaking.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/attachment/AttachmentRemove.js +1 -2
- package/dist/primitives/attachment/AttachmentRoot.d.ts +1 -1
- package/dist/primitives/attachment/AttachmentRoot.js +1 -2
- package/dist/primitives/attachment/AttachmentThumb.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerPrevious.d.ts +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.js +1 -2
- package/dist/primitives/branchPicker/BranchPickerRoot.d.ts +1 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.js +1 -2
- package/dist/primitives/branchPicker.js +1 -2
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts +6 -5
- 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/ChainOfThoughtParts.js +1 -2
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.d.ts +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js +1 -2
- package/dist/primitives/chainOfThought.js +1 -2
- package/dist/primitives/composer/ComposerAddAttachment.d.ts +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js +1 -2
- package/dist/primitives/composer/ComposerAttachmentDropzone.js +1 -2
- package/dist/primitives/composer/ComposerAttachments.js +1 -2
- package/dist/primitives/composer/ComposerCancel.d.ts +1 -1
- package/dist/primitives/composer/ComposerCancel.js +1 -2
- package/dist/primitives/composer/ComposerCompactContext.js +1 -2
- package/dist/primitives/composer/ComposerDictate.d.ts +1 -1
- package/dist/primitives/composer/ComposerDictate.js +1 -2
- package/dist/primitives/composer/ComposerDictationTranscript.d.ts +1 -1
- package/dist/primitives/composer/ComposerDictationTranscript.js +1 -2
- package/dist/primitives/composer/ComposerIf.js +1 -2
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +4 -5
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.js +1 -2
- package/dist/primitives/composer/ComposerQueue.js +1 -2
- package/dist/primitives/composer/ComposerQuote.d.ts +3 -3
- package/dist/primitives/composer/ComposerQuote.js +1 -2
- package/dist/primitives/composer/ComposerResume.d.ts +1 -1
- package/dist/primitives/composer/ComposerResume.js +1 -2
- package/dist/primitives/composer/ComposerRoot.d.ts +1 -1
- package/dist/primitives/composer/ComposerRoot.js +1 -2
- package/dist/primitives/composer/ComposerSend.d.ts +1 -1
- package/dist/primitives/composer/ComposerSend.js +1 -2
- package/dist/primitives/composer/ComposerStopDictation.d.ts +1 -1
- package/dist/primitives/composer/ComposerStopDictation.js +1 -2
- package/dist/primitives/composer/composerInputSelector.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverBack.d.ts +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js +1 -2
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +2 -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.d.ts +2 -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.d.ts +1 -1
- 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.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.js +3 -4
- package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/error/ErrorMessage.js +1 -2
- package/dist/primitives/error/ErrorRoot.d.ts +1 -1
- package/dist/primitives/error/ErrorRoot.js +1 -2
- package/dist/primitives/error.js +1 -2
- package/dist/primitives/message/MessageAttachments.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 +1 -2
- package/dist/primitives/message/MessageRoot.d.ts +1 -1
- package/dist/primitives/message/MessageRoot.js +1 -2
- package/dist/primitives/message.js +1 -2
- package/dist/primitives/messagePart/MessagePartImage.d.ts +1 -1
- package/dist/primitives/messagePart/MessagePartImage.js +1 -2
- package/dist/primitives/messagePart/MessagePartInProgress.js +1 -2
- package/dist/primitives/messagePart/MessagePartText.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/queueItem/QueueItemRemove.js +1 -2
- package/dist/primitives/queueItem/QueueItemSteer.d.ts +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.js +1 -2
- package/dist/primitives/queueItem/QueueItemText.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +1 -2
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +1 -2
- package/dist/primitives/selectionToolbar.js +1 -2
- package/dist/primitives/suggestion/SuggestionDescription.d.ts +1 -1
- package/dist/primitives/suggestion/SuggestionDescription.js +1 -2
- package/dist/primitives/suggestion/SuggestionTitle.d.ts +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.js +1 -2
- package/dist/primitives/suggestion/SuggestionTrigger.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/primitives/thread/ThreadLoadEarlier.js +1 -2
- package/dist/primitives/thread/ThreadMessages.js +1 -2
- package/dist/primitives/thread/ThreadRoot.d.ts +1 -1
- package/dist/primitives/thread/ThreadRoot.js +1 -2
- package/dist/primitives/thread/ThreadRootElementContext.js +1 -2
- package/dist/primitives/thread/ThreadScrollToBottom.d.ts +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js +1 -2
- package/dist/primitives/thread/ThreadSuggestion.d.ts +1 -1
- package/dist/primitives/thread/ThreadSuggestion.js +1 -2
- package/dist/primitives/thread/ThreadSuggestions.js +1 -2
- package/dist/primitives/thread/ThreadViewport.d.ts +1 -1
- package/dist/primitives/thread/ThreadViewport.js +1 -2
- package/dist/primitives/thread/ThreadViewportFooter.d.ts +1 -1
- 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.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +7 -5
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/thread.js +1 -2
- package/dist/primitives/threadList/ThreadListItems.js +1 -2
- package/dist/primitives/threadList/ThreadListLoadMore.d.ts +1 -1
- package/dist/primitives/threadList/ThreadListLoadMore.js +1 -2
- package/dist/primitives/threadList/ThreadListNew.d.ts +1 -1
- package/dist/primitives/threadList/ThreadListNew.js +1 -2
- package/dist/primitives/threadList/ThreadListRoot.d.ts +1 -1
- package/dist/primitives/threadList/ThreadListRoot.js +1 -2
- package/dist/primitives/threadList.js +1 -2
- package/dist/primitives/threadListFocusGroup.d.ts +1 -1
- package/dist/primitives/threadListFocusGroup.d.ts.map +1 -1
- package/dist/primitives/threadListFocusGroup.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemArchive.d.ts +1 -1
- package/dist/primitives/threadListItem/ThreadListItemArchive.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemDelete.d.ts +1 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemRoot.d.ts +1 -1
- 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/ThreadListItemTitle.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemTrigger.d.ts +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js +1 -2
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts +2 -2
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.d.ts.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.js +3 -4
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
- 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 +1 -2
- package/dist/unstable/useComposerInput.js +2 -3
- package/dist/unstable/useComposerInput.js.map +1 -1
- package/dist/unstable/useComposerInputHistory.d.ts.map +1 -1
- package/dist/unstable/useComposerInputHistory.js +3 -4
- package/dist/unstable/useComposerInputHistory.js.map +1 -1
- package/dist/unstable/useLiveCompletionAdapter.d.ts.map +1 -1
- package/dist/unstable/useLiveCompletionAdapter.js +4 -4
- package/dist/unstable/useLiveCompletionAdapter.js.map +1 -1
- 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.d.ts +17 -17
- package/dist/utils/Primitive.js +1 -2
- package/dist/utils/createActionButton.d.ts +1 -1
- 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 +13 -13
- package/src/adapters/OpenAIRealtimeVoiceAdapter.test.ts +14 -1
- package/src/cloud-renderer/CloudRendererHost.tsx +4 -2
- package/src/index.ts +9 -8
- package/src/internal.ts +1 -1
- package/src/legacy-runtime/AssistantRuntimeProvider.tsx +1 -1
- 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/actionBar/ActionBarCopy.test.tsx +57 -0
- package/src/primitives/actionBar/ActionBarExportMarkdown.test.tsx +24 -5
- package/src/primitives/assistantModal/AssistantModalRoot.test.tsx +1 -1
- package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.test.tsx +91 -0
- package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +54 -0
- package/src/primitives/composer/ComposerInput.focus-on-run-start.test.tsx +1 -1
- package/src/primitives/composer/ComposerInput.test.tsx +1 -0
- package/src/primitives/composer/ComposerInput.text-change.test.tsx +68 -0
- package/src/primitives/composer/ComposerInput.thread-scope.test.tsx +82 -0
- package/src/primitives/composer/ComposerInput.tsx +4 -3
- package/src/primitives/composer/trigger/triggerSelectionResource.test.ts +6 -4
- package/src/primitives/composer/trigger/triggerSelectionResource.ts +2 -0
- package/src/primitives/reasoning/useScrollLock.test.tsx +71 -2
- package/src/primitives/reasoning/useScrollLock.ts +78 -51
- package/src/primitives/thread/ThreadRoot.test.tsx +1 -1
- package/src/primitives/thread/ThreadViewport.thread-scope.test.tsx +51 -0
- package/src/primitives/thread/useThreadViewportAutoScroll.ts +8 -2
- package/src/primitives/threadListItem/ThreadListItemRoot.tsx +4 -1
- package/src/primitives/threadListItem/ThreadListItemUnarchive.test.tsx +52 -0
- package/src/primitives/threadListItem/ThreadListItemUnarchive.ts +2 -2
- package/src/primitives/threadListItem/ThreadListKeyboardNav.test.tsx +25 -0
- package/src/tests/DataRenderers.test.tsx +1 -1
- package/src/tests/MessageParts.loading.test.tsx +1 -1
- package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +1 -1
- package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +4 -2
- package/src/tests/RemoteThreadListRuntime.reloadMainThread.test.tsx +4 -2
- package/src/tests/generative-ui.primitive.test.tsx +1 -1
- package/src/tests/local-runtime-queue.test.tsx +2 -2
- package/src/tests/messagePartSwitchRace.test.tsx +2 -2
- package/src/tests/messagePartTypeMismatch.test.tsx +1 -1
- package/src/tests/threadListItemIsRunning.test.tsx +5 -3
- package/src/tests/toolCallTiming.test.tsx +1 -1
- package/src/unstable/useComposerInput.test.tsx +1 -1
- package/src/unstable/useComposerInput.ts +1 -1
- package/src/unstable/useComposerInputHistory.test.tsx +10 -7
- package/src/unstable/useComposerInputHistory.thread-scope.test.tsx +123 -0
- package/src/unstable/useComposerInputHistory.ts +3 -2
- package/src/unstable/useLiveCompletionAdapter.test.tsx +44 -0
- package/src/unstable/useLiveCompletionAdapter.ts +3 -2
- package/src/unstable/webmcp/convertTools.test.ts +11 -1
- package/src/utils/hooks/useMediaQuery.test.tsx +35 -0
- package/src/utils/smooth/useSmooth.test.tsx +150 -14
- package/src/utils/smooth/useSmooth.ts +16 -2
- package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts +0 -2
- package/dist/context/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +0 -1
- package/dist/context/providers/ChainOfThoughtPartByIndexProvider.js +0 -3
- package/dist/legacy-runtime/RuntimeAdapter.d.ts +0 -2
- package/dist/legacy-runtime/RuntimeAdapter.d.ts.map +0 -1
- package/dist/legacy-runtime/RuntimeAdapter.js +0 -2
- package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts +0 -2
- package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +0 -1
- package/dist/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.js +0 -3
- package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts +0 -3
- package/dist/legacy-runtime/runtime/AssistantRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/AssistantRuntime.js +0 -2
- package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts +0 -3
- package/dist/legacy-runtime/runtime/AttachmentRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/AttachmentRuntime.js +0 -2
- package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts +0 -4
- package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/ComposerRuntime.js +0 -2
- package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts +0 -3
- package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/RuntimeBindings.js +0 -0
- package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts +0 -2
- package/dist/legacy-runtime/runtime/RuntimePathTypes.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/RuntimePathTypes.js +0 -0
- package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts +0 -5
- package/dist/legacy-runtime/runtime/ThreadListItemRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/ThreadListItemRuntime.js +0 -2
- package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +0 -4
- package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime/ThreadRuntime.js +0 -2
- package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.js +0 -3
- package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.js +0 -3
- package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.js +0 -0
- package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.js +0 -0
- package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.js +0 -0
- package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.js +0 -0
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.js +0 -0
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/auto-status.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/auto-status.js +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/external-message-converter.js +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.js +0 -3
- package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/ChatModelAdapter.js +0 -0
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts +0 -4
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.js +0 -2
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts +0 -3
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.js +0 -2
- package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/local/shouldContinue.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/shouldContinue.js +0 -2
- package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.js +0 -3
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.js +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.js +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.js +0 -3
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.js +0 -3
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.js +0 -3
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.js +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/types.js +0 -0
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts +0 -2
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.js +0 -3
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts +0 -4
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js +0 -3
- package/dist/utils/hooks/useOnResizeContent.d.ts +0 -2
- package/dist/utils/hooks/useOnResizeContent.d.ts.map +0 -1
- package/dist/utils/hooks/useOnResizeContent.js +0 -21
- package/dist/utils/hooks/useOnResizeContent.js.map +0 -1
- package/src/context/providers/ChainOfThoughtPartByIndexProvider.tsx +0 -3
- package/src/legacy-runtime/RuntimeAdapter.ts +0 -1
- package/src/legacy-runtime/cloud/AssistantCloudThreadHistoryAdapter.ts +0 -3
- package/src/legacy-runtime/runtime/AssistantRuntime.ts +0 -2
- package/src/legacy-runtime/runtime/AttachmentRuntime.ts +0 -7
- package/src/legacy-runtime/runtime/ComposerRuntime.ts +0 -20
- package/src/legacy-runtime/runtime/RuntimeBindings.ts +0 -12
- package/src/legacy-runtime/runtime/RuntimePathTypes.ts +0 -8
- package/src/legacy-runtime/runtime/ThreadListItemRuntime.ts +0 -10
- package/src/legacy-runtime/runtime/ThreadRuntime.ts +0 -14
- package/src/legacy-runtime/runtime-cores/adapters/RuntimeAdapterProvider.tsx +0 -7
- package/src/legacy-runtime/runtime-cores/adapters/attachment/CloudFileAttachmentAdapter.ts +0 -3
- package/src/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/composer/DefaultEditComposerRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/composer/DefaultThreadComposerRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/core/AssistantRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/core/BaseAssistantRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.ts +0 -6
- package/src/legacy-runtime/runtime-cores/core/ThreadListRuntimeCore.ts +0 -4
- package/src/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.ts +0 -13
- package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreAdapter.ts +0 -6
- package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadListRuntimeCore.ts +0 -2
- package/src/legacy-runtime/runtime-cores/external-store/ExternalStoreThreadRuntimeCore.ts +0 -4
- package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageConverter.ts +0 -2
- package/src/legacy-runtime/runtime-cores/external-store/ThreadMessageLike.ts +0 -2
- package/src/legacy-runtime/runtime-cores/external-store/auto-status.ts +0 -1
- package/src/legacy-runtime/runtime-cores/external-store/createMessageConverter.ts +0 -2
- package/src/legacy-runtime/runtime-cores/external-store/external-message-converter.ts +0 -7
- package/src/legacy-runtime/runtime-cores/external-store/useExternalStoreRuntime.ts +0 -3
- package/src/legacy-runtime/runtime-cores/local/ChatModelAdapter.ts +0 -7
- package/src/legacy-runtime/runtime-cores/local/LocalRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/local/LocalRuntimeOptions.ts +0 -3
- package/src/legacy-runtime/runtime-cores/local/LocalThreadListRuntimeCore.ts +0 -2
- package/src/legacy-runtime/runtime-cores/local/LocalThreadRuntimeCore.ts +0 -1
- package/src/legacy-runtime/runtime-cores/local/shouldContinue.ts +0 -1
- package/src/legacy-runtime/runtime-cores/local/useLocalRuntime.ts +0 -3
- package/src/legacy-runtime/runtime-cores/remote-thread-list/BaseSubscribable.ts +0 -1
- package/src/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.ts +0 -1
- package/src/legacy-runtime/runtime-cores/remote-thread-list/OptimisticState.ts +0 -1
- package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.tsx +0 -3
- package/src/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.tsx +0 -3
- package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud.tsx +0 -3
- package/src/legacy-runtime/runtime-cores/remote-thread-list/adapter/in-memory.ts +0 -1
- package/src/legacy-runtime/runtime-cores/remote-thread-list/types.ts +0 -7
- package/src/legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime.ts +0 -3
- package/src/legacy-runtime/runtime-cores/utils/MessageRepository.ts +0 -3
- package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.ts +0 -49
- package/src/utils/hooks/useOnResizeContent.ts +0 -15
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
act,
|
|
5
|
+
cleanup,
|
|
6
|
+
fireEvent,
|
|
7
|
+
render,
|
|
8
|
+
screen,
|
|
9
|
+
} from "@testing-library/react";
|
|
10
|
+
import type { FC } from "react";
|
|
11
|
+
import { afterEach, expect, it } from "vitest";
|
|
12
|
+
import { useAui } from "@assistant-ui/store";
|
|
13
|
+
import { useLocalRuntime } from "@assistant-ui/core/react";
|
|
14
|
+
import type { ChatModelAdapter } from "@assistant-ui/core";
|
|
15
|
+
import { AssistantRuntimeProvider } from "../../context";
|
|
16
|
+
import { ThreadPrimitiveViewportProvider } from "../../context/providers/ThreadViewportProvider";
|
|
17
|
+
import { ComposerPrimitiveInput } from "./ComposerInput";
|
|
18
|
+
|
|
19
|
+
const adapter: ChatModelAdapter = {
|
|
20
|
+
async *run() {
|
|
21
|
+
yield { content: [{ type: "text", text: "done" }] };
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
afterEach(cleanup);
|
|
26
|
+
|
|
27
|
+
it("emits composer.textChange with the user origin for typing and the send origin for the clear", async () => {
|
|
28
|
+
let aui!: ReturnType<typeof useAui>;
|
|
29
|
+
const Capture: FC = () => {
|
|
30
|
+
aui = useAui();
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
const App: FC = () => (
|
|
34
|
+
<AssistantRuntimeProvider runtime={useLocalRuntime(adapter)}>
|
|
35
|
+
<Capture />
|
|
36
|
+
<ThreadPrimitiveViewportProvider>
|
|
37
|
+
<ComposerPrimitiveInput aria-label="Composer" />
|
|
38
|
+
</ThreadPrimitiveViewportProvider>
|
|
39
|
+
</AssistantRuntimeProvider>
|
|
40
|
+
);
|
|
41
|
+
render(<App />);
|
|
42
|
+
const changes: unknown[] = [];
|
|
43
|
+
aui.on({ scope: "*", event: "composer.textChange" }, (change) =>
|
|
44
|
+
changes.push(change),
|
|
45
|
+
);
|
|
46
|
+
const input = screen.getByRole("textbox", { name: "Composer" });
|
|
47
|
+
|
|
48
|
+
await act(async () => {
|
|
49
|
+
fireEvent.change(input, { target: { value: "hi" } });
|
|
50
|
+
});
|
|
51
|
+
await act(async () => {
|
|
52
|
+
fireEvent.change(input, { target: { value: "" } });
|
|
53
|
+
});
|
|
54
|
+
await act(async () => {
|
|
55
|
+
fireEvent.change(input, { target: { value: "hello" } });
|
|
56
|
+
});
|
|
57
|
+
await act(async () => {
|
|
58
|
+
aui.composer().send();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const threadId = aui.threads().getState().mainThreadId;
|
|
62
|
+
expect(changes).toEqual([
|
|
63
|
+
{ threadId, text: "hi", origin: "user" },
|
|
64
|
+
{ threadId, text: "", origin: "user" },
|
|
65
|
+
{ threadId, text: "hello", origin: "user" },
|
|
66
|
+
{ threadId, text: "", origin: "send" },
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
act,
|
|
5
|
+
cleanup,
|
|
6
|
+
fireEvent,
|
|
7
|
+
render,
|
|
8
|
+
screen,
|
|
9
|
+
waitFor,
|
|
10
|
+
} from "@testing-library/react";
|
|
11
|
+
import { afterEach, expect, it } from "vitest";
|
|
12
|
+
import { AuiConfig, AuiProvider, Derived, useAui } from "@assistant-ui/store";
|
|
13
|
+
import { ExternalThread, InMemoryThreadList } from "@assistant-ui/core/store";
|
|
14
|
+
import { resource, useResource } from "@assistant-ui/tap";
|
|
15
|
+
import { ThreadPrimitiveViewportProvider } from "../../context/providers/ThreadViewportProvider";
|
|
16
|
+
import { ComposerPrimitiveInput } from "./ComposerInput";
|
|
17
|
+
|
|
18
|
+
const StandaloneThread = resource(function useStandaloneThread() {
|
|
19
|
+
return useResource(ExternalThread({ messages: [] }));
|
|
20
|
+
});
|
|
21
|
+
const StandaloneApp = () => {
|
|
22
|
+
const config = AuiConfig({
|
|
23
|
+
thread: StandaloneThread(),
|
|
24
|
+
composer: Derived({
|
|
25
|
+
source: "thread",
|
|
26
|
+
query: {},
|
|
27
|
+
get: (aui) => aui.thread.composer(),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
return (
|
|
31
|
+
<AuiProvider config={config}>
|
|
32
|
+
<ThreadPrimitiveViewportProvider>
|
|
33
|
+
<ComposerPrimitiveInput aria-label="Composer" />
|
|
34
|
+
</ThreadPrimitiveViewportProvider>
|
|
35
|
+
</AuiProvider>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
afterEach(cleanup);
|
|
40
|
+
|
|
41
|
+
it("edits a draft without a thread-list scope", async () => {
|
|
42
|
+
render(<StandaloneApp />);
|
|
43
|
+
const input = screen.getByRole("textbox", {
|
|
44
|
+
name: "Composer",
|
|
45
|
+
}) as HTMLTextAreaElement;
|
|
46
|
+
await act(async () => {
|
|
47
|
+
fireEvent.change(input, { target: { value: "New question" } });
|
|
48
|
+
});
|
|
49
|
+
expect(input.value).toBe("New question");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("restores composer focus when the thread switches", async () => {
|
|
53
|
+
let captured!: ReturnType<typeof useAui>;
|
|
54
|
+
const App = () => {
|
|
55
|
+
const aui = useAui({
|
|
56
|
+
threads: InMemoryThreadList({
|
|
57
|
+
thread: () => ExternalThread({ messages: [] }),
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
captured = aui;
|
|
61
|
+
return (
|
|
62
|
+
<AuiProvider value={aui}>
|
|
63
|
+
<ThreadPrimitiveViewportProvider>
|
|
64
|
+
<button>Outside</button>
|
|
65
|
+
<ComposerPrimitiveInput aria-label="Composer" autoFocus />
|
|
66
|
+
</ThreadPrimitiveViewportProvider>
|
|
67
|
+
</AuiProvider>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
render(<App />);
|
|
71
|
+
const input = screen.getByRole("textbox", { name: "Composer" });
|
|
72
|
+
expect(document.activeElement).toBe(input);
|
|
73
|
+
act(() => screen.getByRole("button", { name: "Outside" }).focus());
|
|
74
|
+
const oldId = captured.threads.getState().mainThreadId;
|
|
75
|
+
await act(async () => {
|
|
76
|
+
captured.threads.switchToNewThread();
|
|
77
|
+
});
|
|
78
|
+
await waitFor(() =>
|
|
79
|
+
expect(captured.threads.getState().mainThreadId).not.toBe(oldId),
|
|
80
|
+
);
|
|
81
|
+
expect(document.activeElement).toBe(input);
|
|
82
|
+
});
|
|
@@ -393,7 +393,8 @@ export const ComposerPrimitiveInput = forwardRef<
|
|
|
393
393
|
useEffect(() => {
|
|
394
394
|
if (
|
|
395
395
|
aui.composer.getState().type !== "thread" ||
|
|
396
|
-
!unstable_focusOnThreadSwitched
|
|
396
|
+
!unstable_focusOnThreadSwitched ||
|
|
397
|
+
!aui.optional.threads
|
|
397
398
|
)
|
|
398
399
|
return undefined;
|
|
399
400
|
|
|
@@ -426,7 +427,7 @@ export const ComposerPrimitiveInput = forwardRef<
|
|
|
426
427
|
const isComposing = nativeIsComposing || compositionRef.current;
|
|
427
428
|
// Standalone tap roots need a synchronous flush while the input is composing.
|
|
428
429
|
flushTapSync(() => {
|
|
429
|
-
aui.composer.setText(e.target.value);
|
|
430
|
+
aui.composer.setText(e.target.value, { origin: "user" });
|
|
430
431
|
});
|
|
431
432
|
if (isComposing) return;
|
|
432
433
|
const pos = e.target.selectionStart ?? e.target.value.length;
|
|
@@ -453,7 +454,7 @@ export const ComposerPrimitiveInput = forwardRef<
|
|
|
453
454
|
if (!aui.composer.getState().isEditing) return;
|
|
454
455
|
const target = e.target as HTMLTextAreaElement;
|
|
455
456
|
flushTapSync(() => {
|
|
456
|
-
aui.composer.setText(target.value);
|
|
457
|
+
aui.composer.setText(target.value, { origin: "user" });
|
|
457
458
|
});
|
|
458
459
|
const pos = target.selectionStart ?? target.value.length;
|
|
459
460
|
if (pluginRegistry) {
|
|
@@ -77,7 +77,7 @@ describe("TriggerSelectionResource", () => {
|
|
|
77
77
|
|
|
78
78
|
root.getValue().selectItem(item);
|
|
79
79
|
|
|
80
|
-
expect(setText).toHaveBeenCalledWith("@file.txt tail");
|
|
80
|
+
expect(setText).toHaveBeenCalledWith("@file.txt tail", { origin: "user" });
|
|
81
81
|
expect(setCursorPosition).toHaveBeenCalledWith("@file.txt".length + 1);
|
|
82
82
|
expect(onSelected).toHaveBeenCalledOnce();
|
|
83
83
|
});
|
|
@@ -120,7 +120,7 @@ describe("TriggerSelectionResource", () => {
|
|
|
120
120
|
|
|
121
121
|
root.getValue().selectItem(item);
|
|
122
122
|
|
|
123
|
-
expect(setText).toHaveBeenCalledWith("before tail");
|
|
123
|
+
expect(setText).toHaveBeenCalledWith("before tail", { origin: "user" });
|
|
124
124
|
expect(setCursorPosition).toHaveBeenCalledWith(7);
|
|
125
125
|
});
|
|
126
126
|
|
|
@@ -153,7 +153,7 @@ describe("TriggerSelectionResource", () => {
|
|
|
153
153
|
root.getValue().selectItem(item);
|
|
154
154
|
|
|
155
155
|
expect(setText).toHaveBeenCalledOnce();
|
|
156
|
-
expect(setText).toHaveBeenCalledWith("@file.txt ");
|
|
156
|
+
expect(setText).toHaveBeenCalledWith("@file.txt ", { origin: "user" });
|
|
157
157
|
expect(textRef.value).toBe("@file.txt ");
|
|
158
158
|
});
|
|
159
159
|
|
|
@@ -166,6 +166,8 @@ describe("TriggerSelectionResource", () => {
|
|
|
166
166
|
|
|
167
167
|
root.getValue().selectItem(item);
|
|
168
168
|
|
|
169
|
-
expect(setText).toHaveBeenCalledWith("hello @file.txt tail"
|
|
169
|
+
expect(setText).toHaveBeenCalledWith("hello @file.txt tail", {
|
|
170
|
+
origin: "user",
|
|
171
|
+
});
|
|
170
172
|
});
|
|
171
173
|
});
|
|
@@ -90,6 +90,7 @@ const useTriggerSelectionResource = ({
|
|
|
90
90
|
const directive = behavior.formatter.serialize(item);
|
|
91
91
|
aui.composer.setText(
|
|
92
92
|
before + directive + (after.startsWith(" ") ? after : ` ${after}`),
|
|
93
|
+
{ origin: "user" },
|
|
93
94
|
);
|
|
94
95
|
setCursorPosition(before.length + directive.length + 1);
|
|
95
96
|
};
|
|
@@ -101,6 +102,7 @@ const useTriggerSelectionResource = ({
|
|
|
101
102
|
if (behavior.removeOnExecute) {
|
|
102
103
|
aui.composer.setText(
|
|
103
104
|
before + (after.startsWith(" ") ? after.slice(1) : after),
|
|
105
|
+
{ origin: "user" },
|
|
104
106
|
);
|
|
105
107
|
setCursorPosition(before.length);
|
|
106
108
|
} else {
|
|
@@ -31,9 +31,29 @@ function stubWidths(
|
|
|
31
31
|
function lockWithin(container: HTMLElement) {
|
|
32
32
|
const animated = document.createElement("div");
|
|
33
33
|
container.appendChild(animated);
|
|
34
|
+
return createLock(animated).lock;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function createLock(animated: HTMLElement) {
|
|
34
38
|
const ref = { current: animated };
|
|
35
|
-
const { result } = renderHook(() => useScrollLock(ref, 200));
|
|
36
|
-
return result.current;
|
|
39
|
+
const { result, unmount } = renderHook(() => useScrollLock(ref, 200));
|
|
40
|
+
return { lock: result.current, dispose: unmount };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createSharedScroller() {
|
|
44
|
+
const scroller = document.createElement("div");
|
|
45
|
+
scroller.style.overflowY = "auto";
|
|
46
|
+
scroller.style.borderWidth = "0px";
|
|
47
|
+
scroller.style.paddingRight = "4px";
|
|
48
|
+
document.body.appendChild(scroller);
|
|
49
|
+
Object.defineProperty(scroller, "offsetWidth", { value: 306 });
|
|
50
|
+
Object.defineProperty(scroller, "clientWidth", {
|
|
51
|
+
get: () => (scroller.style.scrollbarWidth === "none" ? 306 : 300),
|
|
52
|
+
});
|
|
53
|
+
const first = document.createElement("div");
|
|
54
|
+
const second = document.createElement("div");
|
|
55
|
+
scroller.append(first, second);
|
|
56
|
+
return { scroller, first: createLock(first), second: createLock(second) };
|
|
37
57
|
}
|
|
38
58
|
|
|
39
59
|
describe("useScrollLock", () => {
|
|
@@ -115,6 +135,55 @@ describe("useScrollLock", () => {
|
|
|
115
135
|
expect(scroller.style.scrollbarWidth).toBe("");
|
|
116
136
|
});
|
|
117
137
|
|
|
138
|
+
it("keeps overlapping animations locked until the last one finishes", () => {
|
|
139
|
+
vi.useFakeTimers();
|
|
140
|
+
const { scroller, first, second } = createSharedScroller();
|
|
141
|
+
scroller.scrollTop = 120;
|
|
142
|
+
|
|
143
|
+
first.lock();
|
|
144
|
+
vi.advanceTimersByTime(100);
|
|
145
|
+
second.lock();
|
|
146
|
+
expect(scroller.style.paddingRight).toBe("10px");
|
|
147
|
+
|
|
148
|
+
vi.advanceTimersByTime(100);
|
|
149
|
+
expect(scroller.style.scrollbarWidth).toBe("none");
|
|
150
|
+
expect(scroller.style.paddingRight).toBe("10px");
|
|
151
|
+
scroller.scrollTop = 90;
|
|
152
|
+
scroller.dispatchEvent(new Event("scroll"));
|
|
153
|
+
expect(scroller.scrollTop).toBe(120);
|
|
154
|
+
|
|
155
|
+
vi.advanceTimersByTime(100);
|
|
156
|
+
expect(scroller.style.scrollbarWidth).toBe("");
|
|
157
|
+
expect(scroller.style.paddingRight).toBe("4px");
|
|
158
|
+
scroller.scrollTop = 90;
|
|
159
|
+
scroller.dispatchEvent(new Event("scroll"));
|
|
160
|
+
expect(scroller.scrollTop).toBe(90);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it.each(["first", "second"] as const)(
|
|
164
|
+
"preserves a restarted shared lock when the %s owner is disposed first",
|
|
165
|
+
(disposedFirst) => {
|
|
166
|
+
vi.useFakeTimers();
|
|
167
|
+
const shared = createSharedScroller();
|
|
168
|
+
const { scroller, first, second } = shared;
|
|
169
|
+
first.lock();
|
|
170
|
+
second.lock();
|
|
171
|
+
vi.advanceTimersByTime(100);
|
|
172
|
+
first.lock();
|
|
173
|
+
|
|
174
|
+
shared[disposedFirst].dispose();
|
|
175
|
+
expect(scroller.style.scrollbarWidth).toBe("none");
|
|
176
|
+
expect(scroller.style.paddingRight).toBe("10px");
|
|
177
|
+
|
|
178
|
+
shared[disposedFirst === "first" ? "second" : "first"].dispose();
|
|
179
|
+
expect(scroller.style.scrollbarWidth).toBe("");
|
|
180
|
+
expect(scroller.style.paddingRight).toBe("4px");
|
|
181
|
+
scroller.style.scrollbarWidth = "thin";
|
|
182
|
+
vi.advanceTimersByTime(200);
|
|
183
|
+
expect(scroller.style.scrollbarWidth).toBe("thin");
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
|
|
118
187
|
it("leaves the padding alone when no scrollbar takes space", () => {
|
|
119
188
|
const scroller = document.createElement("div");
|
|
120
189
|
scroller.style.overflowY = "auto";
|
|
@@ -12,6 +12,74 @@ const findScrollableAncestor = (element: HTMLElement | null) => {
|
|
|
12
12
|
return null;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const scrollLocks = new WeakMap<
|
|
16
|
+
HTMLElement,
|
|
17
|
+
{ count: number; restore: () => void }
|
|
18
|
+
>();
|
|
19
|
+
|
|
20
|
+
const acquireScrollLock = (scrollContainer: HTMLElement) => {
|
|
21
|
+
const existing = scrollLocks.get(scrollContainer);
|
|
22
|
+
if (existing) {
|
|
23
|
+
existing.count++;
|
|
24
|
+
return existing;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const scrollPosition = scrollContainer.scrollTop;
|
|
28
|
+
const scrollbarWidth = scrollContainer.style.scrollbarWidth;
|
|
29
|
+
|
|
30
|
+
// Hiding the scrollbar collapses its gutter on classic scrollbars, which
|
|
31
|
+
// shifts centered content horizontally; compensate with padding on the
|
|
32
|
+
// side the scrollbar occupies (the left side in RTL).
|
|
33
|
+
const computed = getComputedStyle(scrollContainer);
|
|
34
|
+
const paddingSide =
|
|
35
|
+
computed.direction === "rtl" ? "paddingLeft" : "paddingRight";
|
|
36
|
+
const previousPadding = scrollContainer.style[paddingSide];
|
|
37
|
+
const elementScrollbarSize =
|
|
38
|
+
scrollContainer.offsetWidth -
|
|
39
|
+
scrollContainer.clientWidth -
|
|
40
|
+
parseFloat(computed.borderLeftWidth) -
|
|
41
|
+
parseFloat(computed.borderRightWidth);
|
|
42
|
+
// A root element's offsetWidth already excludes the viewport scrollbar, so
|
|
43
|
+
// the element formula reports zero once the scroll propagates to the
|
|
44
|
+
// viewport, and only then does the viewport measure apply. A body that
|
|
45
|
+
// scrolls in its own right is measured by the element formula like any
|
|
46
|
+
// other scroller, whether or not the viewport is scrolling too.
|
|
47
|
+
const ownerDocument = scrollContainer.ownerDocument;
|
|
48
|
+
const isRootScroller =
|
|
49
|
+
scrollContainer === ownerDocument.documentElement ||
|
|
50
|
+
scrollContainer === ownerDocument.body;
|
|
51
|
+
const scrollbarSize =
|
|
52
|
+
isRootScroller && elementScrollbarSize <= 0
|
|
53
|
+
? (ownerDocument.defaultView?.innerWidth ?? 0) -
|
|
54
|
+
ownerDocument.documentElement.clientWidth
|
|
55
|
+
: elementScrollbarSize;
|
|
56
|
+
|
|
57
|
+
scrollContainer.style.scrollbarWidth = "none";
|
|
58
|
+
if (scrollbarSize > 0) {
|
|
59
|
+
scrollContainer.style[paddingSide] = `${
|
|
60
|
+
parseFloat(computed[paddingSide]) + scrollbarSize
|
|
61
|
+
}px`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const restoreStyles = () => {
|
|
65
|
+
scrollContainer.style.scrollbarWidth = scrollbarWidth;
|
|
66
|
+
scrollContainer.style[paddingSide] = previousPadding;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const resetPosition = () => (scrollContainer.scrollTop = scrollPosition);
|
|
70
|
+
scrollContainer.addEventListener("scroll", resetPosition);
|
|
71
|
+
|
|
72
|
+
const lock = {
|
|
73
|
+
count: 1,
|
|
74
|
+
restore: () => {
|
|
75
|
+
scrollContainer.removeEventListener("scroll", resetPosition);
|
|
76
|
+
restoreStyles();
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
scrollLocks.set(scrollContainer, lock);
|
|
80
|
+
return lock;
|
|
81
|
+
};
|
|
82
|
+
|
|
15
83
|
/**
|
|
16
84
|
* Locks scroll position during collapsible/height animations and hides scrollbar.
|
|
17
85
|
*
|
|
@@ -59,61 +127,20 @@ export const useScrollLock = <T extends HTMLElement = HTMLElement>(
|
|
|
59
127
|
return;
|
|
60
128
|
}
|
|
61
129
|
|
|
62
|
-
const
|
|
63
|
-
const scrollbarWidth = scrollContainer.style.scrollbarWidth;
|
|
64
|
-
|
|
65
|
-
// Hiding the scrollbar collapses its gutter on classic scrollbars, which
|
|
66
|
-
// shifts centered content horizontally; compensate with padding on the
|
|
67
|
-
// side the scrollbar occupies (the left side in RTL).
|
|
68
|
-
const computed = getComputedStyle(scrollContainer);
|
|
69
|
-
const paddingSide =
|
|
70
|
-
computed.direction === "rtl" ? "paddingLeft" : "paddingRight";
|
|
71
|
-
const previousPadding = scrollContainer.style[paddingSide];
|
|
72
|
-
const elementScrollbarSize =
|
|
73
|
-
scrollContainer.offsetWidth -
|
|
74
|
-
scrollContainer.clientWidth -
|
|
75
|
-
parseFloat(computed.borderLeftWidth) -
|
|
76
|
-
parseFloat(computed.borderRightWidth);
|
|
77
|
-
// A root element's offsetWidth already excludes the viewport scrollbar, so
|
|
78
|
-
// the element formula reports zero once the scroll propagates to the
|
|
79
|
-
// viewport, and only then does the viewport measure apply. A body that
|
|
80
|
-
// scrolls in its own right is measured by the element formula like any
|
|
81
|
-
// other scroller, whether or not the viewport is scrolling too.
|
|
82
|
-
const ownerDocument = scrollContainer.ownerDocument;
|
|
83
|
-
const isRootScroller =
|
|
84
|
-
scrollContainer === ownerDocument.documentElement ||
|
|
85
|
-
scrollContainer === ownerDocument.body;
|
|
86
|
-
const scrollbarSize =
|
|
87
|
-
isRootScroller && elementScrollbarSize <= 0
|
|
88
|
-
? (ownerDocument.defaultView?.innerWidth ?? 0) -
|
|
89
|
-
ownerDocument.documentElement.clientWidth
|
|
90
|
-
: elementScrollbarSize;
|
|
91
|
-
|
|
92
|
-
scrollContainer.style.scrollbarWidth = "none";
|
|
93
|
-
if (scrollbarSize > 0) {
|
|
94
|
-
scrollContainer.style[paddingSide] = `${
|
|
95
|
-
parseFloat(computed[paddingSide]) + scrollbarSize
|
|
96
|
-
}px`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const restoreStyles = () => {
|
|
100
|
-
scrollContainer.style.scrollbarWidth = scrollbarWidth;
|
|
101
|
-
scrollContainer.style[paddingSide] = previousPadding;
|
|
102
|
-
};
|
|
130
|
+
const lock = acquireScrollLock(scrollContainer);
|
|
103
131
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
scrollContainer.removeEventListener("scroll", resetPosition);
|
|
109
|
-
restoreStyles();
|
|
110
|
-
cleanupRef.current = null;
|
|
111
|
-
}, animationDuration);
|
|
132
|
+
const timeoutId = setTimeout(
|
|
133
|
+
() => cleanupRef.current?.(),
|
|
134
|
+
animationDuration,
|
|
135
|
+
);
|
|
112
136
|
|
|
113
137
|
cleanupRef.current = () => {
|
|
114
138
|
clearTimeout(timeoutId);
|
|
115
|
-
|
|
116
|
-
|
|
139
|
+
if (--lock.count === 0) {
|
|
140
|
+
lock.restore();
|
|
141
|
+
scrollLocks.delete(scrollContainer);
|
|
142
|
+
}
|
|
143
|
+
cleanupRef.current = null;
|
|
117
144
|
};
|
|
118
145
|
}, [animationDuration, animatedElementRef]);
|
|
119
146
|
|
|
@@ -4,7 +4,7 @@ import { act, render, screen, waitFor } from "@testing-library/react";
|
|
|
4
4
|
import type { FC, PropsWithChildren } from "react";
|
|
5
5
|
import { describe, expect, it, vi } from "vitest";
|
|
6
6
|
import { AssistantRuntimeProvider } from "../../context";
|
|
7
|
-
import { useLocalRuntime } from "
|
|
7
|
+
import { useLocalRuntime } from "@assistant-ui/core/react";
|
|
8
8
|
import type {
|
|
9
9
|
ChatModelAdapter,
|
|
10
10
|
SpeechSynthesisAdapter,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { cleanup, render } from "@testing-library/react";
|
|
4
|
+
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
|
5
|
+
import { AuiConfig, AuiProvider } from "@assistant-ui/store";
|
|
6
|
+
import { resource, useResource } from "@assistant-ui/tap";
|
|
7
|
+
import { ExternalThread } from "@assistant-ui/core/store";
|
|
8
|
+
import { ThreadPrimitiveViewport } from "./ThreadViewport";
|
|
9
|
+
|
|
10
|
+
const StandaloneThread = resource(function useStandaloneThread() {
|
|
11
|
+
return useResource(ExternalThread({ messages: [] }));
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const Harness = ({ standalone }: { standalone: boolean }) => {
|
|
15
|
+
const config = AuiConfig({
|
|
16
|
+
thread: standalone ? StandaloneThread() : ExternalThread({ messages: [] }),
|
|
17
|
+
});
|
|
18
|
+
return (
|
|
19
|
+
<AuiProvider config={config}>
|
|
20
|
+
<ThreadPrimitiveViewport role="region" aria-label="Conversation">
|
|
21
|
+
Conversation content
|
|
22
|
+
</ThreadPrimitiveViewport>
|
|
23
|
+
</AuiProvider>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
vi.stubGlobal(
|
|
29
|
+
"ResizeObserver",
|
|
30
|
+
class {
|
|
31
|
+
observe() {}
|
|
32
|
+
unobserve() {}
|
|
33
|
+
disconnect() {}
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
cleanup();
|
|
40
|
+
vi.unstubAllGlobals();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it.each([true, false])(
|
|
44
|
+
"renders a thread viewport with standalone=%s",
|
|
45
|
+
(standalone) => {
|
|
46
|
+
const view = render(<Harness standalone={standalone} />);
|
|
47
|
+
expect(view.getByRole("region", { name: "Conversation" }).textContent).toBe(
|
|
48
|
+
"Conversation content",
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
useCallback,
|
|
5
|
+
useEffect,
|
|
5
6
|
useInsertionEffect,
|
|
6
7
|
useRef,
|
|
7
8
|
type RefCallback,
|
|
@@ -56,7 +57,7 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
|
|
|
56
57
|
const divRef = useRef<TElement>(null);
|
|
57
58
|
const hasMessages = useAuiState((s) => s.thread.messages.length > 0);
|
|
58
59
|
const firstMessageId = useAuiState((s) => s.thread.messages[0]?.id);
|
|
59
|
-
const threadId = useAuiState((s) => s.threadListItem
|
|
60
|
+
const threadId = useAuiState((s) => s.optional.threadListItem?.id);
|
|
60
61
|
const isRunning = useAuiState((s) => s.thread.isRunning);
|
|
61
62
|
const threadViewportStore = useThreadViewportStore();
|
|
62
63
|
const binding = getThreadViewportAutoScroll(threadViewportStore);
|
|
@@ -105,7 +106,12 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
|
|
|
105
106
|
|
|
106
107
|
useOnScrollToBottom(({ behavior }) => controller.scrollToBottom(behavior));
|
|
107
108
|
useAuiEvent("thread.runStart", () => controller.runStarted());
|
|
108
|
-
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (!aui.optional.threads) return;
|
|
111
|
+
return aui.on("threads.selectionChanged", () =>
|
|
112
|
+
controller.threadSwitched(),
|
|
113
|
+
);
|
|
114
|
+
}, [aui, controller]);
|
|
109
115
|
|
|
110
116
|
return useManagedRef(
|
|
111
117
|
useCallback(
|
|
@@ -51,7 +51,10 @@ export const ThreadListItemPrimitiveRoot = forwardRef<
|
|
|
51
51
|
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
52
52
|
const triggers = getItems()
|
|
53
53
|
.map((item) => item.ref.current)
|
|
54
|
-
.filter(
|
|
54
|
+
.filter(
|
|
55
|
+
(node): node is HTMLButtonElement =>
|
|
56
|
+
node !== null && !node.disabled,
|
|
57
|
+
);
|
|
55
58
|
const next =
|
|
56
59
|
triggers[
|
|
57
60
|
triggers.indexOf(trigger) + (event.key === "ArrowDown" ? 1 : -1)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { cleanup, fireEvent, render } from "@testing-library/react";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
AssistantRuntimeProvider,
|
|
7
|
+
ThreadListItemByIndexProvider,
|
|
8
|
+
} from "@assistant-ui/core/react";
|
|
9
|
+
import {
|
|
10
|
+
AssistantRuntimeImpl,
|
|
11
|
+
ExternalStoreRuntimeCore,
|
|
12
|
+
} from "@assistant-ui/core/internal";
|
|
13
|
+
import { ThreadListItemPrimitiveUnarchive } from "./ThreadListItemUnarchive";
|
|
14
|
+
|
|
15
|
+
afterEach(cleanup);
|
|
16
|
+
|
|
17
|
+
describe("ThreadListItemPrimitive.Unarchive", () => {
|
|
18
|
+
it.each([true, false])(
|
|
19
|
+
"renders an actionable button only when unarchive is supported (%s)",
|
|
20
|
+
(supported) => {
|
|
21
|
+
const onUnarchive = vi.fn();
|
|
22
|
+
const runtime = new AssistantRuntimeImpl(
|
|
23
|
+
new ExternalStoreRuntimeCore({
|
|
24
|
+
messages: [],
|
|
25
|
+
onNew: async () => {},
|
|
26
|
+
adapters: {
|
|
27
|
+
threadList: {
|
|
28
|
+
archivedThreads: [{ id: "archived", status: "archived" }],
|
|
29
|
+
onUnarchive: supported ? onUnarchive : undefined,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
34
|
+
const { getByRole } = render(
|
|
35
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
36
|
+
<ThreadListItemByIndexProvider index={0} archived>
|
|
37
|
+
<ThreadListItemPrimitiveUnarchive disabled={false}>
|
|
38
|
+
Restore
|
|
39
|
+
</ThreadListItemPrimitiveUnarchive>
|
|
40
|
+
</ThreadListItemByIndexProvider>
|
|
41
|
+
</AssistantRuntimeProvider>,
|
|
42
|
+
);
|
|
43
|
+
const button = getByRole("button", {
|
|
44
|
+
name: "Restore",
|
|
45
|
+
}) as HTMLButtonElement;
|
|
46
|
+
expect(button.disabled).toBe(!supported);
|
|
47
|
+
fireEvent.click(button);
|
|
48
|
+
if (supported) expect(onUnarchive).toHaveBeenCalledWith("archived");
|
|
49
|
+
else expect(onUnarchive).not.toHaveBeenCalled();
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
});
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { useThreadListItemUnarchive as useThreadListItemUnarchiveBehavior } from "@assistant-ui/core/react";
|
|
9
9
|
|
|
10
10
|
const useThreadListItemUnarchive = () => {
|
|
11
|
-
const { unarchive } = useThreadListItemUnarchiveBehavior();
|
|
12
|
-
return unarchive;
|
|
11
|
+
const { unarchive, disabled } = useThreadListItemUnarchiveBehavior();
|
|
12
|
+
return disabled ? null : unarchive;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export namespace ThreadListItemPrimitiveUnarchive {
|
|
@@ -112,6 +112,31 @@ describe("thread list keyboard navigation", () => {
|
|
|
112
112
|
expect(document.activeElement).toBe(first);
|
|
113
113
|
});
|
|
114
114
|
|
|
115
|
+
it("skips disabled triggers in both directions without wrapping", () => {
|
|
116
|
+
const { container } = render(
|
|
117
|
+
<ThreadListPrimitiveRoot>
|
|
118
|
+
{[0, 1, 2].map((i) => (
|
|
119
|
+
<ThreadListItemPrimitiveRoot key={i}>
|
|
120
|
+
<ThreadListItemPrimitiveTrigger disabled={i === 1}>
|
|
121
|
+
item {i}
|
|
122
|
+
</ThreadListItemPrimitiveTrigger>
|
|
123
|
+
</ThreadListItemPrimitiveRoot>
|
|
124
|
+
))}
|
|
125
|
+
</ThreadListPrimitiveRoot>,
|
|
126
|
+
);
|
|
127
|
+
const [first, , third] = triggers(container);
|
|
128
|
+
|
|
129
|
+
first!.focus();
|
|
130
|
+
expect(fireEvent.keyDown(first!, { key: "ArrowDown" })).toBe(false);
|
|
131
|
+
expect(document.activeElement).toBe(third);
|
|
132
|
+
expect(fireEvent.keyDown(third!, { key: "ArrowDown" })).toBe(true);
|
|
133
|
+
expect(document.activeElement).toBe(third);
|
|
134
|
+
expect(fireEvent.keyDown(third!, { key: "ArrowUp" })).toBe(false);
|
|
135
|
+
expect(document.activeElement).toBe(first);
|
|
136
|
+
expect(fireEvent.keyDown(first!, { key: "ArrowUp" })).toBe(true);
|
|
137
|
+
expect(document.activeElement).toBe(first);
|
|
138
|
+
});
|
|
139
|
+
|
|
115
140
|
it("moves between an item and its More button with right/left arrows", () => {
|
|
116
141
|
const { trigger, more } = renderItem();
|
|
117
142
|
|
|
@@ -15,7 +15,7 @@ import { useAui } from "@assistant-ui/store";
|
|
|
15
15
|
import { AssistantRuntimeProvider } from "../context";
|
|
16
16
|
import * as MessagePrimitive from "../primitives/message";
|
|
17
17
|
import * as ThreadPrimitive from "../primitives/thread";
|
|
18
|
-
import { useLocalRuntime } from "
|
|
18
|
+
import { useLocalRuntime } from "@assistant-ui/core/react";
|
|
19
19
|
import {
|
|
20
20
|
useAssistantDataUI,
|
|
21
21
|
type ChatModelAdapter,
|