@assistant-ui/react 0.15.23 → 0.15.25
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/README.md +44 -23
- package/dist/assistant-transport.js.map +1 -1
- package/dist/cloud-renderer/CloudRendererHost.js.map +1 -1
- package/dist/context/providers/MessageProvider.js.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
- package/dist/hooks/useToolCallElapsed.d.ts +3 -1
- package/dist/hooks/useToolCallElapsed.d.ts.map +1 -1
- package/dist/hooks/useToolCallElapsed.js +7 -8
- package/dist/hooks/useToolCallElapsed.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
- package/dist/mcp-apps/app-frame.js.map +1 -1
- package/dist/model-context/frame/useAssistantFrameHost.js.map +1 -1
- package/dist/model-context/makeAssistantVisible.d.ts +1 -0
- package/dist/model-context/makeAssistantVisible.d.ts.map +1 -1
- package/dist/model-context/makeAssistantVisible.js +31 -12
- package/dist/model-context/makeAssistantVisible.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackNegative.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarFeedbackPositive.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarReload.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarRoot.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarSpeak.js.map +1 -1
- package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -1
- package/dist/primitives/actionBar/useActionBarFloatStatus.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreContent.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreItem.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreRoot.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreSeparator.js.map +1 -1
- package/dist/primitives/actionBarMore/ActionBarMoreTrigger.js.map +1 -1
- package/dist/primitives/actionBarMore/scope.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalAnchor.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalContent.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalRoot.js.map +1 -1
- package/dist/primitives/assistantModal/AssistantModalTrigger.js.map +1 -1
- package/dist/primitives/assistantModal/popoverRenderPrimitives.js.map +1 -1
- package/dist/primitives/assistantModal/scope.js.map +1 -1
- package/dist/primitives/attachment/AttachmentName.js.map +1 -1
- package/dist/primitives/attachment/AttachmentRemove.js.map +1 -1
- package/dist/primitives/attachment/AttachmentRoot.js.map +1 -1
- package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerCount.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNext.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerNumber.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerPrevious.js.map +1 -1
- package/dist/primitives/branchPicker/BranchPickerRoot.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
- package/dist/primitives/chainOfThought/ChainOfThoughtRoot.js.map +1 -1
- package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
- package/dist/primitives/composer/ComposerCancel.js.map +1 -1
- package/dist/primitives/composer/ComposerDictate.js.map +1 -1
- package/dist/primitives/composer/ComposerDictationTranscript.js.map +1 -1
- package/dist/primitives/composer/ComposerInput.d.ts +1 -1
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +4 -3
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/ComposerInputPluginContext.js.map +1 -1
- package/dist/primitives/composer/ComposerQuote.js.map +1 -1
- package/dist/primitives/composer/ComposerRoot.js.map +1 -1
- package/dist/primitives/composer/ComposerSend.js.map +1 -1
- package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts +11 -11
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +62 -60
- package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverAction.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js +6 -6
- package/dist/primitives/composer/trigger/TriggerPopoverAction.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverBack.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts +3 -3
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverCategories.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts +9 -9
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js +7 -7
- package/dist/primitives/composer/trigger/TriggerPopoverDirective.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts +5 -5
- package/dist/primitives/composer/trigger/TriggerPopoverItems.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverItems.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverResource.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +8 -8
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
- package/dist/primitives/composer/trigger/index.d.ts +1 -1
- package/dist/primitives/composer/trigger/index.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerDetectionResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerNavigationResource.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerSelectionResource.js.map +1 -1
- package/dist/primitives/composer/useComposerInputState.js.map +1 -1
- package/dist/primitives/composer.d.ts +20 -1
- package/dist/primitives/composer.d.ts.map +1 -1
- package/dist/primitives/composer.js +8 -1
- package/dist/primitives/composer.js.map +1 -1
- package/dist/primitives/dropdownMenuRenderPrimitives.js.map +1 -1
- package/dist/primitives/error/ErrorMessage.js.map +1 -1
- package/dist/primitives/error/ErrorRoot.js.map +1 -1
- package/dist/primitives/message/MessageIf.js.map +1 -1
- package/dist/primitives/message/MessageParts.js.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js +42 -17
- package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
- package/dist/primitives/message/MessageRoot.js.map +1 -1
- package/dist/primitives/messagePart/MessagePartImage.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemRemove.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemSteer.js.map +1 -1
- package/dist/primitives/queueItem/QueueItemText.js.map +1 -1
- package/dist/primitives/reasoning/useScrollLock.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -1
- package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
- package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
- package/dist/primitives/thread/ThreadIf.js.map +1 -1
- package/dist/primitives/thread/ThreadLoadEarlier.d.ts +19 -0
- package/dist/primitives/thread/ThreadLoadEarlier.d.ts.map +1 -0
- package/dist/primitives/thread/ThreadLoadEarlier.js +36 -0
- package/dist/primitives/thread/ThreadLoadEarlier.js.map +1 -0
- package/dist/primitives/thread/ThreadMessages.d.ts +1 -1
- package/dist/primitives/thread/ThreadMessages.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadMessages.js +2 -2
- package/dist/primitives/thread/ThreadRoot.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadRoot.js +2 -0
- package/dist/primitives/thread/ThreadRoot.js.map +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
- package/dist/primitives/thread/ThreadSuggestion.js.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +111 -2
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/thread.d.ts +2 -0
- package/dist/primitives/thread.d.ts.map +1 -1
- package/dist/primitives/thread.js +5 -2
- package/dist/primitives/thread.js.map +1 -1
- package/dist/primitives/threadList/ThreadListLoadMore.js.map +1 -1
- package/dist/primitives/threadList/ThreadListNew.js.map +1 -1
- package/dist/primitives/threadList/ThreadListRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemArchive.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemDelete.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemUnarchive.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreContent.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreItem.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreRoot.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreSeparator.js.map +1 -1
- package/dist/primitives/threadListItemMore/ThreadListItemMoreTrigger.js.map +1 -1
- package/dist/primitives/threadListItemMore/scope.js.map +1 -1
- package/dist/sandbox-host/SandboxHost.d.ts.map +1 -1
- package/dist/sandbox-host/SandboxHost.js +6 -1
- package/dist/sandbox-host/SandboxHost.js.map +1 -1
- package/dist/unstable/useMessageStallDetection.d.ts.map +1 -1
- package/dist/unstable/useMessageStallDetection.js +10 -6
- package/dist/unstable/useMessageStallDetection.js.map +1 -1
- package/dist/unstable/useModelContextSnapshot.js.map +1 -1
- package/dist/unstable/webmcp/WebMcpRegistrationResource.js.map +1 -1
- package/dist/unstable/webmcp/useWebMcpProvider.js.map +1 -1
- package/dist/utils/Primitive.js.map +1 -1
- package/dist/utils/createActionButton.js.map +1 -1
- package/dist/utils/hooks/useManagedRef.js.map +1 -1
- package/dist/utils/hooks/useMediaQuery.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.js.map +1 -1
- package/dist/utils/hooks/useSizeHandle.js.map +1 -1
- package/dist/utils/isCompositionKey.d.ts +2 -0
- package/dist/utils/isCompositionKey.d.ts.map +1 -0
- package/dist/utils/isCompositionKey.js +6 -0
- package/dist/utils/isCompositionKey.js.map +1 -0
- package/dist/utils/smooth/SmoothContext.js.map +1 -1
- package/dist/utils/smooth/useSmooth.js +6 -6
- package/dist/utils/smooth/useSmooth.js.map +1 -1
- package/package.json +12 -11
- package/src/hooks/useToolCallElapsed.test.tsx +35 -0
- package/src/hooks/useToolCallElapsed.ts +9 -7
- package/src/index.ts +28 -3
- package/src/model-context/makeAssistantVisible.test.tsx +315 -5
- package/src/model-context/makeAssistantVisible.tsx +43 -7
- package/src/primitives/composer/ComposerInput.test.tsx +33 -1
- package/src/primitives/composer/ComposerInput.tsx +4 -3
- package/src/primitives/composer/trigger/TriggerPopover.tsx +11 -11
- package/src/primitives/composer/trigger/TriggerPopoverAction.tsx +10 -13
- package/src/primitives/composer/trigger/TriggerPopoverCategories.tsx +2 -2
- package/src/primitives/composer/trigger/TriggerPopoverDirective.tsx +11 -14
- package/src/primitives/composer/trigger/TriggerPopoverExports.test.ts +61 -0
- package/src/primitives/composer/trigger/TriggerPopoverItems.tsx +3 -3
- package/src/primitives/composer/trigger/TriggerPopoverRootContext.tsx +8 -8
- package/src/primitives/composer.ts +21 -1
- package/src/primitives/message/MessagePartsGrouped.test.tsx +271 -1
- package/src/primitives/message/MessagePartsGrouped.tsx +14 -6
- package/src/primitives/message/MessageRoot.test.tsx +125 -2
- package/src/primitives/thread/ThreadLoadEarlier.tsx +35 -0
- package/src/primitives/thread/ThreadMessages.tsx +1 -0
- package/src/primitives/thread/ThreadRoot.test.tsx +33 -0
- package/src/primitives/thread/ThreadRoot.tsx +3 -0
- package/src/primitives/thread/useThreadViewportAutoScroll.test.tsx +256 -5
- package/src/primitives/thread/useThreadViewportAutoScroll.ts +147 -1
- package/src/primitives/thread.ts +2 -0
- package/src/sandbox-host/SandboxHost.test.tsx +34 -0
- package/src/sandbox-host/SandboxHost.tsx +8 -4
- package/src/tests/toolCallTiming.test.tsx +19 -2
- package/src/unstable/useMessageStallDetection.test.tsx +40 -0
- package/src/unstable/useMessageStallDetection.ts +10 -6
- package/src/utils/isCompositionKey.ts +5 -0
- package/src/utils/smooth/useSmooth.test.tsx +16 -5
- package/src/utils/smooth/useSmooth.ts +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadListItemMoreSeparator.js","names":["c","_c","ComponentRef","forwardRef","DropdownMenu","DropdownMenuPrimitive","WithRenderPropProps","DropdownMenuRenderSeparator","ScopedProps","useDropdownMenuScope","ThreadListItemMorePrimitiveSeparator","Element","Separator","Props","t0","ref","$","__scopeThreadListItemMore","rest","scope","t1","displayName"],"sources":["../../../src/primitives/threadListItemMore/ThreadListItemMoreSeparator.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ComponentRef, forwardRef } from \"react\";\nimport type { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { WithRenderPropProps } from \"../../utils/Primitive\";\nimport { DropdownMenuRenderSeparator } from \"../dropdownMenuRenderPrimitives\";\nimport { type ScopedProps, useDropdownMenuScope } from \"./scope\";\n\nexport namespace ThreadListItemMorePrimitiveSeparator {\n export type Element = ComponentRef<typeof DropdownMenuPrimitive.Separator>;\n export type Props = WithRenderPropProps<\n typeof DropdownMenuPrimitive.Separator\n >;\n}\n\nexport const ThreadListItemMorePrimitiveSeparator = forwardRef<\n ThreadListItemMorePrimitiveSeparator.Element,\n ThreadListItemMorePrimitiveSeparator.Props\n>(\n (\n {\n __scopeThreadListItemMore,\n ...rest\n }: ScopedProps<ThreadListItemMorePrimitiveSeparator.Props>,\n ref,\n ) => {\n const scope = useDropdownMenuScope(__scopeThreadListItemMore);\n\n return <DropdownMenuRenderSeparator {...scope} {...rest} ref={ref} />;\n },\n);\n\nThreadListItemMorePrimitiveSeparator.displayName =\n \"ThreadListItemMorePrimitive.Separator\";\n"],"mappings":";;;;;;;AAeA,MAAaU,uCAAuCP,YAIlDW,IAAAC,QAAA;CAAA,MAAAC,IAAAf,EAAA,CAAA;CAAA,IAAAgB;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAF,IAAA;EACE,CAAA,CAAAG,2BAAA,GAAAC,QAAAJ;EAG0DE,EAAA,KAAAF;EAAAE,EAAA,KAAAC;EAAAD,EAAA,KAAAE;CAAA,OAAA;EAAAD,4BAAAD,EAAA;EAAAE,OAAAF,EAAA;CAAA;CAG1D,MAAAG,QAAcV,qBAAqBQ,yBAAyB;CAAE,IAAAG;CAAA,IAAAJ,EAAA,OAAAD,OAAAC,EAAA,OAAAE,QAAAF,EAAA,OAAAG,OAAA;EAEvDC,KAAA,oBAAC,6BAAD;GAA4B,GAAKD;GAAK,GAAMD;GAAWH;EAAG,CAAA;EAAIC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAA9DI;AAA8D,CAEzE;AAEAV,qCAAqCW,cACnC"}
|
|
1
|
+
{"version":3,"file":"ThreadListItemMoreSeparator.js","names":["c","_c","ComponentRef","forwardRef","DropdownMenu","DropdownMenuPrimitive","WithRenderPropProps","DropdownMenuRenderSeparator","ScopedProps","useDropdownMenuScope","ThreadListItemMorePrimitiveSeparator","Element","Separator","Props","t0","ref","$","__scopeThreadListItemMore","rest","scope","t1","displayName","_c"],"sources":["../../../src/primitives/threadListItemMore/ThreadListItemMoreSeparator.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ComponentRef, forwardRef } from \"react\";\nimport type { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { WithRenderPropProps } from \"../../utils/Primitive\";\nimport { DropdownMenuRenderSeparator } from \"../dropdownMenuRenderPrimitives\";\nimport { type ScopedProps, useDropdownMenuScope } from \"./scope\";\n\nexport namespace ThreadListItemMorePrimitiveSeparator {\n export type Element = ComponentRef<typeof DropdownMenuPrimitive.Separator>;\n export type Props = WithRenderPropProps<\n typeof DropdownMenuPrimitive.Separator\n >;\n}\n\nexport const ThreadListItemMorePrimitiveSeparator = forwardRef<\n ThreadListItemMorePrimitiveSeparator.Element,\n ThreadListItemMorePrimitiveSeparator.Props\n>(\n (\n {\n __scopeThreadListItemMore,\n ...rest\n }: ScopedProps<ThreadListItemMorePrimitiveSeparator.Props>,\n ref,\n ) => {\n const scope = useDropdownMenuScope(__scopeThreadListItemMore);\n\n return <DropdownMenuRenderSeparator {...scope} {...rest} ref={ref} />;\n },\n);\n\nThreadListItemMorePrimitiveSeparator.displayName =\n \"ThreadListItemMorePrimitive.Separator\";\n"],"mappings":";;;;;;;AAeA,MAAaU,uCAAuCP,YAIlDW,IAAAC,QAAA;CAAA,MAAAC,IAAAf,EAAA,CAAA;CAAA,IAAAgB;CAAA,IAAAC;CAAA,IAAAF,EAAA,OAAAF,IAAA;EACE,CAAA,CAAAG,2BAAA,GAAAC,QAAAJ;EAG0DE,EAAA,KAAAF;EAAAE,EAAA,KAAAC;EAAAD,EAAA,KAAAE;CAAA,OAAA;EAAAD,4BAAAD,EAAA;EAAAE,OAAAF,EAAA;CAAA;CAG1D,MAAAG,QAAcV,qBAAqBQ,yBAAyB;CAAE,IAAAG;CAAA,IAAAJ,EAAA,OAAAD,OAAAC,EAAA,OAAAE,QAAAF,EAAA,OAAAG,OAAA;EAEvDC,KAAA,oBAAC,6BAAD;GAA4B,GAAKD;GAAK,GAAMD;GAAWH;EAAG,CAAA;EAAIC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAA9DI;AAA8D,CAEzE;AAEAV,qCAAqCW,cACnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadListItemMoreTrigger.js","names":["c","_c","ComponentRef","forwardRef","Direction","DropdownMenu","DropdownMenuPrimitive","useComposedRefs","composeEventHandlers","WithRenderPropProps","DropdownMenuRenderTrigger","useThreadListItemFocus","useThreadListItemMoreSharedFocusGroup","useThreadListItemMoreSetOpen","ScopedProps","useDropdownMenuScope","ThreadListItemMorePrimitiveTrigger","Element","Trigger","Props","t0","ref","$","__scopeThreadListItemMore","rest","scope","focus","setOpen","sharedFocusGroup","composedRef","moreRef","direction","useDirection","openKey","T0","t1","event","key","altKey","ctrlKey","metaKey","shiftKey","preventDefault","t2","onKeyDown","t3","displayName"],"sources":["../../../src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ComponentRef, forwardRef } from \"react\";\nimport {\n Direction,\n type DropdownMenu as DropdownMenuPrimitive,\n} from \"radix-ui\";\nimport { useComposedRefs } from \"radix-ui/internal\";\nimport { composeEventHandlers } from \"radix-ui/internal\";\nimport type { WithRenderPropProps } from \"../../utils/Primitive\";\nimport { DropdownMenuRenderTrigger } from \"../dropdownMenuRenderPrimitives\";\nimport { useThreadListItemFocus } from \"../threadListFocusGroup\";\nimport {\n useThreadListItemMoreSharedFocusGroup,\n useThreadListItemMoreSetOpen,\n} from \"./ThreadListItemMoreRoot\";\nimport { type ScopedProps, useDropdownMenuScope } from \"./scope\";\n\nexport namespace ThreadListItemMorePrimitiveTrigger {\n export type Element = ComponentRef<typeof DropdownMenuPrimitive.Trigger>;\n export type Props = WithRenderPropProps<typeof DropdownMenuPrimitive.Trigger>;\n}\n\nexport const ThreadListItemMorePrimitiveTrigger = forwardRef<\n ThreadListItemMorePrimitiveTrigger.Element,\n ThreadListItemMorePrimitiveTrigger.Props\n>(\n (\n {\n __scopeThreadListItemMore,\n ...rest\n }: ScopedProps<ThreadListItemMorePrimitiveTrigger.Props>,\n ref,\n ) => {\n const scope = useDropdownMenuScope(__scopeThreadListItemMore);\n const focus = useThreadListItemFocus();\n const setOpen = useThreadListItemMoreSetOpen();\n const sharedFocusGroup = useThreadListItemMoreSharedFocusGroup();\n const composedRef = useComposedRefs(ref, focus?.moreRef);\n const direction = Direction.useDirection();\n const openKey = direction === \"rtl\" ? \"ArrowLeft\" : \"ArrowRight\";\n\n return (\n <DropdownMenuRenderTrigger\n {...scope}\n {...rest}\n onKeyDown={composeEventHandlers(rest.onKeyDown, (event) => {\n if (!sharedFocusGroup || event.key !== openKey) return;\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)\n return;\n event.preventDefault();\n setOpen(true);\n })}\n ref={composedRef}\n />\n );\n },\n);\n\nThreadListItemMorePrimitiveTrigger.displayName =\n \"ThreadListItemMorePrimitive.Trigger\";\n"],"mappings":";;;;;;;;;;;AAuBA,MAAagB,qCAAqCb,YAIhDiB,IAAAC,QAAA;CAAA,MAAAC,IAAArB,EAAA,EAAA;CACE,MAAA,EAAAsB,2BAAA,GAAAC,SAAAJ;CAMA,MAAAK,QAAcV,qBAAqBQ,yBAAyB;CAC5D,MAAAG,QAAcf,uBAAuB;CACrC,MAAAgB,UAAgBd,6BAA6B;CAC7C,MAAAe,mBAAyBhB,sCAAsC;CAC/D,MAAAiB,cAAoBtB,gBAAgBc,KAAKK,OAAKI,OAAS;CAEvD,MAAAG,UADkB7B,UAAS4B,aACXD,MAAc,QAAd,cAAA;CAGb,MAAAG,KAAAxB;CAAyB,IAAAyB;CAAA,IAAAb,EAAA,OAAAW,WAAAX,EAAA,OAAAK,WAAAL,EAAA,OAAAM,kBAAA;EAGwBO,MAAAC,UAAA;GAC9C,IAAI,CAACR,oBAAoBQ,MAAKC,QAASJ,SAAO;GAC9C,IAAIG,MAAKE,UAAWF,MAAKG,WAAYH,MAAKI,WAAYJ,MAAKK,UAAS;GAEpEL,MAAKM,eAAgB;GACrBf,QAAQ,IAAI;EAAC;EACdL,EAAA,KAAAW;EAAAX,EAAA,KAAAK;EAAAL,EAAA,KAAAM;EAAAN,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CANU,MAAAqB,KAAAnC,qBAAqBgB,KAAIoB,WAAYT,EAM/C;CAAC,IAAAU;CAAA,IAAAvB,EAAA,OAAAY,MAAAZ,EAAA,OAAAO,eAAAP,EAAA,OAAAE,QAAAF,EAAA,OAAAG,SAAAH,EAAA,OAAAqB,IAAA;EATJE,KAAA,oBAAC,IAAD;GAA0B,GACpBpB;GAAK,GACLD;GACO,WAAAmB;GAONd,KAAAA;EAAW,CAAA;EAChBP,EAAA,KAAAY;EAAAZ,EAAA,KAAAO;EAAAP,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAqB;EAAArB,EAAA,KAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CAAA,OAXFuB;AAWE,CAGR;AAEA7B,mCAAmC8B,cACjC"}
|
|
1
|
+
{"version":3,"file":"ThreadListItemMoreTrigger.js","names":["c","_c","ComponentRef","forwardRef","Direction","DropdownMenu","DropdownMenuPrimitive","useComposedRefs","composeEventHandlers","WithRenderPropProps","DropdownMenuRenderTrigger","useThreadListItemFocus","useThreadListItemMoreSharedFocusGroup","useThreadListItemMoreSetOpen","ScopedProps","useDropdownMenuScope","ThreadListItemMorePrimitiveTrigger","Element","Trigger","Props","t0","ref","$","__scopeThreadListItemMore","rest","scope","focus","setOpen","sharedFocusGroup","composedRef","moreRef","direction","useDirection","openKey","T0","t1","event","key","altKey","ctrlKey","metaKey","shiftKey","preventDefault","t2","onKeyDown","t3","displayName","_c"],"sources":["../../../src/primitives/threadListItemMore/ThreadListItemMoreTrigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { type ComponentRef, forwardRef } from \"react\";\nimport {\n Direction,\n type DropdownMenu as DropdownMenuPrimitive,\n} from \"radix-ui\";\nimport { useComposedRefs } from \"radix-ui/internal\";\nimport { composeEventHandlers } from \"radix-ui/internal\";\nimport type { WithRenderPropProps } from \"../../utils/Primitive\";\nimport { DropdownMenuRenderTrigger } from \"../dropdownMenuRenderPrimitives\";\nimport { useThreadListItemFocus } from \"../threadListFocusGroup\";\nimport {\n useThreadListItemMoreSharedFocusGroup,\n useThreadListItemMoreSetOpen,\n} from \"./ThreadListItemMoreRoot\";\nimport { type ScopedProps, useDropdownMenuScope } from \"./scope\";\n\nexport namespace ThreadListItemMorePrimitiveTrigger {\n export type Element = ComponentRef<typeof DropdownMenuPrimitive.Trigger>;\n export type Props = WithRenderPropProps<typeof DropdownMenuPrimitive.Trigger>;\n}\n\nexport const ThreadListItemMorePrimitiveTrigger = forwardRef<\n ThreadListItemMorePrimitiveTrigger.Element,\n ThreadListItemMorePrimitiveTrigger.Props\n>(\n (\n {\n __scopeThreadListItemMore,\n ...rest\n }: ScopedProps<ThreadListItemMorePrimitiveTrigger.Props>,\n ref,\n ) => {\n const scope = useDropdownMenuScope(__scopeThreadListItemMore);\n const focus = useThreadListItemFocus();\n const setOpen = useThreadListItemMoreSetOpen();\n const sharedFocusGroup = useThreadListItemMoreSharedFocusGroup();\n const composedRef = useComposedRefs(ref, focus?.moreRef);\n const direction = Direction.useDirection();\n const openKey = direction === \"rtl\" ? \"ArrowLeft\" : \"ArrowRight\";\n\n return (\n <DropdownMenuRenderTrigger\n {...scope}\n {...rest}\n onKeyDown={composeEventHandlers(rest.onKeyDown, (event) => {\n if (!sharedFocusGroup || event.key !== openKey) return;\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)\n return;\n event.preventDefault();\n setOpen(true);\n })}\n ref={composedRef}\n />\n );\n },\n);\n\nThreadListItemMorePrimitiveTrigger.displayName =\n \"ThreadListItemMorePrimitive.Trigger\";\n"],"mappings":";;;;;;;;;;;AAuBA,MAAagB,qCAAqCb,YAIhDiB,IAAAC,QAAA;CAAA,MAAAC,IAAArB,EAAA,EAAA;CACE,MAAA,EAAAsB,2BAAA,GAAAC,SAAAJ;CAMA,MAAAK,QAAcV,qBAAqBQ,yBAAyB;CAC5D,MAAAG,QAAcf,uBAAuB;CACrC,MAAAgB,UAAgBd,6BAA6B;CAC7C,MAAAe,mBAAyBhB,sCAAsC;CAC/D,MAAAiB,cAAoBtB,gBAAgBc,KAAKK,OAAKI,OAAS;CAEvD,MAAAG,UADkB7B,UAAS4B,aACXD,MAAc,QAAd,cAAA;CAGb,MAAAG,KAAAxB;CAAyB,IAAAyB;CAAA,IAAAb,EAAA,OAAAW,WAAAX,EAAA,OAAAK,WAAAL,EAAA,OAAAM,kBAAA;EAGwBO,MAAAC,UAAA;GAC9C,IAAI,CAACR,oBAAoBQ,MAAKC,QAASJ,SAAO;GAC9C,IAAIG,MAAKE,UAAWF,MAAKG,WAAYH,MAAKI,WAAYJ,MAAKK,UAAS;GAEpEL,MAAKM,eAAgB;GACrBf,QAAQ,IAAI;EAAC;EACdL,EAAA,KAAAW;EAAAX,EAAA,KAAAK;EAAAL,EAAA,KAAAM;EAAAN,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CANU,MAAAqB,KAAAnC,qBAAqBgB,KAAIoB,WAAYT,EAM/C;CAAC,IAAAU;CAAA,IAAAvB,EAAA,OAAAY,MAAAZ,EAAA,OAAAO,eAAAP,EAAA,OAAAE,QAAAF,EAAA,OAAAG,SAAAH,EAAA,OAAAqB,IAAA;EATJE,KAAA,oBAAC,IAAD;GAA0B,GACpBpB;GAAK,GACLD;GACO,WAAAmB;GAONd,KAAAA;EAAW,CAAA;EAChBP,EAAA,KAAAY;EAAAZ,EAAA,KAAAO;EAAAP,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAqB;EAAArB,EAAA,KAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CAAA,OAXFuB;AAWE,CAGR;AAEA7B,mCAAmC8B,cACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","names":["DropdownMenu","DropdownMenuPrimitive","Context","useDropdownMenuScope","ReturnType","createDropdownMenuScope","ScopedProps","P","__scopeThreadListItemMore","Scope"],"sources":["../../../src/primitives/threadListItemMore/scope.ts"],"sourcesContent":["import { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { Context } from \"radix-ui/internal\";\n\nexport const useDropdownMenuScope: ReturnType<\n typeof DropdownMenuPrimitive.createDropdownMenuScope\n> = DropdownMenuPrimitive.createDropdownMenuScope();\n\nexport type ScopedProps<P> = P & { __scopeThreadListItemMore?: Context.Scope };\n"],"mappings":";;AAGA,MAAaG,uBAETF,aAAsBI,wBAAwB"}
|
|
1
|
+
{"version":3,"file":"scope.js","names":["DropdownMenu","DropdownMenuPrimitive","Context","useDropdownMenuScope","ReturnType","createDropdownMenuScope","ScopedProps","P","__scopeThreadListItemMore","Scope","DropdownMenuPrimitive"],"sources":["../../../src/primitives/threadListItemMore/scope.ts"],"sourcesContent":["import { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport type { Context } from \"radix-ui/internal\";\n\nexport const useDropdownMenuScope: ReturnType<\n typeof DropdownMenuPrimitive.createDropdownMenuScope\n> = DropdownMenuPrimitive.createDropdownMenuScope();\n\nexport type ScopedProps<P> = P & { __scopeThreadListItemMore?: Context.Scope };\n"],"mappings":";;AAGA,MAAaG,uBAETF,aAAsBI,wBAAwB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxHost.d.ts","sourceRoot":"","sources":["../../src/sandbox-host/SandboxHost.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,OAAO,CAAC;AACf,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAO5B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,aAAa,EACb,QAAQ,GAAG,QAAQ,GAAG,aAAa,CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,CACZ,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,cAAc,KACjB,aAAa,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACjE,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAIT;AASD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,UAAU,EACV,OAAO,EACP,SAA8B,EAC9B,YAAY,EACZ,OAAO,EACP,cAAc,GACf,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"SandboxHost.d.ts","sourceRoot":"","sources":["../../src/sandbox-host/SandboxHost.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,OAAO,CAAC;AACf,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAO5B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,aAAa,EACb,QAAQ,GAAG,QAAQ,GAAG,aAAa,CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,CACZ,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,cAAc,KACjB,aAAa,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACjE,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAIT;AASD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,UAAU,EACV,OAAO,EACP,SAA8B,EAC9B,YAAY,EACZ,OAAO,EACP,cAAc,GACf,EAAE,gBAAgB,+BAkKlB"}
|
|
@@ -69,6 +69,7 @@ function SandboxHost(t0) {
|
|
|
69
69
|
let frame = null;
|
|
70
70
|
let bridge = null;
|
|
71
71
|
let onMessage = null;
|
|
72
|
+
const renderController = new AbortController();
|
|
72
73
|
const { content: liveContent, sandbox: sb } = liveRef.current;
|
|
73
74
|
const reportError = (err) => {
|
|
74
75
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -80,7 +81,10 @@ function SandboxHost(t0) {
|
|
|
80
81
|
...sb?.enableBrowserCaching !== void 0 && { enableBrowserCaching: sb.enableBrowserCaching },
|
|
81
82
|
...sb?.salt !== void 0 && { salt: sb.salt }
|
|
82
83
|
});
|
|
83
|
-
const renderOpts =
|
|
84
|
+
const renderOpts = {
|
|
85
|
+
signal: renderController.signal,
|
|
86
|
+
...sb?.unsafeDocumentWrite !== void 0 && { unsafeDocumentWrite: sb.unsafeDocumentWrite }
|
|
87
|
+
};
|
|
84
88
|
scf.renderHtml(liveContent.html, container, renderOpts).then((rendered) => {
|
|
85
89
|
if (cancelled) {
|
|
86
90
|
rendered.dispose();
|
|
@@ -134,6 +138,7 @@ function SandboxHost(t0) {
|
|
|
134
138
|
const bridgeToDispose = bridge;
|
|
135
139
|
bridge = null;
|
|
136
140
|
if (bridgeToDispose) runCleanup(() => bridgeToDispose.dispose());
|
|
141
|
+
runCleanup(() => renderController.abort());
|
|
137
142
|
const frameToDispose = frame;
|
|
138
143
|
frame = null;
|
|
139
144
|
if (frameToDispose) runCleanup(() => frameToDispose.dispose());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxHost.js","names":["c","_c","CSSProperties","useEffect","useLayoutEffect","useRef","useState","isShimLoadError","RenderedFrame","SafeContentFrame","SandboxOption","invokeUserCallback","DEFAULT_PRODUCT","DEFAULT_MAX_HEIGHT","LOAD_TIMEOUT_MS","SandboxHostConfig","sandbox","useShadowDom","enableBrowserCaching","salt","product","className","style","unsafeDocumentWrite","SandboxHostFrame","Pick","SandboxHostApi","setHeight","height","SandboxBridge","onMessage","event","MessageEvent","dispose","SandboxContent","html","SandboxHostProps","content","contentKey","maxHeight","createBridge","frame","host","onError","error","Error","containerProps","Record","isSandboxFrameMessage","iframe","HTMLIFrameElement","origin","source","contentWindow","LiveSnapshot","SandboxHost","t0","$","t1","undefined","containerRef","contentHeight","setContentHeight","t2","liveRef","t3","t4","current","t5","Symbol","for","container","cancelled","bridge","liveContent","sb","reportError","err","String","bind","scf","renderOpts","renderHtml","then","rendered","hostApi","Number","isFinite","sendMessage","window","addEventListener","fullyLoadedPromiseWithTimeout","catch","err_0","code","err_1","cleanupFailed","cleanupError","runCleanup","cleanup","t6","console","listener","removeEventListener","bridgeToDispose","frameToDispose","resolvedHeight","Math","min","t7","mergedStyle","t8","t9"],"sources":["../../src/sandbox-host/SandboxHost.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type CSSProperties,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n isShimLoadError,\n type RenderedFrame,\n SafeContentFrame,\n type SandboxOption,\n} from \"safe-content-frame\";\nimport { invokeUserCallback } from \"@assistant-ui/core/internal\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-sandbox\";\nconst DEFAULT_MAX_HEIGHT = 800;\nconst LOAD_TIMEOUT_MS = 10_000;\n\nexport type SandboxHostConfig = {\n sandbox?: SandboxOption[];\n useShadowDom?: boolean;\n enableBrowserCaching?: boolean;\n salt?: string;\n product?: string;\n className?: string;\n style?: CSSProperties;\n unsafeDocumentWrite?: boolean;\n};\n\nexport type SandboxHostFrame = Pick<\n RenderedFrame,\n \"iframe\" | \"origin\" | \"sendMessage\"\n>;\n\nexport type SandboxHostApi = {\n setHeight: (height: number) => void;\n};\n\nexport type SandboxBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n};\n\nexport type SandboxContent = { html: string };\n\nexport type SandboxHostProps = {\n content: SandboxContent;\n contentKey: string;\n sandbox?: SandboxHostConfig | undefined;\n maxHeight?: number | undefined;\n createBridge: (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ) => SandboxBridge;\n onError?: ((error: Error) => void) | undefined;\n containerProps?: Record<string, string | undefined> | undefined;\n};\n\nexport function isSandboxFrameMessage(\n event: MessageEvent,\n frame: { iframe: HTMLIFrameElement; origin: string },\n): boolean {\n return (\n event.source === frame.iframe.contentWindow && event.origin === frame.origin\n );\n}\n\ntype LiveSnapshot = {\n content: SandboxContent;\n sandbox: SandboxHostConfig | undefined;\n createBridge: SandboxHostProps[\"createBridge\"];\n onError: SandboxHostProps[\"onError\"];\n};\n\nexport function SandboxHost({\n content,\n contentKey,\n sandbox,\n maxHeight = DEFAULT_MAX_HEIGHT,\n createBridge,\n onError,\n containerProps,\n}: SandboxHostProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [contentHeight, setContentHeight] = useState<number | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n content,\n sandbox,\n createBridge,\n onError,\n });\n useLayoutEffect(() => {\n liveRef.current = { content, sandbox, createBridge, onError };\n }, [content, sandbox, createBridge, onError]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let cancelled = false;\n let frame: RenderedFrame | null = null;\n let bridge: SandboxBridge | null = null;\n let onMessage: ((event: MessageEvent) => void) | null = null;\n\n const { content: liveContent, sandbox: sb } = liveRef.current;\n\n const reportError = (err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n invokeUserCallback(\n \"assistant-ui\",\n \"SandboxHost onError\",\n liveRef.current.onError?.bind(liveRef.current),\n error,\n );\n };\n\n const scf = new SafeContentFrame(sb?.product ?? DEFAULT_PRODUCT, {\n ...(sb?.sandbox !== undefined && { sandbox: sb.sandbox }),\n ...(sb?.useShadowDom !== undefined && { useShadowDom: sb.useShadowDom }),\n ...(sb?.enableBrowserCaching !== undefined && {\n enableBrowserCaching: sb.enableBrowserCaching,\n }),\n ...(sb?.salt !== undefined && { salt: sb.salt }),\n });\n\n const renderOpts =\n sb?.unsafeDocumentWrite !== undefined\n ? { unsafeDocumentWrite: sb.unsafeDocumentWrite }\n : undefined;\n\n scf\n .renderHtml(liveContent.html, container, renderOpts)\n .then((rendered) => {\n if (cancelled) {\n rendered.dispose();\n return;\n }\n frame = rendered;\n\n const hostApi: SandboxHostApi = {\n setHeight: (height) => {\n if (\n typeof height === \"number\" &&\n Number.isFinite(height) &&\n height > 0\n ) {\n setContentHeight(height);\n }\n },\n };\n\n bridge = liveRef.current.createBridge(\n {\n iframe: rendered.iframe,\n origin: rendered.origin,\n sendMessage: rendered.sendMessage,\n },\n hostApi,\n );\n\n // Single owner of the window listener; the cross-origin guard runs\n // here so the bridge only sees frame-validated messages.\n onMessage = (event) => {\n if (!isSandboxFrameMessage(event, rendered)) return;\n bridge?.onMessage(event);\n };\n window.addEventListener(\"message\", onMessage);\n\n // renderHtml resolves at iframe load, which a shim that was never\n // served also reaches, so a completed render is only known once the\n // frame says so. render-timeout is excluded because the shim is\n // running and the guest may still paint, and reporting it would leave\n // a host that renders an error state showing one over a frame that\n // recovers.\n rendered.fullyLoadedPromiseWithTimeout(LOAD_TIMEOUT_MS).catch((err) => {\n if (cancelled) return;\n if (isShimLoadError(err) && err.code === \"render-timeout\") return;\n reportError(err);\n });\n })\n .catch((err) => {\n if (cancelled) return;\n frame?.dispose();\n frame = null;\n reportError(err);\n });\n\n return () => {\n cancelled = true;\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n if (onMessage) {\n const listener = onMessage;\n onMessage = null;\n runCleanup(() => window.removeEventListener(\"message\", listener));\n }\n const bridgeToDispose = bridge;\n bridge = null;\n if (bridgeToDispose) runCleanup(() => bridgeToDispose.dispose());\n const frameToDispose = frame;\n frame = null;\n if (frameToDispose) runCleanup(() => frameToDispose.dispose());\n runCleanup(() => setContentHeight(undefined));\n\n if (cleanupFailed) throw cleanupError;\n };\n // oxlint-disable-next-line react/exhaustive-deps -- re-init only on contentKey change; live values flow through liveRef\n }, [contentKey]);\n\n const resolvedHeight =\n contentHeight != null ? Math.min(contentHeight, maxHeight) : undefined;\n const mergedStyle =\n resolvedHeight != null\n ? { ...sandbox?.style, height: resolvedHeight }\n : sandbox?.style;\n\n return (\n <div\n {...containerProps}\n ref={containerRef}\n className={sandbox?.className}\n style={mergedStyle}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SandboxHost.js","names":["c","_c","CSSProperties","useEffect","useLayoutEffect","useRef","useState","isShimLoadError","RenderedFrame","SafeContentFrame","SandboxOption","invokeUserCallback","DEFAULT_PRODUCT","DEFAULT_MAX_HEIGHT","LOAD_TIMEOUT_MS","SandboxHostConfig","sandbox","useShadowDom","enableBrowserCaching","salt","product","className","style","unsafeDocumentWrite","SandboxHostFrame","Pick","SandboxHostApi","setHeight","height","SandboxBridge","onMessage","event","MessageEvent","dispose","SandboxContent","html","SandboxHostProps","content","contentKey","maxHeight","createBridge","frame","host","onError","error","Error","containerProps","Record","isSandboxFrameMessage","iframe","HTMLIFrameElement","origin","source","contentWindow","LiveSnapshot","SandboxHost","t0","$","t1","undefined","containerRef","contentHeight","setContentHeight","t2","liveRef","t3","t4","current","t5","Symbol","for","container","cancelled","bridge","renderController","AbortController","liveContent","sb","reportError","err","String","bind","scf","renderOpts","signal","renderHtml","then","rendered","hostApi","Number","isFinite","sendMessage","window","addEventListener","fullyLoadedPromiseWithTimeout","catch","err_0","code","err_1","cleanupFailed","cleanupError","runCleanup","cleanup","t6","console","listener","removeEventListener","bridgeToDispose","abort","frameToDispose","resolvedHeight","Math","min","t7","mergedStyle","t8","t9","_c"],"sources":["../../src/sandbox-host/SandboxHost.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type CSSProperties,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n isShimLoadError,\n type RenderedFrame,\n SafeContentFrame,\n type SandboxOption,\n} from \"safe-content-frame\";\nimport { invokeUserCallback } from \"@assistant-ui/core/internal\";\n\nconst DEFAULT_PRODUCT = \"assistant-ui-sandbox\";\nconst DEFAULT_MAX_HEIGHT = 800;\nconst LOAD_TIMEOUT_MS = 10_000;\n\nexport type SandboxHostConfig = {\n sandbox?: SandboxOption[];\n useShadowDom?: boolean;\n enableBrowserCaching?: boolean;\n salt?: string;\n product?: string;\n className?: string;\n style?: CSSProperties;\n unsafeDocumentWrite?: boolean;\n};\n\nexport type SandboxHostFrame = Pick<\n RenderedFrame,\n \"iframe\" | \"origin\" | \"sendMessage\"\n>;\n\nexport type SandboxHostApi = {\n setHeight: (height: number) => void;\n};\n\nexport type SandboxBridge = {\n onMessage: (event: MessageEvent) => void;\n dispose: () => void;\n};\n\nexport type SandboxContent = { html: string };\n\nexport type SandboxHostProps = {\n content: SandboxContent;\n contentKey: string;\n sandbox?: SandboxHostConfig | undefined;\n maxHeight?: number | undefined;\n createBridge: (\n frame: SandboxHostFrame,\n host: SandboxHostApi,\n ) => SandboxBridge;\n onError?: ((error: Error) => void) | undefined;\n containerProps?: Record<string, string | undefined> | undefined;\n};\n\nexport function isSandboxFrameMessage(\n event: MessageEvent,\n frame: { iframe: HTMLIFrameElement; origin: string },\n): boolean {\n return (\n event.source === frame.iframe.contentWindow && event.origin === frame.origin\n );\n}\n\ntype LiveSnapshot = {\n content: SandboxContent;\n sandbox: SandboxHostConfig | undefined;\n createBridge: SandboxHostProps[\"createBridge\"];\n onError: SandboxHostProps[\"onError\"];\n};\n\nexport function SandboxHost({\n content,\n contentKey,\n sandbox,\n maxHeight = DEFAULT_MAX_HEIGHT,\n createBridge,\n onError,\n containerProps,\n}: SandboxHostProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [contentHeight, setContentHeight] = useState<number | undefined>(\n undefined,\n );\n\n const liveRef = useRef<LiveSnapshot>({\n content,\n sandbox,\n createBridge,\n onError,\n });\n useLayoutEffect(() => {\n liveRef.current = { content, sandbox, createBridge, onError };\n }, [content, sandbox, createBridge, onError]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n let cancelled = false;\n let frame: RenderedFrame | null = null;\n let bridge: SandboxBridge | null = null;\n let onMessage: ((event: MessageEvent) => void) | null = null;\n const renderController = new AbortController();\n\n const { content: liveContent, sandbox: sb } = liveRef.current;\n\n const reportError = (err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n invokeUserCallback(\n \"assistant-ui\",\n \"SandboxHost onError\",\n liveRef.current.onError?.bind(liveRef.current),\n error,\n );\n };\n\n const scf = new SafeContentFrame(sb?.product ?? DEFAULT_PRODUCT, {\n ...(sb?.sandbox !== undefined && { sandbox: sb.sandbox }),\n ...(sb?.useShadowDom !== undefined && { useShadowDom: sb.useShadowDom }),\n ...(sb?.enableBrowserCaching !== undefined && {\n enableBrowserCaching: sb.enableBrowserCaching,\n }),\n ...(sb?.salt !== undefined && { salt: sb.salt }),\n });\n\n const renderOpts = {\n signal: renderController.signal,\n ...(sb?.unsafeDocumentWrite !== undefined && {\n unsafeDocumentWrite: sb.unsafeDocumentWrite,\n }),\n };\n\n scf\n .renderHtml(liveContent.html, container, renderOpts)\n .then((rendered) => {\n if (cancelled) {\n rendered.dispose();\n return;\n }\n frame = rendered;\n\n const hostApi: SandboxHostApi = {\n setHeight: (height) => {\n if (\n typeof height === \"number\" &&\n Number.isFinite(height) &&\n height > 0\n ) {\n setContentHeight(height);\n }\n },\n };\n\n bridge = liveRef.current.createBridge(\n {\n iframe: rendered.iframe,\n origin: rendered.origin,\n sendMessage: rendered.sendMessage,\n },\n hostApi,\n );\n\n // Single owner of the window listener; the cross-origin guard runs\n // here so the bridge only sees frame-validated messages.\n onMessage = (event) => {\n if (!isSandboxFrameMessage(event, rendered)) return;\n bridge?.onMessage(event);\n };\n window.addEventListener(\"message\", onMessage);\n\n // renderHtml resolves at iframe load, which a shim that was never\n // served also reaches, so a completed render is only known once the\n // frame says so. render-timeout is excluded because the shim is\n // running and the guest may still paint, and reporting it would leave\n // a host that renders an error state showing one over a frame that\n // recovers.\n rendered.fullyLoadedPromiseWithTimeout(LOAD_TIMEOUT_MS).catch((err) => {\n if (cancelled) return;\n if (isShimLoadError(err) && err.code === \"render-timeout\") return;\n reportError(err);\n });\n })\n .catch((err) => {\n if (cancelled) return;\n frame?.dispose();\n frame = null;\n reportError(err);\n });\n\n return () => {\n cancelled = true;\n let cleanupFailed = false;\n let cleanupError: unknown;\n const runCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch (error) {\n if (cleanupFailed) {\n console.error(error);\n } else {\n cleanupFailed = true;\n cleanupError = error;\n }\n }\n };\n\n if (onMessage) {\n const listener = onMessage;\n onMessage = null;\n runCleanup(() => window.removeEventListener(\"message\", listener));\n }\n const bridgeToDispose = bridge;\n bridge = null;\n if (bridgeToDispose) runCleanup(() => bridgeToDispose.dispose());\n runCleanup(() => renderController.abort());\n const frameToDispose = frame;\n frame = null;\n if (frameToDispose) runCleanup(() => frameToDispose.dispose());\n runCleanup(() => setContentHeight(undefined));\n\n if (cleanupFailed) throw cleanupError;\n };\n // oxlint-disable-next-line react/exhaustive-deps -- re-init only on contentKey change; live values flow through liveRef\n }, [contentKey]);\n\n const resolvedHeight =\n contentHeight != null ? Math.min(contentHeight, maxHeight) : undefined;\n const mergedStyle =\n resolvedHeight != null\n ? { ...sandbox?.style, height: resolvedHeight }\n : sandbox?.style;\n\n return (\n <div\n {...containerProps}\n ref={containerRef}\n className={sandbox?.className}\n style={mergedStyle}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageStallDetection.d.ts","sourceRoot":"","sources":["../../src/unstable/useMessageStallDetection.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,qCAAqC,GAAG;IAClD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,qCAAqC,GAC9C,8BAA8B,
|
|
1
|
+
{"version":3,"file":"useMessageStallDetection.d.ts","sourceRoot":"","sources":["../../src/unstable/useMessageStallDetection.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,qCAAqC,GAAG;IAClD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,CAAC,EAAE,qCAAqC,GAC9C,8BAA8B,CAkEhC"}
|
|
@@ -25,9 +25,9 @@ function unstable_useMessageStallDetection(options) {
|
|
|
25
25
|
return values;
|
|
26
26
|
}));
|
|
27
27
|
const running = activity[0] === true;
|
|
28
|
-
const lastActivityRef = useRef(
|
|
28
|
+
const lastActivityRef = useRef(0);
|
|
29
29
|
const [stalled, setStalled] = useState(false);
|
|
30
|
-
const [,
|
|
30
|
+
const [now, setNow] = useState(0);
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
if (!running) return void 0;
|
|
33
33
|
lastActivityRef.current = Date.now();
|
|
@@ -37,13 +37,17 @@ function unstable_useMessageStallDetection(options) {
|
|
|
37
37
|
setStalled(false);
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
+
const stall = () => {
|
|
41
|
+
setNow(Date.now());
|
|
42
|
+
setStalled(true);
|
|
43
|
+
};
|
|
40
44
|
const sinceActivity = Date.now() - lastActivityRef.current;
|
|
41
45
|
if (sinceActivity >= thresholdMs) {
|
|
42
|
-
|
|
46
|
+
stall();
|
|
43
47
|
return;
|
|
44
48
|
}
|
|
45
49
|
setStalled(false);
|
|
46
|
-
const id = setTimeout(
|
|
50
|
+
const id = setTimeout(stall, thresholdMs - sinceActivity);
|
|
47
51
|
return () => clearTimeout(id);
|
|
48
52
|
}, [
|
|
49
53
|
running,
|
|
@@ -52,7 +56,7 @@ function unstable_useMessageStallDetection(options) {
|
|
|
52
56
|
]);
|
|
53
57
|
useEffect(() => {
|
|
54
58
|
if (!stalled) return void 0;
|
|
55
|
-
const id = setInterval(() =>
|
|
59
|
+
const id = setInterval(() => setNow(Date.now()), 1e3);
|
|
56
60
|
return () => clearInterval(id);
|
|
57
61
|
}, [stalled]);
|
|
58
62
|
if (!stalled) return {
|
|
@@ -61,7 +65,7 @@ function unstable_useMessageStallDetection(options) {
|
|
|
61
65
|
};
|
|
62
66
|
return {
|
|
63
67
|
stalled: true,
|
|
64
|
-
stalledForMs: Math.max(0,
|
|
68
|
+
stalledForMs: Math.max(0, now - lastActivityRef.current)
|
|
65
69
|
};
|
|
66
70
|
}
|
|
67
71
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessageStallDetection.js","names":["useEffect","useRef","useState","useAuiState","useShallowSelector","Unstable_MessageStallDetectionOptions","thresholdMs","Unstable_MessageStallDetection","stalled","stalledForMs","unstable_useMessageStallDetection","options","activity","s","running","message","status","type","values","content","length","part","push","text","argsText","result","undefined","lastActivityRef","
|
|
1
|
+
{"version":3,"file":"useMessageStallDetection.js","names":["useEffect","useRef","useState","useAuiState","useShallowSelector","Unstable_MessageStallDetectionOptions","thresholdMs","Unstable_MessageStallDetection","stalled","stalledForMs","unstable_useMessageStallDetection","options","activity","s","running","message","status","type","values","content","length","part","push","text","argsText","result","undefined","lastActivityRef","setStalled","now","setNow","current","Date","stall","sinceActivity","id","setTimeout","clearTimeout","setInterval","clearInterval","Math","max"],"sources":["../../src/unstable/useMessageStallDetection.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { useShallowSelector } from \"@assistant-ui/store/internal\";\n\nexport type Unstable_MessageStallDetectionOptions = {\n /**\n * Milliseconds of unchanged message content before the message counts as\n * stalled.\n * @default 2000\n */\n thresholdMs?: number | undefined;\n};\n\nexport type Unstable_MessageStallDetection = {\n /** True while the message is running and its content has not changed for at least `thresholdMs`. */\n stalled: boolean;\n /** Milliseconds since the last observed content change. `0` while not stalled. */\n stalledForMs: number;\n};\n\n/**\n * @deprecated Under active development and might change without notice.\n *\n * Detects mid-run output stalls on the current message: while the message is\n * running, watches its text, reasoning, and tool-argument values plus tool-result\n * availability and reports a stall once they stop changing for `thresholdMs`.\n * Useful for re-surfacing a \"still working\" indicator during tool think-time or\n * provider stalls, after the first tokens have already streamed.\n *\n * Must be used inside a message scope.\n */\nexport function unstable_useMessageStallDetection(\n options?: Unstable_MessageStallDetectionOptions,\n): Unstable_MessageStallDetection {\n const thresholdMs = options?.thresholdMs ?? 2000;\n\n const activity = useAuiState(\n useShallowSelector((s) => {\n const running = s.message.status?.type === \"running\";\n if (!running) return [false];\n\n const values: unknown[] = [true, s.message.content.length];\n\n for (const part of s.message.content) {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n values.push(part.type, part.text);\n } else if (part.type === \"tool-call\") {\n values.push(part.type, part.argsText, part.result !== undefined);\n } else {\n values.push(part.type);\n }\n }\n return values;\n }),\n );\n\n const running = activity[0] === true;\n const lastActivityRef = useRef(0);\n const [stalled, setStalled] = useState(false);\n const [now, setNow] = useState(0);\n\n useEffect(() => {\n if (!running) return undefined;\n lastActivityRef.current = Date.now();\n return undefined;\n }, [running, activity]);\n\n useEffect(() => {\n if (!running) {\n setStalled(false);\n return undefined;\n }\n\n const stall = () => {\n setNow(Date.now());\n setStalled(true);\n };\n const sinceActivity = Date.now() - lastActivityRef.current;\n if (sinceActivity >= thresholdMs) {\n stall();\n return undefined;\n }\n\n setStalled(false);\n const id = setTimeout(stall, thresholdMs - sinceActivity);\n return () => clearTimeout(id);\n }, [running, activity, thresholdMs]);\n\n useEffect(() => {\n if (!stalled) return undefined;\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [stalled]);\n\n if (!stalled) return { stalled: false, stalledForMs: 0 };\n return {\n stalled: true,\n stalledForMs: Math.max(0, now - lastActivityRef.current),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiCA,SAAgBU,kCACdC,SACgC;CAChC,MAAML,cAAcK,SAASL,eAAe;CAE5C,MAAMM,WAAWT,YACfC,oBAAoBS,MAAM;EAExB,IAAI,EADYA,EAAEE,QAAQC,QAAQC,SAAS,YAC7B,OAAO,CAAC,KAAK;EAE3B,MAAMC,SAAoB,CAAC,MAAML,EAAEE,QAAQI,QAAQC,MAAM;EAEzD,KAAK,MAAMC,QAAQR,EAAEE,QAAQI,SAC3B,IAAIE,KAAKJ,SAAS,UAAUI,KAAKJ,SAAS,aACxCC,OAAOI,KAAKD,KAAKJ,MAAMI,KAAKE,IAAI;OAC3B,IAAIF,KAAKJ,SAAS,aACvBC,OAAOI,KAAKD,KAAKJ,MAAMI,KAAKG,UAAUH,KAAKI,WAAWC,KAAAA,CAAS;OAE/DR,OAAOI,KAAKD,KAAKJ,IAAI;EAGzB,OAAOC;CACT,CAAC,CACH;CAEA,MAAMJ,UAAUF,SAAS,OAAO;CAChC,MAAMe,kBAAkB1B,OAAO,CAAC;CAChC,MAAM,CAACO,SAASoB,cAAc1B,SAAS,KAAK;CAC5C,MAAM,CAAC2B,KAAKC,UAAU5B,SAAS,CAAC;CAEhCF,gBAAgB;EACd,IAAI,CAACc,SAAS,OAAOY,KAAAA;EACrBC,gBAAgBI,UAAUC,KAAKH,IAAI;CAErC,GAAG,CAACf,SAASF,QAAQ,CAAC;CAEtBZ,gBAAgB;EACd,IAAI,CAACc,SAAS;GACZc,WAAW,KAAK;GAChB;EACF;EAEA,MAAMK,cAAc;GAClBH,OAAOE,KAAKH,IAAI,CAAC;GACjBD,WAAW,IAAI;EACjB;EACA,MAAMM,gBAAgBF,KAAKH,IAAI,IAAIF,gBAAgBI;EACnD,IAAIG,iBAAiB5B,aAAa;GAChC2B,MAAM;GACN;EACF;EAEAL,WAAW,KAAK;EAChB,MAAMO,KAAKC,WAAWH,OAAO3B,cAAc4B,aAAa;EACxD,aAAaG,aAAaF,EAAE;CAC9B,GAAG;EAACrB;EAASF;EAAUN;CAAW,CAAC;CAEnCN,gBAAgB;EACd,IAAI,CAACQ,SAAS,OAAOkB,KAAAA;EACrB,MAAMS,KAAKG,kBAAkBR,OAAOE,KAAKH,IAAI,CAAC,GAAG,GAAI;EACrD,aAAaU,cAAcJ,EAAE;CAC/B,GAAG,CAAC3B,OAAO,CAAC;CAEZ,IAAI,CAACA,SAAS,OAAO;EAAEA,SAAS;EAAOC,cAAc;CAAE;CACvD,OAAO;EACLD,SAAS;EACTC,cAAc+B,KAAKC,IAAI,GAAGZ,MAAMF,gBAAgBI,OAAO;CACzD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModelContextSnapshot.js","names":["c","_c","useEffect","useState","AssistantClient","Unsubscribe","ModelContextSnapshotSource","empty","T","read","aui","subscribe","onChange","isEqual","previous","next","useModelContextSnapshot","enabled","source","$","t0","snapshot","setSnapshot","t1","t2","shallowEqualRecords","Readonly","Record","keys","Object","length","every","key","hasOwn"],"sources":["../../src/unstable/useModelContextSnapshot.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { AssistantClient } from \"@assistant-ui/store\";\nimport type { Unsubscribe } from \"@assistant-ui/core\";\n\n/**\n * Where a snapshot comes from and what counts as a change to it. Declared once\n * per consumer at module scope: the subscription effect keys on this object, so\n * an inline source without an `isEqual` re-reads itself into a render loop.\n */\nexport type ModelContextSnapshotSource<T> = {\n /** Seeds the snapshot when it starts disabled. */\n readonly empty: T;\n /** Projects the fields the consumer observes out of the live model context. */\n read(aui: AssistantClient): T;\n subscribe(aui: AssistantClient, onChange: () => void): Unsubscribe;\n /**\n * An equal pair keeps the previous reference. Omitted by a consumer that\n * re-derives on every notification, where a caller republishing an unchanged\n * tool set is how it asks to be re-run.\n */\n isEqual?(previous: T, next: T): boolean;\n};\n\n/**\n * `getModelContext()` rebuilds its result on every call, so a projection of the\n * fields a consumer observes is held in state and refreshed on notification\n * rather than read during render. Keeping the previous reference for an equal\n * projection is what stops a notification carrying no observable change from\n * invalidating everything derived from it.\n */\nexport const useModelContextSnapshot = <T>(\n aui: AssistantClient,\n enabled: boolean,\n source: ModelContextSnapshotSource<T>,\n): T => {\n const [snapshot, setSnapshot] = useState(() =>\n enabled ? source.read(aui) : source.empty,\n );\n\n useEffect(() => {\n if (!enabled) return undefined;\n const read = () => {\n const next = source.read(aui);\n setSnapshot((previous) =>\n source.isEqual?.(previous, next) ? previous : next,\n );\n };\n read();\n return source.subscribe(aui, read);\n }, [aui, enabled, source]);\n\n return snapshot;\n};\n\n/** Shallow own-key comparison, for a projection whose values are records. */\nexport const shallowEqualRecords = (\n previous: Readonly<Record<string, unknown>>,\n next: Readonly<Record<string, unknown>>,\n): boolean => {\n const keys = Object.keys(previous);\n if (keys.length !== Object.keys(next).length) return false;\n return keys.every(\n (key) => Object.hasOwn(next, key) && previous[key] === next[key],\n );\n};\n"],"mappings":";;;;;;;;;;;AAgCA,MAAagB,2BAA0BN,KAAAO,SAAAC,WAAA;CAAA,MAAAC,IAAAlB,EAAA,CAAA;CAAA,IAAAmB;CAAA,IAAAD,EAAA,OAAAT,OAAAS,EAAA,OAAAF,WAAAE,EAAA,OAAAD,QAAA;EAKIE,WACvCH,UAAUC,OAAMT,KAAMC,GAAkB,IAAXQ,OAAMX;EAAMY,EAAA,KAAAT;EAAAS,EAAA,KAAAF;EAAAE,EAAA,KAAAD;EAAAC,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAD3C,MAAA,CAAAE,UAAAC,eAAgCnB,SAASiB,EAEzC;CAAE,IAAAG;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAT,OAAAS,EAAA,OAAAF,WAAAE,EAAA,OAAAD,QAAA;EAEQK,WAAA;GACR,IAAI,CAACN,SAAO;GACZ,MAAAR,aAAa;IACX,MAAAM,OAAaG,OAAMT,KAAMC,GAAG;IAC5BY,aAAYR,aACVI,OAAML,UAAWC,UAAUC,IAAsB,IAAjDD,WAAAC,IACF;GAAC;GAEHN,KAAK;GAAC,OACCS,OAAMP,UAAWD,KAAKD,IAAI;EAAC;EACjCe,KAAA;GAACd;GAAKO;GAASC;EAAM;EAACC,EAAA,KAAAT;EAAAS,EAAA,KAAAF;EAAAE,EAAA,KAAAD;EAAAC,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAD,KAAAJ,EAAA;EAAAK,KAAAL,EAAA;CAAA;CAVzBjB,UAAUqB,IAUPC,EAAsB;CAAC,OAEnBH;AAAQ;;AAIjB,MAAaI,uBACXX,UACAC,SACY;CACZ,MAAMa,OAAOC,OAAOD,KAAKd,QAAQ;CACjC,IAAIc,KAAKE,WAAWD,OAAOD,KAAKb,IAAI,CAAC,CAACe,QAAQ,OAAO;CACrD,OAAOF,KAAKG,OACTC,QAAQH,OAAOI,OAAOlB,MAAMiB,GAAG,KAAKlB,SAASkB,SAASjB,KAAKiB,IAC9D;AACF"}
|
|
1
|
+
{"version":3,"file":"useModelContextSnapshot.js","names":["c","_c","useEffect","useState","AssistantClient","Unsubscribe","ModelContextSnapshotSource","empty","T","read","aui","subscribe","onChange","isEqual","previous","next","useModelContextSnapshot","enabled","source","$","t0","snapshot","setSnapshot","t1","t2","shallowEqualRecords","Readonly","Record","keys","Object","length","every","key","hasOwn","_c"],"sources":["../../src/unstable/useModelContextSnapshot.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { AssistantClient } from \"@assistant-ui/store\";\nimport type { Unsubscribe } from \"@assistant-ui/core\";\n\n/**\n * Where a snapshot comes from and what counts as a change to it. Declared once\n * per consumer at module scope: the subscription effect keys on this object, so\n * an inline source without an `isEqual` re-reads itself into a render loop.\n */\nexport type ModelContextSnapshotSource<T> = {\n /** Seeds the snapshot when it starts disabled. */\n readonly empty: T;\n /** Projects the fields the consumer observes out of the live model context. */\n read(aui: AssistantClient): T;\n subscribe(aui: AssistantClient, onChange: () => void): Unsubscribe;\n /**\n * An equal pair keeps the previous reference. Omitted by a consumer that\n * re-derives on every notification, where a caller republishing an unchanged\n * tool set is how it asks to be re-run.\n */\n isEqual?(previous: T, next: T): boolean;\n};\n\n/**\n * `getModelContext()` rebuilds its result on every call, so a projection of the\n * fields a consumer observes is held in state and refreshed on notification\n * rather than read during render. Keeping the previous reference for an equal\n * projection is what stops a notification carrying no observable change from\n * invalidating everything derived from it.\n */\nexport const useModelContextSnapshot = <T>(\n aui: AssistantClient,\n enabled: boolean,\n source: ModelContextSnapshotSource<T>,\n): T => {\n const [snapshot, setSnapshot] = useState(() =>\n enabled ? source.read(aui) : source.empty,\n );\n\n useEffect(() => {\n if (!enabled) return undefined;\n const read = () => {\n const next = source.read(aui);\n setSnapshot((previous) =>\n source.isEqual?.(previous, next) ? previous : next,\n );\n };\n read();\n return source.subscribe(aui, read);\n }, [aui, enabled, source]);\n\n return snapshot;\n};\n\n/** Shallow own-key comparison, for a projection whose values are records. */\nexport const shallowEqualRecords = (\n previous: Readonly<Record<string, unknown>>,\n next: Readonly<Record<string, unknown>>,\n): boolean => {\n const keys = Object.keys(previous);\n if (keys.length !== Object.keys(next).length) return false;\n return keys.every(\n (key) => Object.hasOwn(next, key) && previous[key] === next[key],\n );\n};\n"],"mappings":";;;;;;;;;;;AAgCA,MAAagB,2BAA0BN,KAAAO,SAAAC,WAAA;CAAA,MAAAC,IAAAlB,EAAA,CAAA;CAAA,IAAAmB;CAAA,IAAAD,EAAA,OAAAT,OAAAS,EAAA,OAAAF,WAAAE,EAAA,OAAAD,QAAA;EAKIE,WACvCH,UAAUC,OAAMT,KAAMC,GAAkB,IAAXQ,OAAMX;EAAMY,EAAA,KAAAT;EAAAS,EAAA,KAAAF;EAAAE,EAAA,KAAAD;EAAAC,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAD3C,MAAA,CAAAE,UAAAC,eAAgCnB,SAASiB,EAEzC;CAAE,IAAAG;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAT,OAAAS,EAAA,OAAAF,WAAAE,EAAA,OAAAD,QAAA;EAEQK,WAAA;GACR,IAAI,CAACN,SAAO;GACZ,MAAAR,aAAa;IACX,MAAAM,OAAaG,OAAMT,KAAMC,GAAG;IAC5BY,aAAYR,aACVI,OAAML,UAAWC,UAAUC,IAAsB,IAAjDD,WAAAC,IACF;GAAC;GAEHN,KAAK;GAAC,OACCS,OAAMP,UAAWD,KAAKD,IAAI;EAAC;EACjCe,KAAA;GAACd;GAAKO;GAASC;EAAM;EAACC,EAAA,KAAAT;EAAAS,EAAA,KAAAF;EAAAE,EAAA,KAAAD;EAAAC,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAD,KAAAJ,EAAA;EAAAK,KAAAL,EAAA;CAAA;CAVzBjB,UAAUqB,IAUPC,EAAsB;CAAC,OAEnBH;AAAQ;;AAIjB,MAAaI,uBACXX,UACAC,SACY;CACZ,MAAMa,OAAOC,OAAOD,KAAKd,QAAQ;CACjC,IAAIc,KAAKE,WAAWD,OAAOD,KAAKb,IAAI,CAAC,CAACe,QAAQ,OAAO;CACrD,OAAOF,KAAKG,OACTC,QAAQH,OAAOI,OAAOlB,MAAMiB,GAAG,KAAKlB,SAASkB,SAASjB,KAAKiB,IAC9D;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebMcpRegistrationResource.js","names":["useEffect","useRef","useState","resource","Tool","toWebMcpTool","WebMcpHost","WebMcpRegistrationProps","host","name","signature","tool","getCurrentTool","notPermitted","error","notPermittedMessage","useWebMcpRegistration","t0","$","_c","refused","setRefused","fallbackToolRef","t1","lifecycle","AbortController","live","dispose","refuse","message","console","warn","registerTool","current","signal","error_1","t2","abort","t3","WebMcpRegistrationResource"],"sources":["../../../src/unstable/webmcp/WebMcpRegistrationResource.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { Tool } from \"assistant-stream\";\nimport { toWebMcpTool } from \"./convertTools\";\nimport type { WebMcpHost } from \"./webmcp-host\";\n\nexport type WebMcpRegistrationProps = {\n host: WebMcpHost;\n name: string;\n /** Re-registers when it changes; an execute-only edit reads through instead. */\n signature: string;\n tool: Tool<any, any>;\n getCurrentTool: (name: string) => Tool<any, any> | undefined;\n};\n\n// The explainer specifies NotAllowedError for a page whose tools permission is\n// off, which a cross-origin iframe without allow=\"tools\" reaches routinely. It\n// documents no rejection for a name already taken, so that stays a hedge.\nconst notPermitted = (error: unknown) =>\n (error as { name?: unknown } | null | undefined)?.name === \"NotAllowedError\";\n\nconst notPermittedMessage = (name: string) =>\n `[assistant-ui] WebMCP registration for tool \"${name}\" was not permitted; the page's tools permission is disabled.`;\n\nconst useWebMcpRegistration = ({\n host,\n name,\n signature,\n tool,\n getCurrentTool,\n}: WebMcpRegistrationProps): string | null => {\n // A refused name is remembered for as long as the tool stays in the model\n // context, so a permanent collision warns once rather than on every sync.\n const [refused, setRefused] = useState(false);\n const fallbackToolRef = useRef(tool);\n\n useEffect(() => {\n if (refused) return undefined;\n\n const lifecycle = new AbortController();\n let live = true;\n let dispose: (() => void) | undefined;\n\n const refuse = (message: string, error: unknown) => {\n if (!live) return;\n live = false;\n setRefused(true);\n console.warn(message, error);\n };\n\n try {\n dispose = host.registerTool(\n toWebMcpTool(\n name,\n () => getCurrentTool(name) ?? fallbackToolRef.current,\n lifecycle.signal,\n ),\n (error) =>\n refuse(\n notPermitted(error)\n ? notPermittedMessage(name)\n : `[assistant-ui] WebMCP registration for tool \"${name}\" failed (name may already be registered).`,\n error,\n ),\n );\n } catch (error) {\n refuse(\n notPermitted(error)\n ? notPermittedMessage(name)\n : `[assistant-ui] Skipping WebMCP registration for tool \"${name}\": registerTool failed (name may already be registered).`,\n error,\n );\n return undefined;\n }\n\n return () => {\n live = false;\n lifecycle.abort();\n try {\n dispose();\n } catch (error) {\n console.warn(\n `[assistant-ui] Unregistering WebMCP tool \"${name}\" failed.`,\n error,\n );\n }\n };\n }, [getCurrentTool, host, name, signature, refused]);\n\n return refused ? null : name;\n};\n\nexport const WebMcpRegistrationResource = resource(useWebMcpRegistration);\n"],"mappings":";;;;;AAkBA,MAAMa,gBAAgBC,UACnBA,OAAiDL,SAAS;AAE7D,MAAMM,uBAAuBN,SAC3B,gDAAgDA,KAAI;AAEtD,MAAMO,yBAAwBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAC,MAAA,EAAAX,MAAAC,MAAAC,WAAAC,MAAAC,mBAAAK;CAS7B,MAAA,CAAAG,SAAAC,cAA8BnB,SAAS,KAAK;CAC5C,MAAAoB,kBAAwBrB,OAAOU,IAAI;CAAE,IAAAY;CAAA,IAAAL,EAAA,OAAAN,kBAAAM,EAAA,OAAAV,QAAAU,EAAA,OAAAT,QAAAS,EAAA,OAAAE,SAAA;EAE3BG,WAAA;GACR,IAAIH,SAAO;GAEX,MAAAI,YAAkB,IAAIC,gBAAgB;GACtC,IAAAC,OAAW;GACPC,IAAAA;GAEJ,MAAAC,UAAeC,SAAAf,UAAA;IACb,IAAI,CAACY,MAAI;IACTA,OAAOA;IACPL,WAAW,IAAI;IACfS,QAAOC,KAAMF,SAASf,KAAK;GAAC;GAG9B,IAAA;IACEa,UAAUnB,KAAIwB,aACZ3B,aACEI,YACMG,eAAeH,IAA+B,KAAtBa,gBAAeW,SAC7CT,UAASU,MACX,IACAC,YACEP,OACEf,aAAaC,OAEsF,IAD/FC,oBAAoBN,IAC2E,IAFnG,gDAEoDA,KAAI,6CACxDK,OACF,CACJ;GAbO,SAAAsB,IAAA;IAcAtB,MAAAA,UAAAA;IACPc,OACEf,aAAaC,OAE6G,IADtHC,oBAAoBN,IACkG,IAF1H,yDAE6DA,KAAI,2DACjEK,OACF;IAAC;GAAA;GAEF,aAEM;IACLY,OAAOA;IACPF,UAASa,MAAO;IAChB,IAAA;KACEV,QAAQ;IAAC,SAAAW,IAAA;KACFxB,MAAAA,UAAAA;KACPgB,QAAOC,KACL,6CAA6CtB,KAAI,YACjDK,OACF;IAAC;GACF;EACF;EACFI,EAAA,KAAAN;EAAAM,EAAA,KAAAV;EAAAU,EAAA,KAAAT;EAAAS,EAAA,KAAAE;EAAAF,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,IAAAkB;CAAA,IAAAlB,EAAA,OAAAN,kBAAAM,EAAA,OAAAV,QAAAU,EAAA,OAAAT,QAAAS,EAAA,OAAAE,WAAAF,EAAA,OAAAR,WAAA;EAAE0B,KAAA;GAACxB;GAAgBJ;GAAMC;GAAMC;GAAWU;EAAO;EAACF,EAAA,KAAAN;EAAAM,EAAA,KAAAV;EAAAU,EAAA,KAAAT;EAAAS,EAAA,KAAAE;EAAAF,EAAA,KAAAR;EAAAQ,EAAA,MAAAkB;CAAA,OAAAA,KAAAlB,EAAA;CAnDnDlB,UAAUuB,IAmDPa,EAAgD;CAAC,OAE7ChB,UAAA,OAAAX;AAAqB;AAG9B,MAAa8B,6BAA6BpC,SAASa,qBAAqB"}
|
|
1
|
+
{"version":3,"file":"WebMcpRegistrationResource.js","names":["useEffect","useRef","useState","resource","Tool","toWebMcpTool","WebMcpHost","WebMcpRegistrationProps","host","name","signature","tool","getCurrentTool","notPermitted","error","notPermittedMessage","useWebMcpRegistration","t0","$","_c","refused","setRefused","fallbackToolRef","t1","lifecycle","AbortController","live","dispose","refuse","message","console","warn","registerTool","current","signal","error_1","t2","abort","t3","WebMcpRegistrationResource","_c"],"sources":["../../../src/unstable/webmcp/WebMcpRegistrationResource.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { Tool } from \"assistant-stream\";\nimport { toWebMcpTool } from \"./convertTools\";\nimport type { WebMcpHost } from \"./webmcp-host\";\n\nexport type WebMcpRegistrationProps = {\n host: WebMcpHost;\n name: string;\n /** Re-registers when it changes; an execute-only edit reads through instead. */\n signature: string;\n tool: Tool<any, any>;\n getCurrentTool: (name: string) => Tool<any, any> | undefined;\n};\n\n// The explainer specifies NotAllowedError for a page whose tools permission is\n// off, which a cross-origin iframe without allow=\"tools\" reaches routinely. It\n// documents no rejection for a name already taken, so that stays a hedge.\nconst notPermitted = (error: unknown) =>\n (error as { name?: unknown } | null | undefined)?.name === \"NotAllowedError\";\n\nconst notPermittedMessage = (name: string) =>\n `[assistant-ui] WebMCP registration for tool \"${name}\" was not permitted; the page's tools permission is disabled.`;\n\nconst useWebMcpRegistration = ({\n host,\n name,\n signature,\n tool,\n getCurrentTool,\n}: WebMcpRegistrationProps): string | null => {\n // A refused name is remembered for as long as the tool stays in the model\n // context, so a permanent collision warns once rather than on every sync.\n const [refused, setRefused] = useState(false);\n const fallbackToolRef = useRef(tool);\n\n useEffect(() => {\n if (refused) return undefined;\n\n const lifecycle = new AbortController();\n let live = true;\n let dispose: (() => void) | undefined;\n\n const refuse = (message: string, error: unknown) => {\n if (!live) return;\n live = false;\n setRefused(true);\n console.warn(message, error);\n };\n\n try {\n dispose = host.registerTool(\n toWebMcpTool(\n name,\n () => getCurrentTool(name) ?? fallbackToolRef.current,\n lifecycle.signal,\n ),\n (error) =>\n refuse(\n notPermitted(error)\n ? notPermittedMessage(name)\n : `[assistant-ui] WebMCP registration for tool \"${name}\" failed (name may already be registered).`,\n error,\n ),\n );\n } catch (error) {\n refuse(\n notPermitted(error)\n ? notPermittedMessage(name)\n : `[assistant-ui] Skipping WebMCP registration for tool \"${name}\": registerTool failed (name may already be registered).`,\n error,\n );\n return undefined;\n }\n\n return () => {\n live = false;\n lifecycle.abort();\n try {\n dispose();\n } catch (error) {\n console.warn(\n `[assistant-ui] Unregistering WebMCP tool \"${name}\" failed.`,\n error,\n );\n }\n };\n }, [getCurrentTool, host, name, signature, refused]);\n\n return refused ? null : name;\n};\n\nexport const WebMcpRegistrationResource = resource(useWebMcpRegistration);\n"],"mappings":";;;;;AAkBA,MAAMa,gBAAgBC,UACnBA,OAAiDL,SAAS;AAE7D,MAAMM,uBAAuBN,SAC3B,gDAAgDA,KAAI;AAEtD,MAAMO,yBAAwBC,OAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAC,MAAA,EAAAX,MAAAC,MAAAC,WAAAC,MAAAC,mBAAAK;CAS7B,MAAA,CAAAG,SAAAC,cAA8BnB,SAAS,KAAK;CAC5C,MAAAoB,kBAAwBrB,OAAOU,IAAI;CAAE,IAAAY;CAAA,IAAAL,EAAA,OAAAN,kBAAAM,EAAA,OAAAV,QAAAU,EAAA,OAAAT,QAAAS,EAAA,OAAAE,SAAA;EAE3BG,WAAA;GACR,IAAIH,SAAO;GAEX,MAAAI,YAAkB,IAAIC,gBAAgB;GACtC,IAAAC,OAAW;GACPC,IAAAA;GAEJ,MAAAC,UAAeC,SAAAf,UAAA;IACb,IAAI,CAACY,MAAI;IACTA,OAAOA;IACPL,WAAW,IAAI;IACfS,QAAOC,KAAMF,SAASf,KAAK;GAAC;GAG9B,IAAA;IACEa,UAAUnB,KAAIwB,aACZ3B,aACEI,YACMG,eAAeH,IAA+B,KAAtBa,gBAAeW,SAC7CT,UAASU,MACX,IACAC,YACEP,OACEf,aAAaC,OAEsF,IAD/FC,oBAAoBN,IAC2E,IAFnG,gDAEoDA,KAAI,6CACxDK,OACF,CACJ;GAbO,SAAAsB,IAAA;IAcAtB,MAAAA,UAAAA;IACPc,OACEf,aAAaC,OAE6G,IADtHC,oBAAoBN,IACkG,IAF1H,yDAE6DA,KAAI,2DACjEK,OACF;IAAC;GAAA;GAEF,aAEM;IACLY,OAAOA;IACPF,UAASa,MAAO;IAChB,IAAA;KACEV,QAAQ;IAAC,SAAAW,IAAA;KACFxB,MAAAA,UAAAA;KACPgB,QAAOC,KACL,6CAA6CtB,KAAI,YACjDK,OACF;IAAC;GACF;EACF;EACFI,EAAA,KAAAN;EAAAM,EAAA,KAAAV;EAAAU,EAAA,KAAAT;EAAAS,EAAA,KAAAE;EAAAF,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,IAAAkB;CAAA,IAAAlB,EAAA,OAAAN,kBAAAM,EAAA,OAAAV,QAAAU,EAAA,OAAAT,QAAAS,EAAA,OAAAE,WAAAF,EAAA,OAAAR,WAAA;EAAE0B,KAAA;GAACxB;GAAgBJ;GAAMC;GAAMC;GAAWU;EAAO;EAACF,EAAA,KAAAN;EAAAM,EAAA,KAAAV;EAAAU,EAAA,KAAAT;EAAAS,EAAA,KAAAE;EAAAF,EAAA,KAAAR;EAAAQ,EAAA,MAAAkB;CAAA,OAAAA,KAAAlB,EAAA;CAnDnDlB,UAAUuB,IAmDPa,EAAgD;CAAC,OAE7ChB,UAAA,OAAAX;AAAqB;AAG9B,MAAa8B,6BAA6BpC,SAASa,qBAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebMcpProvider.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","useRef","useState","useSyncExternalStore","useResources","useTapRoot","withKey","useAui","Tool","getDefaultWebMcpHost","WebMcpHost","defaultWebMcpFilter","toWebMcpInputSchema","WebMcpRegistrationResource","shallowEqual","useModelContextSnapshot","ModelContextSnapshotSource","Unstable_WebMcpProviderOptions","filter","name","tool","Unstable_WebMcpProviderResult","status","registeredToolNames","EMPTY_NAMES","Object","freeze","EMPTY_TOOLS","Record","warned","WeakSet","signatures","WeakMap","description","signature","signatureOf","cached","get","JSON","stringify","set","NO_SUBSCRIPTION","modelContextToolSource","empty","read","aui","modelContext","getModelContext","tools","subscribe","onChange","useStableNames","names","cell","next","sort","previous","useWebMcpRegistry","t0","$","host","getCurrentTool","elements","entries","push","t1","error","has","add","console","warn","unstable_useWebMcpProvider","options","available","currentToolsRef","current","root","WebMcpProviderRoot","getValue","published","setPublished"],"sources":["../../../src/unstable/webmcp/useWebMcpProvider.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { useResources, useTapRoot, withKey } from \"@assistant-ui/tap\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { getDefaultWebMcpHost, type WebMcpHost } from \"./webmcp-host\";\nimport { defaultWebMcpFilter, toWebMcpInputSchema } from \"./convertTools\";\nimport { WebMcpRegistrationResource } from \"./WebMcpRegistrationResource\";\nimport { shallowEqual } from \"@assistant-ui/store/internal\";\nimport {\n useModelContextSnapshot,\n type ModelContextSnapshotSource,\n} from \"../useModelContextSnapshot\";\n\nexport type Unstable_WebMcpProviderOptions = {\n filter?: (name: string, tool: Tool<any, any>) => boolean;\n};\n\nexport type Unstable_WebMcpProviderResult = {\n status: \"unsupported\" | \"active\";\n registeredToolNames: readonly string[];\n};\n\nconst EMPTY_NAMES: readonly string[] = Object.freeze([]);\nconst EMPTY_TOOLS: Record<string, Tool<any, any>> = Object.freeze({});\n\n// The description is re-read on every sync so mutating it in place is\n// observed; the schema is converted only when the tool object itself changes.\n// Keyed on the tool so a schema or filter that throws warns once instead of\n// on every model-context notify.\nconst warned = new WeakSet<Tool<any, any>>();\n\nconst signatures = new WeakMap<\n Tool<any, any>,\n { description: string | undefined; signature: string }\n>();\n\nconst signatureOf = (tool: Tool<any, any>) => {\n const cached = signatures.get(tool);\n if (cached && cached.description === tool.description)\n return cached.signature;\n const signature = `${tool.description ?? \"\"}\\u0000${JSON.stringify(\n toWebMcpInputSchema(tool),\n )}`;\n signatures.set(tool, { description: tool.description, signature });\n return signature;\n};\n\nconst NO_SUBSCRIPTION = () => {};\n\n// No `isEqual`: a caller republishing an unchanged tool set is how it asks for\n// a re-sync, which is what re-attempts a tool whose filter has stopped throwing\n// and what picks up a description edited in place on a stable tool object.\nconst modelContextToolSource: ModelContextSnapshotSource<\n Record<string, Tool<any, any>>\n> = {\n empty: EMPTY_TOOLS,\n read: (aui) => aui.modelContext.getModelContext().tools ?? EMPTY_TOOLS,\n subscribe: (aui, onChange) =>\n aui.modelContext.subscribe?.(onChange) ?? NO_SUBSCRIPTION,\n};\n\nconst useStableNames = (names: readonly (string | null)[]) => {\n const [cell] = useState(() => ({ names: EMPTY_NAMES }));\n const next = names.filter((name): name is string => name !== null).sort();\n const previous = cell.names;\n if (shallowEqual(previous, next)) {\n return previous;\n }\n cell.names = next;\n return next;\n};\n\nconst useWebMcpRegistry = ({\n host,\n filter,\n tools,\n getCurrentTool,\n}: {\n host: WebMcpHost;\n filter: (name: string, tool: Tool<any, any>) => boolean;\n tools: Record<string, Tool<any, any>>;\n getCurrentTool: (name: string) => Tool<any, any> | undefined;\n}) => {\n const elements = [];\n for (const [name, tool] of Object.entries(tools)) {\n try {\n if (!filter(name, tool)) continue;\n const signature = signatureOf(tool);\n elements.push(\n withKey(\n name,\n WebMcpRegistrationResource({\n host,\n name,\n signature,\n tool,\n getCurrentTool,\n }),\n [host, name, signature, tool, getCurrentTool],\n ),\n );\n } catch (error) {\n if (warned.has(tool)) continue;\n warned.add(tool);\n console.warn(\n `[assistant-ui] Skipping WebMCP registration for tool \"${name}\": filter or schema conversion failed.`,\n error,\n );\n }\n }\n\n return useStableNames(useResources(elements));\n};\n\n/**\n * Publishes the frontend tools in the model context to a WebMCP-capable\n * browser, so the user's own browser agent can call them.\n *\n * Returns `status: \"unsupported\"` when the page exposes no\n * `document.modelContext` (or `navigator.modelContext`), and the sorted names\n * of the tools currently registered with the host.\n */\nexport const unstable_useWebMcpProvider = (\n options: Unstable_WebMcpProviderOptions = {},\n): Unstable_WebMcpProviderResult => {\n const aui = useAui();\n const [host] = useState(getDefaultWebMcpHost);\n const filter = options.filter ?? defaultWebMcpFilter;\n const tools = useModelContextSnapshot(\n aui,\n host.available,\n modelContextToolSource,\n );\n const currentToolsRef = useRef(tools);\n useInsertionEffect(() => {\n currentToolsRef.current = tools;\n }, [tools]);\n const getCurrentTool = useCallback(\n (name: string) => currentToolsRef.current[name],\n [],\n );\n\n const root = useTapRoot(function WebMcpProviderRoot() {\n return useWebMcpRegistry({\n host,\n filter,\n tools,\n getCurrentTool,\n });\n });\n const registeredToolNames = useSyncExternalStore(\n root.subscribe,\n root.getValue,\n () => EMPTY_NAMES,\n );\n\n const [published, setPublished] = useState(false);\n useEffect(() => {\n if (host.available) setPublished(true);\n }, [host]);\n\n return {\n status: published ? \"active\" : \"unsupported\",\n registeredToolNames,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useWebMcpProvider.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","useRef","useState","useSyncExternalStore","useResources","useTapRoot","withKey","useAui","Tool","getDefaultWebMcpHost","WebMcpHost","defaultWebMcpFilter","toWebMcpInputSchema","WebMcpRegistrationResource","shallowEqual","useModelContextSnapshot","ModelContextSnapshotSource","Unstable_WebMcpProviderOptions","filter","name","tool","Unstable_WebMcpProviderResult","status","registeredToolNames","EMPTY_NAMES","Object","freeze","EMPTY_TOOLS","Record","warned","WeakSet","signatures","WeakMap","description","signature","signatureOf","cached","get","JSON","stringify","set","NO_SUBSCRIPTION","modelContextToolSource","empty","read","aui","modelContext","getModelContext","tools","subscribe","onChange","useStableNames","names","cell","next","sort","previous","useWebMcpRegistry","t0","$","host","getCurrentTool","elements","entries","push","t1","error","has","add","console","warn","unstable_useWebMcpProvider","options","available","currentToolsRef","current","root","WebMcpProviderRoot","getValue","published","setPublished","_c"],"sources":["../../../src/unstable/webmcp/useWebMcpProvider.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { useResources, useTapRoot, withKey } from \"@assistant-ui/tap\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { getDefaultWebMcpHost, type WebMcpHost } from \"./webmcp-host\";\nimport { defaultWebMcpFilter, toWebMcpInputSchema } from \"./convertTools\";\nimport { WebMcpRegistrationResource } from \"./WebMcpRegistrationResource\";\nimport { shallowEqual } from \"@assistant-ui/store/internal\";\nimport {\n useModelContextSnapshot,\n type ModelContextSnapshotSource,\n} from \"../useModelContextSnapshot\";\n\nexport type Unstable_WebMcpProviderOptions = {\n filter?: (name: string, tool: Tool<any, any>) => boolean;\n};\n\nexport type Unstable_WebMcpProviderResult = {\n status: \"unsupported\" | \"active\";\n registeredToolNames: readonly string[];\n};\n\nconst EMPTY_NAMES: readonly string[] = Object.freeze([]);\nconst EMPTY_TOOLS: Record<string, Tool<any, any>> = Object.freeze({});\n\n// The description is re-read on every sync so mutating it in place is\n// observed; the schema is converted only when the tool object itself changes.\n// Keyed on the tool so a schema or filter that throws warns once instead of\n// on every model-context notify.\nconst warned = new WeakSet<Tool<any, any>>();\n\nconst signatures = new WeakMap<\n Tool<any, any>,\n { description: string | undefined; signature: string }\n>();\n\nconst signatureOf = (tool: Tool<any, any>) => {\n const cached = signatures.get(tool);\n if (cached && cached.description === tool.description)\n return cached.signature;\n const signature = `${tool.description ?? \"\"}\\u0000${JSON.stringify(\n toWebMcpInputSchema(tool),\n )}`;\n signatures.set(tool, { description: tool.description, signature });\n return signature;\n};\n\nconst NO_SUBSCRIPTION = () => {};\n\n// No `isEqual`: a caller republishing an unchanged tool set is how it asks for\n// a re-sync, which is what re-attempts a tool whose filter has stopped throwing\n// and what picks up a description edited in place on a stable tool object.\nconst modelContextToolSource: ModelContextSnapshotSource<\n Record<string, Tool<any, any>>\n> = {\n empty: EMPTY_TOOLS,\n read: (aui) => aui.modelContext.getModelContext().tools ?? EMPTY_TOOLS,\n subscribe: (aui, onChange) =>\n aui.modelContext.subscribe?.(onChange) ?? NO_SUBSCRIPTION,\n};\n\nconst useStableNames = (names: readonly (string | null)[]) => {\n const [cell] = useState(() => ({ names: EMPTY_NAMES }));\n const next = names.filter((name): name is string => name !== null).sort();\n const previous = cell.names;\n if (shallowEqual(previous, next)) {\n return previous;\n }\n cell.names = next;\n return next;\n};\n\nconst useWebMcpRegistry = ({\n host,\n filter,\n tools,\n getCurrentTool,\n}: {\n host: WebMcpHost;\n filter: (name: string, tool: Tool<any, any>) => boolean;\n tools: Record<string, Tool<any, any>>;\n getCurrentTool: (name: string) => Tool<any, any> | undefined;\n}) => {\n const elements = [];\n for (const [name, tool] of Object.entries(tools)) {\n try {\n if (!filter(name, tool)) continue;\n const signature = signatureOf(tool);\n elements.push(\n withKey(\n name,\n WebMcpRegistrationResource({\n host,\n name,\n signature,\n tool,\n getCurrentTool,\n }),\n [host, name, signature, tool, getCurrentTool],\n ),\n );\n } catch (error) {\n if (warned.has(tool)) continue;\n warned.add(tool);\n console.warn(\n `[assistant-ui] Skipping WebMCP registration for tool \"${name}\": filter or schema conversion failed.`,\n error,\n );\n }\n }\n\n return useStableNames(useResources(elements));\n};\n\n/**\n * Publishes the frontend tools in the model context to a WebMCP-capable\n * browser, so the user's own browser agent can call them.\n *\n * Returns `status: \"unsupported\"` when the page exposes no\n * `document.modelContext` (or `navigator.modelContext`), and the sorted names\n * of the tools currently registered with the host.\n */\nexport const unstable_useWebMcpProvider = (\n options: Unstable_WebMcpProviderOptions = {},\n): Unstable_WebMcpProviderResult => {\n const aui = useAui();\n const [host] = useState(getDefaultWebMcpHost);\n const filter = options.filter ?? defaultWebMcpFilter;\n const tools = useModelContextSnapshot(\n aui,\n host.available,\n modelContextToolSource,\n );\n const currentToolsRef = useRef(tools);\n useInsertionEffect(() => {\n currentToolsRef.current = tools;\n }, [tools]);\n const getCurrentTool = useCallback(\n (name: string) => currentToolsRef.current[name],\n [],\n );\n\n const root = useTapRoot(function WebMcpProviderRoot() {\n return useWebMcpRegistry({\n host,\n filter,\n tools,\n getCurrentTool,\n });\n });\n const registeredToolNames = useSyncExternalStore(\n root.subscribe,\n root.getValue,\n () => EMPTY_NAMES,\n );\n\n const [published, setPublished] = useState(false);\n useEffect(() => {\n if (host.available) setPublished(true);\n }, [host]);\n\n return {\n status: published ? \"active\" : \"unsupported\",\n registeredToolNames,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Primitive.js","names":["ComponentProps","ComponentPropsWithoutRef","ComponentRef","ElementType","ForwardRefExoticComponent","PropsWithoutRef","ReactElement","ReactNode","RefAttributes","cloneElement","forwardRef","isValidElement","Primitive","RadixPrimitive","Slot","NODES","const","PrimitiveNode","WithRenderPropProps","T","render","PrimitiveProps","E","WithRenderPropRuntimeProps","asChild","children","PrimitiveRef","composeRenderElement","undefined","props","renderSlot","Root","withRenderProp","Component","Wrapped","t0","ref","$","_c","rest","Comp","t1","t2","t3","componentName","displayName","name","createPrimitive","node","RadixComp","reduce","acc","ReturnType","K"],"sources":["../../src/utils/Primitive.tsx"],"sourcesContent":["import {\n type ComponentProps,\n type ComponentPropsWithoutRef,\n type ComponentRef,\n type ElementType,\n type ForwardRefExoticComponent,\n type PropsWithoutRef,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n cloneElement,\n forwardRef,\n isValidElement,\n} from \"react\";\nimport { Primitive as RadixPrimitive } from \"radix-ui/internal\";\nimport { Slot } from \"radix-ui\";\n\n/**\n * Thin wrapper around Radix `Primitive` that adds `render` prop support.\n *\n * When `render` is provided, it is converted to the equivalent `asChild` pattern:\n * render={<Comp props />} + children → asChild + <Comp props>{children}</Comp>\n *\n * All prop merging, ref composition, and event handler chaining remain handled\n * by Radix's battle-tested Slot implementation — we add zero custom logic for that.\n */\n\n// Match @radix-ui/react-primitive's full element set\nconst NODES = [\n \"a\",\n \"button\",\n \"div\",\n \"form\",\n \"h2\",\n \"h3\",\n \"img\",\n \"input\",\n \"label\",\n \"li\",\n \"nav\",\n \"ol\",\n \"p\",\n \"select\",\n \"span\",\n \"svg\",\n \"ul\",\n] as const;\ntype PrimitiveNode = (typeof NODES)[number];\n\ntype WithRenderPropProps<T extends ElementType> =\n ComponentPropsWithoutRef<T> & {\n render?: ReactElement | undefined;\n };\n\ntype PrimitiveProps<E extends PrimitiveNode> = WithRenderPropProps<\n (typeof RadixPrimitive)[E]\n>;\n\ntype WithRenderPropRuntimeProps<T extends ElementType> =\n WithRenderPropProps<T> & {\n asChild?: boolean | undefined;\n children?: ReactNode | undefined;\n };\n\ntype PrimitiveRef<E extends PrimitiveNode> = ComponentRef<\n (typeof RadixPrimitive)[E]\n>;\n\n/**\n * Composes the children of a `render` element. Outer children win when supplied;\n * the render element's own children are the fallback.\n */\nfunction composeRenderElement(\n render: ReactElement,\n children: ReactNode,\n): ReactElement {\n return cloneElement(\n render,\n undefined,\n children !== undefined\n ? children\n : (render.props as { children?: ReactNode }).children,\n );\n}\n\n/**\n * Composes a `render` element at a call site that has already computed its props.\n *\n * `withRenderProp` wraps a component; this covers the case where the props are\n * already in hand and the composition happens inline.\n */\nfunction renderSlot(\n render: ReactElement,\n children: ReactNode,\n props: ComponentProps<typeof Slot.Root>,\n): ReactElement {\n return (\n <Slot.Root {...props}>{composeRenderElement(render, children)}</Slot.Root>\n );\n}\n\nfunction withRenderProp<T extends ElementType>(Component: T) {\n const Wrapped = forwardRef<ComponentRef<T>, WithRenderPropRuntimeProps<T>>(\n (\n {\n render,\n asChild,\n children,\n ...rest\n }: PropsWithoutRef<WithRenderPropRuntimeProps<T>>,\n ref,\n ) => {\n const Comp = Component as any;\n\n if (render && isValidElement(render)) {\n return (\n <Comp {...(rest as any)} asChild ref={ref}>\n {composeRenderElement(render, children)}\n </Comp>\n );\n }\n\n return (\n <Comp {...(rest as any)} asChild={asChild} ref={ref}>\n {children}\n </Comp>\n );\n },\n );\n\n const componentName =\n typeof Component === \"string\"\n ? Component\n : (Component.displayName ?? Component.name ?? \"Component\");\n Wrapped.displayName = componentName;\n\n return Wrapped as ForwardRefExoticComponent<\n WithRenderPropProps<T> & RefAttributes<ComponentRef<T>>\n >;\n}\n\nfunction createPrimitive<E extends PrimitiveNode>(node: E) {\n const RadixComp = RadixPrimitive[node];\n const Component = withRenderProp(RadixComp);\n\n Component.displayName = `Primitive.${node}`;\n return Component as ForwardRefExoticComponent<\n PrimitiveProps<E> & RefAttributes<PrimitiveRef<E>>\n >;\n}\n\nconst Primitive = NODES.reduce(\n (acc, node) => {\n acc[node] = createPrimitive(node);\n return acc;\n },\n {} as {\n [K in PrimitiveNode]: ReturnType<typeof createPrimitive<K>>;\n },\n);\n\nexport { Primitive, renderSlot, withRenderProp };\nexport type { PrimitiveProps, WithRenderPropProps };\n"],"mappings":";;;;;;;;;;;;;;;AA4BA,MAAMe,QAAQ;CACZ;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAAI;;;;;AA2BN,SAASY,qBACPP,QACAK,UACc;CACd,OAAOhB,aACLW,QACAQ,KAAAA,GACAH,aAAaG,KAAAA,IACTH,WACCL,OAAOS,MAAmCJ,QACjD;AACF;;;;;;;AAQA,SAASK,WACPV,QACAK,UACAI,OACc;CACd,OACE,oBAAC,KAAK,MAAN;EAAW,GAAIA;EAAQF,UAAAA,qBAAqBP,QAAQK,QAAQ;CAAa,CAAA;AAE7E;AAEA,SAASO,eAAsCC,WAAc;CAC3D,MAAMC,UAAUxB,YACdyB,IAAAC,QAAA;EAAA,MAAAC,IAAAC,EAAA,EAAA;EAAA,IAAAd;EAAA,IAAAC;EAAA,IAAAL;EAAA,IAAAmB;EAAA,IAAAF,EAAA,OAAAF,IAAA;GACE,CAAA,CAAAf,QAAAI,SAAAC,UAAA,GAAAc,QAAAJ;GAKiDE,EAAA,KAAAF;GAAAE,EAAA,KAAAb;GAAAa,EAAA,KAAAZ;GAAAY,EAAA,KAAAjB;GAAAiB,EAAA,KAAAE;EAAA,OAAA;GAAAf,UAAAa,EAAA;GAAAZ,WAAAY,EAAA;GAAAjB,SAAAiB,EAAA;GAAAE,OAAAF,EAAA;EAAA;EAGjD,MAAAG,OAAaP;EAEb,IAAIb,UAAUT,eAAeS,MAAM,GAAC;GAErB,MAAAqB,KAAAF;GAAW,IAAAG;GAAA,IAAAL,EAAA,OAAAZ,YAAAY,EAAA,OAAAjB,QAAA;IACnBsB,KAAAf,qBAAqBP,QAAQK,QAAQ;IAACY,EAAA,KAAAZ;IAAAY,EAAA,KAAAjB;IAAAiB,EAAA,KAAAK;GAAA,OAAAA,KAAAL,EAAA;GAAA,IAAAM;GAAA,IAAAN,EAAA,OAAAD,OAAAC,EAAA,OAAAI,MAAAJ,EAAA,QAAAK,IAAA;IADzCC,KAAA,oBAAC,MAAD;KAAK,GAAMF;KAAc,SAAA;KAAaL;KACnCM,UAAAA;IADE,CAAA;IAEEL,EAAA,KAAAD;IAAAC,EAAA,KAAAI;IAAAJ,EAAA,MAAAK;IAAAL,EAAA,MAAAM;GAAA,OAAAA,KAAAN,EAAA;GAAA,OAFPM;EAEO;EAKE,MAAAF,KAAAF;EAAW,IAAAG;EAAA,IAAAL,EAAA,QAAAb,WAAAa,EAAA,QAAAZ,YAAAY,EAAA,QAAAD,OAAAC,EAAA,QAAAI,IAAA;GAAtBC,KAAA,oBAAC,MAAD;IAAK,GAAMD;IAAuBjB;IAAcY;IAC7CX;GADE,CAAA;GAEEY,EAAA,MAAAb;GAAAa,EAAA,MAAAZ;GAAAY,EAAA,MAAAD;GAAAC,EAAA,MAAAI;GAAAJ,EAAA,MAAAK;EAAA,OAAAA,KAAAL,EAAA;EAAA,OAFPK;CAEO,CAGb;CAMAR,QAAQW,cAHN,OAAOZ,cAAc,WACjBA,YACCA,UAAUY,eAAeZ,UAAUa,QAAQ;CAGlD,OAAOZ;AAGT;AAEA,SAASa,gBAAyCC,MAAS;CACzD,MAAMC,YAAYpC,YAAemC;CACjC,MAAMf,YAAYD,eAAeiB,SAAS;CAE1ChB,UAAUY,cAAc,aAAaG;CACrC,OAAOf;AAGT;AAEA,MAAMrB,YAAYG,MAAMmC,QACrBC,KAAKH,SAAS;CACbG,IAAIH,QAAQD,gBAAgBC,IAAI;CAChC,OAAOG;AACT,GACA,CAAC,CAGH"}
|
|
1
|
+
{"version":3,"file":"Primitive.js","names":["ComponentProps","ComponentPropsWithoutRef","ComponentRef","ElementType","ForwardRefExoticComponent","PropsWithoutRef","ReactElement","ReactNode","RefAttributes","cloneElement","forwardRef","isValidElement","Primitive","RadixPrimitive","Slot","NODES","const","PrimitiveNode","WithRenderPropProps","T","render","PrimitiveProps","E","WithRenderPropRuntimeProps","asChild","children","PrimitiveRef","composeRenderElement","undefined","props","renderSlot","Root","withRenderProp","Component","Wrapped","t0","ref","$","_c","rest","Comp","t1","t2","t3","componentName","displayName","name","createPrimitive","node","RadixComp","reduce","acc","ReturnType","K","_c","RadixPrimitive"],"sources":["../../src/utils/Primitive.tsx"],"sourcesContent":["import {\n type ComponentProps,\n type ComponentPropsWithoutRef,\n type ComponentRef,\n type ElementType,\n type ForwardRefExoticComponent,\n type PropsWithoutRef,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n cloneElement,\n forwardRef,\n isValidElement,\n} from \"react\";\nimport { Primitive as RadixPrimitive } from \"radix-ui/internal\";\nimport { Slot } from \"radix-ui\";\n\n/**\n * Thin wrapper around Radix `Primitive` that adds `render` prop support.\n *\n * When `render` is provided, it is converted to the equivalent `asChild` pattern:\n * render={<Comp props />} + children → asChild + <Comp props>{children}</Comp>\n *\n * All prop merging, ref composition, and event handler chaining remain handled\n * by Radix's battle-tested Slot implementation — we add zero custom logic for that.\n */\n\n// Match @radix-ui/react-primitive's full element set\nconst NODES = [\n \"a\",\n \"button\",\n \"div\",\n \"form\",\n \"h2\",\n \"h3\",\n \"img\",\n \"input\",\n \"label\",\n \"li\",\n \"nav\",\n \"ol\",\n \"p\",\n \"select\",\n \"span\",\n \"svg\",\n \"ul\",\n] as const;\ntype PrimitiveNode = (typeof NODES)[number];\n\ntype WithRenderPropProps<T extends ElementType> =\n ComponentPropsWithoutRef<T> & {\n render?: ReactElement | undefined;\n };\n\ntype PrimitiveProps<E extends PrimitiveNode> = WithRenderPropProps<\n (typeof RadixPrimitive)[E]\n>;\n\ntype WithRenderPropRuntimeProps<T extends ElementType> =\n WithRenderPropProps<T> & {\n asChild?: boolean | undefined;\n children?: ReactNode | undefined;\n };\n\ntype PrimitiveRef<E extends PrimitiveNode> = ComponentRef<\n (typeof RadixPrimitive)[E]\n>;\n\n/**\n * Composes the children of a `render` element. Outer children win when supplied;\n * the render element's own children are the fallback.\n */\nfunction composeRenderElement(\n render: ReactElement,\n children: ReactNode,\n): ReactElement {\n return cloneElement(\n render,\n undefined,\n children !== undefined\n ? children\n : (render.props as { children?: ReactNode }).children,\n );\n}\n\n/**\n * Composes a `render` element at a call site that has already computed its props.\n *\n * `withRenderProp` wraps a component; this covers the case where the props are\n * already in hand and the composition happens inline.\n */\nfunction renderSlot(\n render: ReactElement,\n children: ReactNode,\n props: ComponentProps<typeof Slot.Root>,\n): ReactElement {\n return (\n <Slot.Root {...props}>{composeRenderElement(render, children)}</Slot.Root>\n );\n}\n\nfunction withRenderProp<T extends ElementType>(Component: T) {\n const Wrapped = forwardRef<ComponentRef<T>, WithRenderPropRuntimeProps<T>>(\n (\n {\n render,\n asChild,\n children,\n ...rest\n }: PropsWithoutRef<WithRenderPropRuntimeProps<T>>,\n ref,\n ) => {\n const Comp = Component as any;\n\n if (render && isValidElement(render)) {\n return (\n <Comp {...(rest as any)} asChild ref={ref}>\n {composeRenderElement(render, children)}\n </Comp>\n );\n }\n\n return (\n <Comp {...(rest as any)} asChild={asChild} ref={ref}>\n {children}\n </Comp>\n );\n },\n );\n\n const componentName =\n typeof Component === \"string\"\n ? Component\n : (Component.displayName ?? Component.name ?? \"Component\");\n Wrapped.displayName = componentName;\n\n return Wrapped as ForwardRefExoticComponent<\n WithRenderPropProps<T> & RefAttributes<ComponentRef<T>>\n >;\n}\n\nfunction createPrimitive<E extends PrimitiveNode>(node: E) {\n const RadixComp = RadixPrimitive[node];\n const Component = withRenderProp(RadixComp);\n\n Component.displayName = `Primitive.${node}`;\n return Component as ForwardRefExoticComponent<\n PrimitiveProps<E> & RefAttributes<PrimitiveRef<E>>\n >;\n}\n\nconst Primitive = NODES.reduce(\n (acc, node) => {\n acc[node] = createPrimitive(node);\n return acc;\n },\n {} as {\n [K in PrimitiveNode]: ReturnType<typeof createPrimitive<K>>;\n },\n);\n\nexport { Primitive, renderSlot, withRenderProp };\nexport type { PrimitiveProps, WithRenderPropProps };\n"],"mappings":";;;;;;;;;;;;;;;AA4BA,MAAMe,QAAQ;CACZ;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAAI;;;;;AA2BN,SAASY,qBACPP,QACAK,UACc;CACd,OAAOhB,aACLW,QACAQ,KAAAA,GACAH,aAAaG,KAAAA,IACTH,WACCL,OAAOS,MAAmCJ,QACjD;AACF;;;;;;;AAQA,SAASK,WACPV,QACAK,UACAI,OACc;CACd,OACE,oBAAC,KAAK,MAAN;EAAW,GAAIA;EAAQF,UAAAA,qBAAqBP,QAAQK,QAAQ;CAAa,CAAA;AAE7E;AAEA,SAASO,eAAsCC,WAAc;CAC3D,MAAMC,UAAUxB,YACdyB,IAAAC,QAAA;EAAA,MAAAC,IAAAC,EAAA,EAAA;EAAA,IAAAd;EAAA,IAAAC;EAAA,IAAAL;EAAA,IAAAmB;EAAA,IAAAF,EAAA,OAAAF,IAAA;GACE,CAAA,CAAAf,QAAAI,SAAAC,UAAA,GAAAc,QAAAJ;GAKiDE,EAAA,KAAAF;GAAAE,EAAA,KAAAb;GAAAa,EAAA,KAAAZ;GAAAY,EAAA,KAAAjB;GAAAiB,EAAA,KAAAE;EAAA,OAAA;GAAAf,UAAAa,EAAA;GAAAZ,WAAAY,EAAA;GAAAjB,SAAAiB,EAAA;GAAAE,OAAAF,EAAA;EAAA;EAGjD,MAAAG,OAAaP;EAEb,IAAIb,UAAUT,eAAeS,MAAM,GAAC;GAErB,MAAAqB,KAAAF;GAAW,IAAAG;GAAA,IAAAL,EAAA,OAAAZ,YAAAY,EAAA,OAAAjB,QAAA;IACnBsB,KAAAf,qBAAqBP,QAAQK,QAAQ;IAACY,EAAA,KAAAZ;IAAAY,EAAA,KAAAjB;IAAAiB,EAAA,KAAAK;GAAA,OAAAA,KAAAL,EAAA;GAAA,IAAAM;GAAA,IAAAN,EAAA,OAAAD,OAAAC,EAAA,OAAAI,MAAAJ,EAAA,QAAAK,IAAA;IADzCC,KAAA,oBAAC,MAAD;KAAK,GAAMF;KAAc,SAAA;KAAaL;KACnCM,UAAAA;IADE,CAAA;IAEEL,EAAA,KAAAD;IAAAC,EAAA,KAAAI;IAAAJ,EAAA,MAAAK;IAAAL,EAAA,MAAAM;GAAA,OAAAA,KAAAN,EAAA;GAAA,OAFPM;EAEO;EAKE,MAAAF,KAAAF;EAAW,IAAAG;EAAA,IAAAL,EAAA,QAAAb,WAAAa,EAAA,QAAAZ,YAAAY,EAAA,QAAAD,OAAAC,EAAA,QAAAI,IAAA;GAAtBC,KAAA,oBAAC,MAAD;IAAK,GAAMD;IAAuBjB;IAAcY;IAC7CX;GADE,CAAA;GAEEY,EAAA,MAAAb;GAAAa,EAAA,MAAAZ;GAAAY,EAAA,MAAAD;GAAAC,EAAA,MAAAI;GAAAJ,EAAA,MAAAK;EAAA,OAAAA,KAAAL,EAAA;EAAA,OAFPK;CAEO,CAGb;CAMAR,QAAQW,cAHN,OAAOZ,cAAc,WACjBA,YACCA,UAAUY,eAAeZ,UAAUa,QAAQ;CAGlD,OAAOZ;AAGT;AAEA,SAASa,gBAAyCC,MAAS;CACzD,MAAMC,YAAYpC,YAAemC;CACjC,MAAMf,YAAYD,eAAeiB,SAAS;CAE1ChB,UAAUY,cAAc,aAAaG;CACrC,OAAOf;AAGT;AAEA,MAAMrB,YAAYG,MAAMmC,QACrBC,KAAKH,SAAS;CACbG,IAAIH,QAAQD,gBAAgBC,IAAI;CAChC,OAAOG;AACT,GACA,CAAC,CAGH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createActionButton.js","names":["ComponentRef","forwardRef","ComponentPropsWithoutRef","MouseEventHandler","Primitive","composeEventHandlers","ActionButtonCallback","props","TProps","HTMLButtonElement","PrimitiveButtonProps","button","ActionButtonProps","THook","ActionButtonElement","createActionButton","displayName","useActionButton","forwardProps","NonNullable","ActionButton","forwardedRef","$","_c","forwardedProps","primitiveProps","Object","keys","Array","forEach","key","includes","callback","undefined","t0","t1","t2","disabled","t3","onClick","t4"],"sources":["../../src/utils/createActionButton.tsx"],"sourcesContent":["import {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n type MouseEventHandler,\n} from \"react\";\nimport { Primitive } from \"./Primitive\";\nimport { composeEventHandlers } from \"radix-ui/internal\";\n\ntype ActionButtonCallback<TProps> = (\n props: TProps,\n) => MouseEventHandler<HTMLButtonElement> | null;\n\ntype PrimitiveButtonProps = ComponentPropsWithoutRef<typeof Primitive.button>;\n\nexport type ActionButtonProps<THook> = PrimitiveButtonProps &\n (THook extends (props: infer TProps) => unknown ? TProps : never);\n\nexport type ActionButtonElement = ComponentRef<typeof Primitive.button>;\n\nexport const createActionButton = <TProps,>(\n displayName: string,\n useActionButton: ActionButtonCallback<TProps>,\n forwardProps: (keyof NonNullable<TProps>)[] = [],\n) => {\n const ActionButton = forwardRef<\n ActionButtonElement,\n PrimitiveButtonProps & TProps\n >((props, forwardedRef) => {\n const forwardedProps = {} as TProps;\n const primitiveProps = {} as PrimitiveButtonProps;\n\n (Object.keys(props) as Array<keyof typeof props>).forEach((key) => {\n if (forwardProps.includes(key as keyof TProps)) {\n (forwardedProps as any)[key] = props[key];\n } else {\n (primitiveProps as any)[key] = props[key];\n }\n });\n\n const callback = useActionButton(forwardedProps as TProps) ?? undefined;\n return (\n <Primitive.button\n type=\"button\"\n {...primitiveProps}\n ref={forwardedRef}\n disabled={primitiveProps.disabled || !callback}\n onClick={composeEventHandlers(primitiveProps.onClick, callback)}\n />\n );\n });\n\n ActionButton.displayName = displayName;\n\n return ActionButton;\n};\n"],"mappings":";;;;;;AAoBA,MAAae,sBACXC,aACAC,iBACAC,eAA8C,CAAA,MAC3C;CACH,MAAME,eAAenB,YAGnBM,OAAAc,iBAAA;EAAA,MAAAC,IAAAC,EAAA,CAAA;EACA,MAAAC,iBAAuB,CAAC;EACxB,MAAAC,iBAAuB,CAAC;EAExB,OAAOE,KAAMpB,KAAK,CAAC,CAA6BsB,SAAUC,QAAA;GACxD,IAAIZ,aAAYa,SAAUD,GAAmB,GAC3C,eAAwBA,OAAOvB,MAAMuB;QAErC,eAAwBA,OAAOvB,MAAMuB;EACtC,CACF;EAED,MAAAE,WAAiBf,gBAAgBO,cAAqC,KAArDS,KAAAA;EAEd,MAAAC,KAAA9B;EACM,MAAA+B,KAAA;EAGK,MAAAC,KAAAX,eAAcY,YAAd,CAA4BL;EAC7B,MAAAM,KAAAjC,qBAAqBoB,eAAcc,SAAUP,QAAQ;EAAC,IAAAQ;EAAA,IAAAlB,EAAA,OAAAD,gBAAAC,EAAA,OAAAG,kBAAAH,EAAA,OAAAY,GAAAvB,UAAAW,EAAA,OAAAc,MAAAd,EAAA,OAAAgB,IAAA;GALjEE,KAAA,oBAAA,GAAA,QAAA;IACO,MAAAL;IAAQ,GACTV;IACCJ,KAAAA;IACK,UAAAe;IACD,SAAAE;GAAsD,CAAA;GAC/DhB,EAAA,KAAAD;GAAAC,EAAA,KAAAG;GAAAH,EAAA,KAAAY,GAAAvB;GAAAW,EAAA,KAAAc;GAAAd,EAAA,KAAAgB;GAAAhB,EAAA,KAAAkB;EAAA,OAAAA,KAAAlB,EAAA;EAAA,OANFkB;CAME,CAEL;CAEDpB,aAAaJ,cAAcA;CAE3B,OAAOI;AACT"}
|
|
1
|
+
{"version":3,"file":"createActionButton.js","names":["ComponentRef","forwardRef","ComponentPropsWithoutRef","MouseEventHandler","Primitive","composeEventHandlers","ActionButtonCallback","props","TProps","HTMLButtonElement","PrimitiveButtonProps","button","ActionButtonProps","THook","ActionButtonElement","createActionButton","displayName","useActionButton","forwardProps","NonNullable","ActionButton","forwardedRef","$","_c","forwardedProps","primitiveProps","Object","keys","Array","forEach","key","includes","callback","undefined","t0","t1","t2","disabled","t3","onClick","t4","_c","Primitive"],"sources":["../../src/utils/createActionButton.tsx"],"sourcesContent":["import {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n type MouseEventHandler,\n} from \"react\";\nimport { Primitive } from \"./Primitive\";\nimport { composeEventHandlers } from \"radix-ui/internal\";\n\ntype ActionButtonCallback<TProps> = (\n props: TProps,\n) => MouseEventHandler<HTMLButtonElement> | null;\n\ntype PrimitiveButtonProps = ComponentPropsWithoutRef<typeof Primitive.button>;\n\nexport type ActionButtonProps<THook> = PrimitiveButtonProps &\n (THook extends (props: infer TProps) => unknown ? TProps : never);\n\nexport type ActionButtonElement = ComponentRef<typeof Primitive.button>;\n\nexport const createActionButton = <TProps,>(\n displayName: string,\n useActionButton: ActionButtonCallback<TProps>,\n forwardProps: (keyof NonNullable<TProps>)[] = [],\n) => {\n const ActionButton = forwardRef<\n ActionButtonElement,\n PrimitiveButtonProps & TProps\n >((props, forwardedRef) => {\n const forwardedProps = {} as TProps;\n const primitiveProps = {} as PrimitiveButtonProps;\n\n (Object.keys(props) as Array<keyof typeof props>).forEach((key) => {\n if (forwardProps.includes(key as keyof TProps)) {\n (forwardedProps as any)[key] = props[key];\n } else {\n (primitiveProps as any)[key] = props[key];\n }\n });\n\n const callback = useActionButton(forwardedProps as TProps) ?? undefined;\n return (\n <Primitive.button\n type=\"button\"\n {...primitiveProps}\n ref={forwardedRef}\n disabled={primitiveProps.disabled || !callback}\n onClick={composeEventHandlers(primitiveProps.onClick, callback)}\n />\n );\n });\n\n ActionButton.displayName = displayName;\n\n return ActionButton;\n};\n"],"mappings":";;;;;;AAoBA,MAAae,sBACXC,aACAC,iBACAC,eAA8C,CAAA,MAC3C;CACH,MAAME,eAAenB,YAGnBM,OAAAc,iBAAA;EAAA,MAAAC,IAAAC,EAAA,CAAA;EACA,MAAAC,iBAAuB,CAAC;EACxB,MAAAC,iBAAuB,CAAC;EAExB,OAAOE,KAAMpB,KAAK,CAAC,CAA6BsB,SAAUC,QAAA;GACxD,IAAIZ,aAAYa,SAAUD,GAAmB,GAC3C,eAAwBA,OAAOvB,MAAMuB;QAErC,eAAwBA,OAAOvB,MAAMuB;EACtC,CACF;EAED,MAAAE,WAAiBf,gBAAgBO,cAAqC,KAArDS,KAAAA;EAEd,MAAAC,KAAA9B;EACM,MAAA+B,KAAA;EAGK,MAAAC,KAAAX,eAAcY,YAAd,CAA4BL;EAC7B,MAAAM,KAAAjC,qBAAqBoB,eAAcc,SAAUP,QAAQ;EAAC,IAAAQ;EAAA,IAAAlB,EAAA,OAAAD,gBAAAC,EAAA,OAAAG,kBAAAH,EAAA,OAAAY,GAAAvB,UAAAW,EAAA,OAAAc,MAAAd,EAAA,OAAAgB,IAAA;GALjEE,KAAA,oBAAA,GAAA,QAAA;IACO,MAAAL;IAAQ,GACTV;IACCJ,KAAAA;IACK,UAAAe;IACD,SAAAE;GAAsD,CAAA;GAC/DhB,EAAA,KAAAD;GAAAC,EAAA,KAAAG;GAAAH,EAAA,KAAAY,GAAAvB;GAAAW,EAAA,KAAAc;GAAAd,EAAA,KAAAgB;GAAAhB,EAAA,KAAAkB;EAAA,OAAAA,KAAAlB,EAAA;EAAA,OANFkB;CAME,CAEL;CAEDpB,aAAaJ,cAAcA;CAE3B,OAAOI;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useManagedRef.js","names":["useCallback","useRef","useManagedRef","callback","$","_c","cleanupRef","undefined","t0","el","current","ref"],"sources":["../../../src/utils/hooks/useManagedRef.ts"],"sourcesContent":["import { useCallback, useRef } from \"react\";\n\nexport const useManagedRef = <TNode>(\n callback: (node: TNode) => (() => void) | undefined,\n) => {\n const cleanupRef = useRef<(() => void) | undefined>(undefined);\n\n const ref = useCallback(\n (el: TNode | null) => {\n // Call the previous cleanup function\n if (cleanupRef.current) {\n cleanupRef.current();\n cleanupRef.current = undefined;\n }\n\n // Call the new callback and store its cleanup function\n if (el) {\n cleanupRef.current = callback(el);\n }\n },\n [callback],\n );\n\n return ref;\n};\n"],"mappings":";;;AAEA,MAAaE,iBAAgBC,aAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAG3B,MAAAC,aAAmBL,OAAiCM,KAAAA,CAAS;CAAE,IAAAC;CAAA,IAAAJ,EAAA,OAAAD,UAAA;EAG7DK,MAAAC,OAAA;GAEE,IAAIH,WAAUI,SAAQ;IACpBJ,WAAUI,QAAS;IACnBJ,WAAUI,UAAWH,KAAAA;GAAH;GAIpB,IAAIE,IACFH,WAAUI,UAAWP,SAASM,EAAE;EACjC;EACFL,EAAA,KAAAD;EAAAC,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAED,OAEKO;AAAG"}
|
|
1
|
+
{"version":3,"file":"useManagedRef.js","names":["useCallback","useRef","useManagedRef","callback","$","_c","cleanupRef","undefined","t0","el","current","ref","_c","ref"],"sources":["../../../src/utils/hooks/useManagedRef.ts"],"sourcesContent":["import { useCallback, useRef } from \"react\";\n\nexport const useManagedRef = <TNode>(\n callback: (node: TNode) => (() => void) | undefined,\n) => {\n const cleanupRef = useRef<(() => void) | undefined>(undefined);\n\n const ref = useCallback(\n (el: TNode | null) => {\n // Call the previous cleanup function\n if (cleanupRef.current) {\n cleanupRef.current();\n cleanupRef.current = undefined;\n }\n\n // Call the new callback and store its cleanup function\n if (el) {\n cleanupRef.current = callback(el);\n }\n },\n [callback],\n );\n\n return ref;\n};\n"],"mappings":";;;AAEA,MAAaE,iBAAgBC,aAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAG3B,MAAAC,aAAmBL,OAAiCM,KAAAA,CAAS;CAAE,IAAAC;CAAA,IAAAJ,EAAA,OAAAD,UAAA;EAG7DK,MAAAC,OAAA;GAEE,IAAIH,WAAUI,SAAQ;IACpBJ,WAAUI,QAAS;IACnBJ,WAAUI,UAAWH,KAAAA;GAAH;GAIpB,IAAIE,IACFH,WAAUI,UAAWP,SAASM,EAAE;EACjC;EACFL,EAAA,KAAAD;EAAAC,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAED,OAEKO;AAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMediaQuery.js","names":["c","_c","useCallback","useSyncExternalStore","getServerSnapshot","noopUnsubscribe","useMediaQuery","query","$","t0","callback","window","matchMedia","mql","addEventListener","removeEventListener","subscribe","t1","matches","getSnapshot"],"sources":["../../../src/utils/hooks/useMediaQuery.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useSyncExternalStore } from \"react\";\n\nconst getServerSnapshot = () => false;\nconst noopUnsubscribe = () => {};\n\nexport const useMediaQuery = (query: string | null): boolean => {\n const subscribe = useCallback(\n (callback: () => void) => {\n if (typeof window === \"undefined\" || query === null || !window.matchMedia)\n return noopUnsubscribe;\n const mql = window.matchMedia(query);\n mql.addEventListener(\"change\", callback);\n return () => mql.removeEventListener(\"change\", callback);\n },\n [query],\n );\n\n const getSnapshot = useCallback(() => {\n if (typeof window === \"undefined\" || query === null || !window.matchMedia)\n return false;\n return window.matchMedia(query).matches;\n }, [query]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n};\n"],"mappings":";;;;AAIA,MAAMI,0BAA0B;AAChC,MAAMC,wBAAwB,CAAC;AAE/B,MAAaC,iBAAgBC,UAAA;CAAA,MAAAC,IAAAP,EAAA,CAAA;CAAA,IAAAQ;CAAA,IAAAD,EAAA,OAAAD,OAAA;EAEzBE,MAAAC,aAAA;GACE,IAAI,OAAOC,WAAW,eAAeJ,UAAU,QAA3C,CAAoDI,OAAMC,YAAW,OAChEP;GACT,MAAAQ,MAAYF,OAAMC,WAAYL,KAAK;GACnCM,IAAGC,iBAAkB,UAAUJ,QAAQ;GAAC,aAC3BG,IAAGE,oBAAqB,UAAUL,QAAQ;EAAC;EACzDF,EAAA,KAAAD;EAAAC,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAPH,MAAAQ,YAAkBP;CAShB,IAAAQ;CAAA,IAAAT,EAAA,OAAAD,OAAA;EAE8BU,WAAA;GAC9B,IAAI,OAAON,WAAW,eAAeJ,UAAU,QAA3C,CAAoDI,OAAMC,YAAW,OAChE;GAAM,OACRD,OAAMC,WAAYL,KAAK,CAAC,CAAAW;EAAQ;EACxCV,EAAA,KAAAD;EAAAC,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAW,OAELL,qBAAqBa,WAAWG,IAAaf,iBAAiB;AAAC"}
|
|
1
|
+
{"version":3,"file":"useMediaQuery.js","names":["c","_c","useCallback","useSyncExternalStore","getServerSnapshot","noopUnsubscribe","useMediaQuery","query","$","t0","callback","window","matchMedia","mql","addEventListener","removeEventListener","subscribe","t1","matches","getSnapshot","_c","getSnapshot"],"sources":["../../../src/utils/hooks/useMediaQuery.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useSyncExternalStore } from \"react\";\n\nconst getServerSnapshot = () => false;\nconst noopUnsubscribe = () => {};\n\nexport const useMediaQuery = (query: string | null): boolean => {\n const subscribe = useCallback(\n (callback: () => void) => {\n if (typeof window === \"undefined\" || query === null || !window.matchMedia)\n return noopUnsubscribe;\n const mql = window.matchMedia(query);\n mql.addEventListener(\"change\", callback);\n return () => mql.removeEventListener(\"change\", callback);\n },\n [query],\n );\n\n const getSnapshot = useCallback(() => {\n if (typeof window === \"undefined\" || query === null || !window.matchMedia)\n return false;\n return window.matchMedia(query).matches;\n }, [query]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n};\n"],"mappings":";;;;AAIA,MAAMI,0BAA0B;AAChC,MAAMC,wBAAwB,CAAC;AAE/B,MAAaC,iBAAgBC,UAAA;CAAA,MAAAC,IAAAP,EAAA,CAAA;CAAA,IAAAQ;CAAA,IAAAD,EAAA,OAAAD,OAAA;EAEzBE,MAAAC,aAAA;GACE,IAAI,OAAOC,WAAW,eAAeJ,UAAU,QAA3C,CAAoDI,OAAMC,YAAW,OAChEP;GACT,MAAAQ,MAAYF,OAAMC,WAAYL,KAAK;GACnCM,IAAGC,iBAAkB,UAAUJ,QAAQ;GAAC,aAC3BG,IAAGE,oBAAqB,UAAUL,QAAQ;EAAC;EACzDF,EAAA,KAAAD;EAAAC,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAPH,MAAAQ,YAAkBP;CAShB,IAAAQ;CAAA,IAAAT,EAAA,OAAAD,OAAA;EAE8BU,WAAA;GAC9B,IAAI,OAAON,WAAW,eAAeJ,UAAU,QAA3C,CAAoDI,OAAMC,YAAW,OAChE;GAAM,OACRD,OAAMC,WAAYL,KAAK,CAAC,CAAAW;EAAQ;EACxCV,EAAA,KAAAD;EAAAC,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAW,OAELL,qBAAqBa,WAAWG,IAAaf,iBAAiB;AAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnResizeContent.js","names":["useCallbackRef","useCallback","useManagedRef","useOnResizeContent","callback","$","_c","callbackRef","t0","el","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","mutations","hasRelevantMutation","some","_temp","observe","childList","subtree","attributes","characterData","disconnect","refCallback","m","type","attributeName"],"sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"sourcesContent":["import { useCallbackRef } from \"radix-ui/internal\";\nimport { useCallback } from \"react\";\nimport { useManagedRef } from \"./useManagedRef\";\n\nexport const useOnResizeContent = (callback: () => void) => {\n const callbackRef = useCallbackRef(callback);\n\n const refCallback = useCallback(\n (el: HTMLElement) => {\n const resizeObserver = new ResizeObserver(() => {\n callbackRef();\n });\n\n const mutationObserver = new MutationObserver((mutations) => {\n // Filter out style-only attribute mutations to prevent feedback loops\n // with code paths that write styles in response to viewport changes.\n const hasRelevantMutation = mutations.some(\n (m) => m.type !== \"attributes\" || m.attributeName !== \"style\",\n );\n if (hasRelevantMutation) {\n callbackRef();\n }\n });\n\n resizeObserver.observe(el);\n mutationObserver.observe(el, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n },\n [callbackRef],\n );\n\n return useManagedRef(refCallback);\n};\n"],"mappings":";;;;;AAIA,MAAaG,sBAAqBC,aAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAChC,MAAAC,cAAoBP,eAAeI,QAAQ;CAAE,IAAAI;CAAA,IAAAH,EAAA,OAAAE,aAAA;EAG3CC,MAAAC,OAAA;GACE,MAAAC,iBAAuB,IAAIC,qBAAe;IACxCJ,YAAY;GAAC,CACd;GAED,MAAAK,mBAAyB,IAAIC,kBAAiBC,cAAA;IAM5C,IAH4BA,UAASE,KACnCC,KAEEF,GACFR,YAAY;GACb,CACF;GAEDG,eAAcQ,QAAST,EAAE;GACzBG,iBAAgBM,QAAST,IAAI;IAAAU,WAChB;IAAIC,SACN;IAAIC,YACD;IAAIC,eACD;GACjB,CAAC;GAAC,aAEK;IACLZ,eAAca,WAAY;IAC1BX,iBAAgBW,WAAY;GAAC;EAC9B;EACFlB,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAED,OAEKH,cAAcsB,EAAW;AAAC;AApCD,SAAAP,MAAAQ,GAAA;CAAA,OAajBA,EAACC,SAAU,gBAAgBD,EAACE,kBAAmB;AAAO"}
|
|
1
|
+
{"version":3,"file":"useOnResizeContent.js","names":["useCallbackRef","useCallback","useManagedRef","useOnResizeContent","callback","$","_c","callbackRef","t0","el","resizeObserver","ResizeObserver","mutationObserver","MutationObserver","mutations","hasRelevantMutation","some","_temp","observe","childList","subtree","attributes","characterData","disconnect","refCallback","m","type","attributeName","_c","refCallback"],"sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"sourcesContent":["import { useCallbackRef } from \"radix-ui/internal\";\nimport { useCallback } from \"react\";\nimport { useManagedRef } from \"./useManagedRef\";\n\nexport const useOnResizeContent = (callback: () => void) => {\n const callbackRef = useCallbackRef(callback);\n\n const refCallback = useCallback(\n (el: HTMLElement) => {\n const resizeObserver = new ResizeObserver(() => {\n callbackRef();\n });\n\n const mutationObserver = new MutationObserver((mutations) => {\n // Filter out style-only attribute mutations to prevent feedback loops\n // with code paths that write styles in response to viewport changes.\n const hasRelevantMutation = mutations.some(\n (m) => m.type !== \"attributes\" || m.attributeName !== \"style\",\n );\n if (hasRelevantMutation) {\n callbackRef();\n }\n });\n\n resizeObserver.observe(el);\n mutationObserver.observe(el, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n return () => {\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n },\n [callbackRef],\n );\n\n return useManagedRef(refCallback);\n};\n"],"mappings":";;;;;AAIA,MAAaG,sBAAqBC,aAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAChC,MAAAC,cAAoBP,eAAeI,QAAQ;CAAE,IAAAI;CAAA,IAAAH,EAAA,OAAAE,aAAA;EAG3CC,MAAAC,OAAA;GACE,MAAAC,iBAAuB,IAAIC,qBAAe;IACxCJ,YAAY;GAAC,CACd;GAED,MAAAK,mBAAyB,IAAIC,kBAAiBC,cAAA;IAM5C,IAH4BA,UAASE,KACnCC,KAEEF,GACFR,YAAY;GACb,CACF;GAEDG,eAAcQ,QAAST,EAAE;GACzBG,iBAAgBM,QAAST,IAAI;IAAAU,WAChB;IAAIC,SACN;IAAIC,YACD;IAAIC,eACD;GACjB,CAAC;GAAC,aAEK;IACLZ,eAAca,WAAY;IAC1BX,iBAAgBW,WAAY;GAAC;EAC9B;EACFlB,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAED,OAEKH,cAAcsB,EAAW;AAAC;AApCD,SAAAP,MAAAQ,GAAA;CAAA,OAajBA,EAACC,SAAU,gBAAgBD,EAACE,kBAAmB;AAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnScrollToBottom.js","names":["c","_c","useCallbackRef","useEffect","useThreadViewport","useOnScrollToBottom","callback","$","callbackRef","onScrollToBottom","_temp","t0","t1","vp"],"sources":["../../../src/utils/hooks/useOnScrollToBottom.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"radix-ui/internal\";\nimport { useEffect } from \"react\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport const useOnScrollToBottom = (\n callback: (config: { behavior: ScrollBehavior }) => void,\n) => {\n const callbackRef = useCallbackRef(callback);\n const onScrollToBottom = useThreadViewport((vp) => vp.onScrollToBottom);\n\n useEffect(() => {\n return onScrollToBottom(callbackRef);\n }, [onScrollToBottom, callbackRef]);\n};\n"],"mappings":";;;;;;AAMA,MAAaK,uBAAsBC,aAAA;CAAA,MAAAC,IAAAN,EAAA,CAAA;CAGjC,MAAAO,cAAoBN,eAAeI,QAAQ;CAC3C,MAAAG,mBAAyBL,kBAAkBM,KAA2B;CAAE,IAAAC;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAC,eAAAD,EAAA,OAAAE,kBAAA;EAE9DE,WACDF,iBAAiBD,WAAW;EAClCI,KAAA,CAACH,kBAAkBD,WAAW;EAACD,EAAA,KAAAC;EAAAD,EAAA,KAAAE;EAAAF,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAD,KAAAJ,EAAA;EAAAK,KAAAL,EAAA;CAAA;CAFlCJ,UAAUQ,IAEPC,EAA+B;AAAC;AARF,SAAAF,MAAAG,IAAA;CAAA,OAIkBA,GAAEJ;AAAiB"}
|
|
1
|
+
{"version":3,"file":"useOnScrollToBottom.js","names":["c","_c","useCallbackRef","useEffect","useThreadViewport","useOnScrollToBottom","callback","$","callbackRef","onScrollToBottom","_temp","t0","t1","vp","_c"],"sources":["../../../src/utils/hooks/useOnScrollToBottom.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"radix-ui/internal\";\nimport { useEffect } from \"react\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport const useOnScrollToBottom = (\n callback: (config: { behavior: ScrollBehavior }) => void,\n) => {\n const callbackRef = useCallbackRef(callback);\n const onScrollToBottom = useThreadViewport((vp) => vp.onScrollToBottom);\n\n useEffect(() => {\n return onScrollToBottom(callbackRef);\n }, [onScrollToBottom, callbackRef]);\n};\n"],"mappings":";;;;;;AAMA,MAAaK,uBAAsBC,aAAA;CAAA,MAAAC,IAAAN,EAAA,CAAA;CAGjC,MAAAO,cAAoBN,eAAeI,QAAQ;CAC3C,MAAAG,mBAAyBL,kBAAkBM,KAA2B;CAAE,IAAAC;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAC,eAAAD,EAAA,OAAAE,kBAAA;EAE9DE,WACDF,iBAAiBD,WAAW;EAClCI,KAAA,CAACH,kBAAkBD,WAAW;EAACD,EAAA,KAAAC;EAAAD,EAAA,KAAAE;EAAAF,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAD,KAAAJ,EAAA;EAAAK,KAAAL,EAAA;CAAA;CAFlCJ,UAAUQ,IAEPC,EAA+B;AAAC;AARF,SAAAF,MAAAG,IAAA;CAAA,OAIkBA,GAAEJ;AAAiB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSizeHandle.js","names":["c","_c","useCallback","useManagedRef","SizeHandle","useSizeHandle","register","getHeight","$","t0","el","sizeHandle","updateHeight","height","offsetHeight","setHeight","ro","ResizeObserver","observe","disconnect","unregister","callbackRef"],"sources":["../../../src/utils/hooks/useSizeHandle.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useManagedRef } from \"./useManagedRef\";\nimport type { SizeHandle } from \"../../context/stores/ThreadViewport\";\n\n/**\n * Hook that creates a ref for tracking element size via a SizeHandle.\n * Automatically sets up ResizeObserver and reports height changes.\n *\n * @param register - Function that returns a SizeHandle (e.g., registerContentInset)\n * @param getHeight - Optional function to compute height (defaults to el.offsetHeight)\n * @returns A ref callback to attach to the element\n */\nexport const useSizeHandle = (\n register: (() => SizeHandle) | null | undefined,\n getHeight?: (el: HTMLElement) => number,\n) => {\n const callbackRef = useCallback(\n (el: HTMLElement) => {\n if (!register) return;\n\n const sizeHandle = register();\n\n const updateHeight = () => {\n const height = getHeight ? getHeight(el) : el.offsetHeight;\n sizeHandle.setHeight(height);\n };\n\n const ro = new ResizeObserver(updateHeight);\n ro.observe(el);\n updateHeight();\n\n return () => {\n ro.disconnect();\n sizeHandle.unregister();\n };\n },\n [register, getHeight],\n );\n\n return useManagedRef(callbackRef);\n};\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAaK,iBAAgBC,UAAAC,cAAA;CAAA,MAAAC,IAAAP,EAAA,CAAA;CAAA,IAAAQ;CAAA,IAAAD,EAAA,OAAAD,aAAAC,EAAA,OAAAF,UAAA;EAKzBG,MAAAC,OAAA;GACE,IAAI,CAACJ,UAAQ;GAEb,MAAAK,aAAmBL,SAAS;GAE5B,MAAAM,qBAAqB;IACnB,MAAAC,SAAeN,YAAYA,UAAUG,EAAoB,IAAdA,GAAEI;IAC7CH,WAAUI,UAAWF,MAAM;GAAC;GAG9B,MAAAG,KAAW,IAAIC,eAAeL,YAAY;GAC1CI,GAAEE,QAASR,EAAE;GACbE,aAAa;GAAC,aAEP;IACLI,GAAEG,WAAY;IACdR,WAAUS,WAAY;GAAC;EACxB;EACFZ,EAAA,KAAAD;EAAAC,EAAA,KAAAF;EAAAE,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAED,OAEKL,cAAckB,EAAW;AAAC"}
|
|
1
|
+
{"version":3,"file":"useSizeHandle.js","names":["c","_c","useCallback","useManagedRef","SizeHandle","useSizeHandle","register","getHeight","$","t0","el","sizeHandle","updateHeight","height","offsetHeight","setHeight","ro","ResizeObserver","observe","disconnect","unregister","callbackRef","_c","callbackRef"],"sources":["../../../src/utils/hooks/useSizeHandle.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useManagedRef } from \"./useManagedRef\";\nimport type { SizeHandle } from \"../../context/stores/ThreadViewport\";\n\n/**\n * Hook that creates a ref for tracking element size via a SizeHandle.\n * Automatically sets up ResizeObserver and reports height changes.\n *\n * @param register - Function that returns a SizeHandle (e.g., registerContentInset)\n * @param getHeight - Optional function to compute height (defaults to el.offsetHeight)\n * @returns A ref callback to attach to the element\n */\nexport const useSizeHandle = (\n register: (() => SizeHandle) | null | undefined,\n getHeight?: (el: HTMLElement) => number,\n) => {\n const callbackRef = useCallback(\n (el: HTMLElement) => {\n if (!register) return;\n\n const sizeHandle = register();\n\n const updateHeight = () => {\n const height = getHeight ? getHeight(el) : el.offsetHeight;\n sizeHandle.setHeight(height);\n };\n\n const ro = new ResizeObserver(updateHeight);\n ro.observe(el);\n updateHeight();\n\n return () => {\n ro.disconnect();\n sizeHandle.unregister();\n };\n },\n [register, getHeight],\n );\n\n return useManagedRef(callbackRef);\n};\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAaK,iBAAgBC,UAAAC,cAAA;CAAA,MAAAC,IAAAP,EAAA,CAAA;CAAA,IAAAQ;CAAA,IAAAD,EAAA,OAAAD,aAAAC,EAAA,OAAAF,UAAA;EAKzBG,MAAAC,OAAA;GACE,IAAI,CAACJ,UAAQ;GAEb,MAAAK,aAAmBL,SAAS;GAE5B,MAAAM,qBAAqB;IACnB,MAAAC,SAAeN,YAAYA,UAAUG,EAAoB,IAAdA,GAAEI;IAC7CH,WAAUI,UAAWF,MAAM;GAAC;GAG9B,MAAAG,KAAW,IAAIC,eAAeL,YAAY;GAC1CI,GAAEE,QAASR,EAAE;GACbE,aAAa;GAAC,aAEP;IACLI,GAAEG,WAAY;IACdR,WAAUS,WAAY;GAAC;EACxB;EACFZ,EAAA,KAAAD;EAAAC,EAAA,KAAAF;EAAAE,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAED,OAEKL,cAAckB,EAAW;AAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isCompositionKey.d.ts","sourceRoot":"","sources":["../../src/utils/isCompositionKey.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,GAAI,OAAO,aAAa,YACT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isCompositionKey.js","names":["isCompositionKey","event","KeyboardEvent","isComposing","keyCode"],"sources":["../../src/utils/isCompositionKey.ts"],"sourcesContent":["// A keydown that ends an IME composition can arrive after compositionend with\n// isComposing false and keyCode 229, as the Enter that commits one does in\n// Safari.\nexport const isCompositionKey = (event: KeyboardEvent) =>\n event.isComposing || event.keyCode === 229;\n"],"mappings":";AAGA,MAAaA,oBAAoBC,UAC/BA,MAAME,eAAeF,MAAMG,YAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmoothContext.js","names":["c","_c","ComponentType","createContext","FC","forwardRef","PropsWithChildren","useContext","useState","ReadonlyStore","create","UseBoundStore","MessagePartStatus","ToolCallMessagePartStatus","useAui","createContextStoreHook","SmoothContextValue","useSmoothStatus","SmoothContext","makeSmoothContext","initialState","SmoothContextProvider","t0","$","children","t1","Symbol","for","optional","outer","useSmoothContext","aui","t2","part","getState","status","context","t3","withSmoothContextProvider","Component","C","Wrapped","props","ref","displayName","options","Error","useSmoothStatusStore"],"sources":["../../../src/utils/smooth/SmoothContext.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ComponentType,\n createContext,\n type FC,\n forwardRef,\n type PropsWithChildren,\n useContext,\n useState,\n} from \"react\";\nimport type { ReadonlyStore } from \"../../context/ReadonlyStore\";\nimport { create, type UseBoundStore } from \"zustand\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { createContextStoreHook } from \"../../context/react/utils/createContextStoreHook\";\n\ntype SmoothContextValue = {\n useSmoothStatus: UseBoundStore<\n ReadonlyStore<MessagePartStatus | ToolCallMessagePartStatus>\n >;\n};\n\nconst SmoothContext = createContext<SmoothContextValue | null>(null);\n\nconst makeSmoothContext = (\n initialState: MessagePartStatus | ToolCallMessagePartStatus,\n) => {\n const useSmoothStatus = create(() => initialState);\n return { useSmoothStatus };\n};\n\nexport const SmoothContextProvider: FC<PropsWithChildren> = ({ children }) => {\n const outer = useSmoothContext({ optional: true });\n const aui = useAui();\n\n const [context] = useState(() =>\n makeSmoothContext(aui.part.getState().status),\n );\n\n // do not wrap if there is an outer SmoothContextProvider\n if (outer) return children;\n\n return (\n <SmoothContext.Provider value={context}>{children}</SmoothContext.Provider>\n );\n};\n\nexport const withSmoothContextProvider = <C extends ComponentType<any>>(\n Component: C,\n): C => {\n const Wrapped = forwardRef((props, ref) => {\n return (\n <SmoothContextProvider>\n <Component {...(props as any)} ref={ref} />\n </SmoothContextProvider>\n );\n });\n Wrapped.displayName = Component.displayName;\n return Wrapped as any;\n};\n\nfunction useSmoothContext(options?: {\n optional?: false | undefined;\n}): SmoothContextValue;\nfunction useSmoothContext(options?: {\n optional?: boolean | undefined;\n}): SmoothContextValue | null;\nfunction useSmoothContext(options?: { optional?: boolean | undefined }) {\n const context = useContext(SmoothContext);\n if (!options?.optional && !context)\n throw new Error(\n \"This component must be used within a SmoothContextProvider.\",\n );\n return context;\n}\n\nexport const { useSmoothStatus, useSmoothStatusStore } = createContextStoreHook(\n useSmoothContext,\n \"useSmoothStatus\",\n);\n"],"mappings":";;;;;;;;AA0BA,MAAMkB,gBAAgBf,cAAyC,IAAI;AAEnE,MAAMgB,qBACJC,iBACG;CAEH,OAAO,EAAEH,iBADeP,aAAaU,YAC5BH,EAAgB;AAC3B;AAEA,MAAaI,yBAA+CC,OAAA;CAAA,MAAAC,IAAAtB,EAAA,CAAA;CAAC,MAAA,EAAAuB,aAAAF;CAAY,IAAAG;CAAA,IAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,GAAA;EACxCF,KAAA,EAAAG,UAAY,KAAK;EAACL,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAjD,MAAAM,QAAcC,iBAAiBL,EAAkB;CACjD,MAAAM,MAAYjB,OAAO;CAAE,IAAAkB;CAAA,IAAAT,EAAA,OAAAQ,IAAAE,MAAA;EAEMD,WACzBb,kBAAkBY,IAAGE,KAAKC,SAAU,CAAC,CAAAC,MAAO;EAACZ,EAAA,KAAAQ,IAAAE;EAAAV,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAD/C,MAAA,CAAAa,WAAkB5B,SAASwB,EAE3B;CAGA,IAAIH,OAAK,OAASL;CAAS,IAAAa;CAAA,IAAAd,EAAA,OAAAC,YAAAD,EAAA,OAAAa,SAAA;EAGzBC,KAAA,oBAAA,cAAA,UAAA;GAA+BD,OAAAA;GAAUZ;EAAS,CAAA;EAAyBD,EAAA,KAAAC;EAAAD,EAAA,KAAAa;EAAAb,EAAA,KAAAc;CAAA,OAAAA,KAAAd,EAAA;CAAA,OAA3Ec;AAA2E;AAI/E,MAAaC,6BACXC,cACM;CACN,MAAME,UAAUpC,YAAWqC,OAAAC,QAAA;EAAA,MAAApB,IAAAtB,EAAA,CAAA;EAGL,MAAAqB,KAAAoB;EAAY,IAAAjB;EAAA,IAAAF,EAAA,OAAAoB,OAAApB,EAAA,OAAAD,IAAA;GAD9BG,KAAA,oBAAC,uBAAD,EAAA,UACE,oBAAC,WAAD;IAAU,GAAMH;IAAoBqB;GAAG,CAAA,EADnB,CAAA;GAEEpB,EAAA,KAAAoB;GAAApB,EAAA,KAAAD;GAAAC,EAAA,KAAAE;EAAA,OAAAA,KAAAF,EAAA;EAAA,OAFxBE;CAEwB,CAE3B;CACDgB,QAAQG,cAAcL,UAAUK;CAChC,OAAOH;AACT;AAQA,SAAAX,iBAAAe,SAAA;CACE,MAAAT,UAAgB7B,WAAWW,aAAa;CACxC,IAAI,CAAC2B,SAAOjB,YAAR,CAAuBQ,SACzB,MAAM,IAAIU,MACR,6DACF;CAAE,OACGV;AAAO;AAGhB,MAAa,EAAEnB,iBAAiB8B,yBAAyBhC,uBACvDe,kBACA,iBACF"}
|
|
1
|
+
{"version":3,"file":"SmoothContext.js","names":["c","_c","ComponentType","createContext","FC","forwardRef","PropsWithChildren","useContext","useState","ReadonlyStore","create","UseBoundStore","MessagePartStatus","ToolCallMessagePartStatus","useAui","createContextStoreHook","SmoothContextValue","useSmoothStatus","SmoothContext","makeSmoothContext","initialState","SmoothContextProvider","t0","$","children","t1","Symbol","for","optional","outer","useSmoothContext","aui","t2","part","getState","status","context","t3","withSmoothContextProvider","Component","C","Wrapped","props","ref","displayName","options","Error","useSmoothStatusStore","_c"],"sources":["../../../src/utils/smooth/SmoothContext.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ComponentType,\n createContext,\n type FC,\n forwardRef,\n type PropsWithChildren,\n useContext,\n useState,\n} from \"react\";\nimport type { ReadonlyStore } from \"../../context/ReadonlyStore\";\nimport { create, type UseBoundStore } from \"zustand\";\nimport type {\n MessagePartStatus,\n ToolCallMessagePartStatus,\n} from \"@assistant-ui/core\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { createContextStoreHook } from \"../../context/react/utils/createContextStoreHook\";\n\ntype SmoothContextValue = {\n useSmoothStatus: UseBoundStore<\n ReadonlyStore<MessagePartStatus | ToolCallMessagePartStatus>\n >;\n};\n\nconst SmoothContext = createContext<SmoothContextValue | null>(null);\n\nconst makeSmoothContext = (\n initialState: MessagePartStatus | ToolCallMessagePartStatus,\n) => {\n const useSmoothStatus = create(() => initialState);\n return { useSmoothStatus };\n};\n\nexport const SmoothContextProvider: FC<PropsWithChildren> = ({ children }) => {\n const outer = useSmoothContext({ optional: true });\n const aui = useAui();\n\n const [context] = useState(() =>\n makeSmoothContext(aui.part.getState().status),\n );\n\n // do not wrap if there is an outer SmoothContextProvider\n if (outer) return children;\n\n return (\n <SmoothContext.Provider value={context}>{children}</SmoothContext.Provider>\n );\n};\n\nexport const withSmoothContextProvider = <C extends ComponentType<any>>(\n Component: C,\n): C => {\n const Wrapped = forwardRef((props, ref) => {\n return (\n <SmoothContextProvider>\n <Component {...(props as any)} ref={ref} />\n </SmoothContextProvider>\n );\n });\n Wrapped.displayName = Component.displayName;\n return Wrapped as any;\n};\n\nfunction useSmoothContext(options?: {\n optional?: false | undefined;\n}): SmoothContextValue;\nfunction useSmoothContext(options?: {\n optional?: boolean | undefined;\n}): SmoothContextValue | null;\nfunction useSmoothContext(options?: { optional?: boolean | undefined }) {\n const context = useContext(SmoothContext);\n if (!options?.optional && !context)\n throw new Error(\n \"This component must be used within a SmoothContextProvider.\",\n );\n return context;\n}\n\nexport const { useSmoothStatus, useSmoothStatusStore } = createContextStoreHook(\n useSmoothContext,\n \"useSmoothStatus\",\n);\n"],"mappings":";;;;;;;;AA0BA,MAAMkB,gBAAgBf,cAAyC,IAAI;AAEnE,MAAMgB,qBACJC,iBACG;CAEH,OAAO,EAAEH,iBADeP,aAAaU,YAC5BH,EAAgB;AAC3B;AAEA,MAAaI,yBAA+CC,OAAA;CAAA,MAAAC,IAAAtB,EAAA,CAAA;CAAC,MAAA,EAAAuB,aAAAF;CAAY,IAAAG;CAAA,IAAAF,EAAA,OAAAG,OAAAC,IAAA,2BAAA,GAAA;EACxCF,KAAA,EAAAG,UAAY,KAAK;EAACL,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAAjD,MAAAM,QAAcC,iBAAiBL,EAAkB;CACjD,MAAAM,MAAYjB,OAAO;CAAE,IAAAkB;CAAA,IAAAT,EAAA,OAAAQ,IAAAE,MAAA;EAEMD,WACzBb,kBAAkBY,IAAGE,KAAKC,SAAU,CAAC,CAAAC,MAAO;EAACZ,EAAA,KAAAQ,IAAAE;EAAAV,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAD/C,MAAA,CAAAa,WAAkB5B,SAASwB,EAE3B;CAGA,IAAIH,OAAK,OAASL;CAAS,IAAAa;CAAA,IAAAd,EAAA,OAAAC,YAAAD,EAAA,OAAAa,SAAA;EAGzBC,KAAA,oBAAA,cAAA,UAAA;GAA+BD,OAAAA;GAAUZ;EAAS,CAAA;EAAyBD,EAAA,KAAAC;EAAAD,EAAA,KAAAa;EAAAb,EAAA,KAAAc;CAAA,OAAAA,KAAAd,EAAA;CAAA,OAA3Ec;AAA2E;AAI/E,MAAaC,6BACXC,cACM;CACN,MAAME,UAAUpC,YAAWqC,OAAAC,QAAA;EAAA,MAAApB,IAAAtB,EAAA,CAAA;EAGL,MAAAqB,KAAAoB;EAAY,IAAAjB;EAAA,IAAAF,EAAA,OAAAoB,OAAApB,EAAA,OAAAD,IAAA;GAD9BG,KAAA,oBAAC,uBAAD,EAAA,UACE,oBAAC,WAAD;IAAU,GAAMH;IAAoBqB;GAAG,CAAA,EADnB,CAAA;GAEEpB,EAAA,KAAAoB;GAAApB,EAAA,KAAAD;GAAAC,EAAA,KAAAE;EAAA,OAAAA,KAAAF,EAAA;EAAA,OAFxBE;CAEwB,CAE3B;CACDgB,QAAQG,cAAcL,UAAUK;CAChC,OAAOH;AACT;AAQA,SAAAX,iBAAAe,SAAA;CACE,MAAAT,UAAgB7B,WAAWW,aAAa;CACxC,IAAI,CAAC2B,SAAOjB,YAAR,CAAuBQ,SACzB,MAAM,IAAIU,MACR,6DACF;CAAE,OACGV;AAAO;AAGhB,MAAa,EAAEnB,iBAAiB8B,yBAAyBhC,uBACvDe,kBACA,iBACF"}
|
|
@@ -10,8 +10,8 @@ const DEFAULT_DRAIN_MS = 250;
|
|
|
10
10
|
const DEFAULT_MAX_CHAR_INTERVAL_MS = 5;
|
|
11
11
|
var TextStreamAnimator = class {
|
|
12
12
|
animationFrameId = null;
|
|
13
|
-
lastUpdateTime =
|
|
14
|
-
lastCommitTime =
|
|
13
|
+
lastUpdateTime = 0;
|
|
14
|
+
lastCommitTime = -Infinity;
|
|
15
15
|
targetText = "";
|
|
16
16
|
drainMs = DEFAULT_DRAIN_MS;
|
|
17
17
|
maxCharIntervalMs = DEFAULT_MAX_CHAR_INTERVAL_MS;
|
|
@@ -25,7 +25,7 @@ var TextStreamAnimator = class {
|
|
|
25
25
|
}
|
|
26
26
|
start() {
|
|
27
27
|
if (this.animationFrameId !== null) return;
|
|
28
|
-
this.lastUpdateTime =
|
|
28
|
+
this.lastUpdateTime = performance.now();
|
|
29
29
|
this.animate();
|
|
30
30
|
}
|
|
31
31
|
stop() {
|
|
@@ -35,7 +35,7 @@ var TextStreamAnimator = class {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
animate = () => {
|
|
38
|
-
const currentTime =
|
|
38
|
+
const currentTime = performance.now();
|
|
39
39
|
let timeToConsume = currentTime - this.lastUpdateTime;
|
|
40
40
|
const remainingChars = this.targetText.length - this.currentText.length;
|
|
41
41
|
const baseTimePerChar = Math.min(this.maxCharIntervalMs, this.drainMs / remainingChars);
|
|
@@ -119,7 +119,7 @@ const useSmooth = (state, smooth = false) => {
|
|
|
119
119
|
displayedText,
|
|
120
120
|
state.status
|
|
121
121
|
]);
|
|
122
|
-
const [animatorRef] = useState(new TextStreamAnimator(displayedText, setText));
|
|
122
|
+
const [animatorRef] = useState(() => new TextStreamAnimator(displayedText, setText));
|
|
123
123
|
useEffect(() => {
|
|
124
124
|
animatorRef.drainMs = drainMs;
|
|
125
125
|
animatorRef.maxCharIntervalMs = maxCharIntervalMs;
|
|
@@ -144,7 +144,7 @@ const useSmooth = (state, smooth = false) => {
|
|
|
144
144
|
if (state.status.type === "running") {
|
|
145
145
|
animatorRef.currentText = "";
|
|
146
146
|
animatorRef.targetText = text;
|
|
147
|
-
animatorRef.lastCommitTime =
|
|
147
|
+
animatorRef.lastCommitTime = -Infinity;
|
|
148
148
|
animatorRef.start();
|
|
149
149
|
} else {
|
|
150
150
|
animatorRef.currentText = text;
|