@assistant-ui/react 0.12.28 → 0.14.2
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 +58 -42
- package/dist/client/ExternalThread.d.ts +7 -0
- package/dist/client/ExternalThread.d.ts.map +1 -1
- package/dist/client/ExternalThread.js +24 -18
- package/dist/client/ExternalThread.js.map +1 -1
- package/dist/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/client/InMemoryThreadList.js +3 -0
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/client/SingleThreadList.d.ts.map +1 -1
- package/dist/client/SingleThreadList.js +3 -0
- package/dist/client/SingleThreadList.js.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.d.ts.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.js +2 -10
- package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
- package/dist/context/stores/ThreadViewport.d.ts +46 -4
- package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
- package/dist/context/stores/ThreadViewport.js +51 -7
- package/dist/context/stores/ThreadViewport.js.map +1 -1
- package/dist/index.d.ts +5 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -28
- package/dist/index.js.map +1 -1
- package/dist/legacy-runtime/cloud/auiV0.d.ts +10 -1
- package/dist/legacy-runtime/cloud/auiV0.d.ts.map +1 -1
- package/dist/legacy-runtime/cloud/auiV0.js +21 -3
- package/dist/legacy-runtime/cloud/auiV0.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js.map +1 -1
- package/dist/mcp-apps/McpAppRenderer.d.ts +28 -0
- package/dist/mcp-apps/McpAppRenderer.d.ts.map +1 -0
- package/dist/mcp-apps/McpAppRenderer.js +115 -0
- package/dist/mcp-apps/McpAppRenderer.js.map +1 -0
- package/dist/mcp-apps/McpAppsRemoteHost.d.ts +3 -0
- package/dist/mcp-apps/McpAppsRemoteHost.d.ts.map +1 -0
- package/dist/mcp-apps/McpAppsRemoteHost.js +27 -0
- package/dist/mcp-apps/McpAppsRemoteHost.js.map +1 -0
- package/dist/mcp-apps/app-frame.d.ts +3 -0
- package/dist/mcp-apps/app-frame.d.ts.map +1 -0
- package/dist/mcp-apps/app-frame.js +203 -0
- package/dist/mcp-apps/app-frame.js.map +1 -0
- package/dist/mcp-apps/bridge.d.ts +18 -0
- package/dist/mcp-apps/bridge.d.ts.map +1 -0
- package/dist/mcp-apps/bridge.js +290 -0
- package/dist/mcp-apps/bridge.js.map +1 -0
- package/dist/mcp-apps/index.d.ts +4 -0
- package/dist/mcp-apps/index.d.ts.map +1 -0
- package/dist/mcp-apps/index.js +3 -0
- package/dist/mcp-apps/index.js.map +1 -0
- package/dist/mcp-apps/types.d.ts +144 -0
- package/dist/mcp-apps/types.d.ts.map +1 -0
- package/dist/mcp-apps/types.js +3 -0
- package/dist/mcp-apps/types.js.map +1 -0
- package/dist/mcp-apps/utils.d.ts +5 -0
- package/dist/mcp-apps/utils.d.ts.map +1 -0
- package/dist/mcp-apps/utils.js +10 -0
- package/dist/mcp-apps/utils.js.map +1 -0
- package/dist/primitives/composer/ComposerInput.d.ts +6 -0
- package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +28 -6
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js +17 -1
- package/dist/primitives/composer/trigger/TriggerPopover.js.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts +33 -0
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js +80 -11
- package/dist/primitives/composer/trigger/TriggerPopoverRootContext.js.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.d.ts.map +1 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js +2 -1
- package/dist/primitives/composer/trigger/triggerKeyboardResource.js.map +1 -1
- package/dist/primitives/message/MessageRoot.d.ts +6 -30
- package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
- package/dist/primitives/message/MessageRoot.js +68 -25
- package/dist/primitives/message/MessageRoot.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartSource.d.ts +22 -3
- package/dist/primitives/messagePart/useMessagePartSource.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewport.d.ts +38 -0
- package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +53 -5
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.d.ts +2 -1
- package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js +2 -1
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts +22 -0
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js +53 -0
- package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js.map +1 -0
- package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts +5 -0
- package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/createReserveObservers.js +38 -0
- package/dist/primitives/thread/topAnchor/createReserveObservers.js.map +1 -0
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts +22 -0
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +75 -0
- package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js.map +1 -0
- package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +15 -0
- package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/topAnchorTurn.js +13 -0
- package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -0
- package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts +15 -0
- package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/topAnchorUtils.js +51 -0
- package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -0
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts +7 -0
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts.map +1 -0
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +18 -0
- package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js.map +1 -0
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +13 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/primitives/thread.d.ts +0 -1
- package/dist/primitives/thread.d.ts.map +1 -1
- package/dist/primitives/thread.js +0 -1
- package/dist/primitives/thread.js.map +1 -1
- package/dist/primitives/threadList/ThreadListLoadMore.d.ts +13 -0
- package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -0
- package/dist/primitives/threadList/ThreadListLoadMore.js +11 -0
- package/dist/primitives/threadList/ThreadListLoadMore.js.map +1 -0
- package/dist/primitives/threadList.d.ts +1 -0
- package/dist/primitives/threadList.d.ts.map +1 -1
- package/dist/primitives/threadList.js +1 -0
- package/dist/primitives/threadList.js.map +1 -1
- package/dist/utils/hooks/useManagedRef.d.ts.map +1 -1
- package/dist/utils/hooks/useManagedRef.js +1 -0
- package/dist/utils/hooks/useManagedRef.js.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
- package/dist/utils/hooks/useOnResizeContent.js +1 -2
- package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
- package/package.json +13 -13
- package/src/client/ExternalThread.ts +32 -19
- package/src/client/InMemoryThreadList.ts +3 -0
- package/src/client/SingleThreadList.ts +3 -0
- package/src/context/providers/ThreadViewportProvider.tsx +2 -12
- package/src/context/stores/ThreadViewport.ts +111 -11
- package/src/index.ts +20 -34
- package/src/legacy-runtime/cloud/auiV0.ts +37 -4
- package/src/legacy-runtime/runtime-cores/assistant-transport/utils.ts +1 -5
- package/src/mcp-apps/McpAppRenderer.tsx +215 -0
- package/src/mcp-apps/McpAppsRemoteHost.ts +52 -0
- package/src/mcp-apps/app-frame.tsx +280 -0
- package/src/mcp-apps/bridge.test.ts +391 -0
- package/src/mcp-apps/bridge.ts +435 -0
- package/src/mcp-apps/index.ts +16 -0
- package/src/mcp-apps/types.ts +158 -0
- package/src/mcp-apps/utils.ts +16 -0
- package/src/primitives/composer/ComposerInput.test.tsx +280 -0
- package/src/primitives/composer/ComposerInput.tsx +29 -6
- package/src/primitives/composer/trigger/TriggerPopover.tsx +21 -1
- package/src/primitives/composer/trigger/TriggerPopoverRootContext.test.tsx +152 -0
- package/src/primitives/composer/trigger/TriggerPopoverRootContext.tsx +134 -17
- package/src/primitives/composer/trigger/triggerKeyboardResource.test.ts +236 -0
- package/src/primitives/composer/trigger/triggerKeyboardResource.ts +2 -1
- package/src/primitives/message/MessageRoot.tsx +135 -57
- package/src/primitives/thread/ThreadViewport.tsx +95 -4
- package/src/primitives/thread/ThreadViewportFooter.tsx +2 -1
- package/src/primitives/thread/topAnchor/computeTopAnchorSlack.test.ts +131 -0
- package/src/primitives/thread/topAnchor/computeTopAnchorSlack.ts +94 -0
- package/src/primitives/thread/topAnchor/createReserveObservers.ts +50 -0
- package/src/primitives/thread/topAnchor/mountTopAnchorReserve.test.ts +131 -0
- package/src/primitives/thread/topAnchor/mountTopAnchorReserve.ts +127 -0
- package/src/primitives/thread/topAnchor/topAnchorTurn.test.ts +46 -0
- package/src/primitives/thread/topAnchor/topAnchorTurn.ts +30 -0
- package/src/primitives/thread/topAnchor/topAnchorUtils.ts +58 -0
- package/src/primitives/thread/topAnchor/useTopAnchorReserve.ts +19 -0
- package/src/primitives/thread/useThreadViewportAutoScroll.ts +15 -1
- package/src/primitives/thread.ts +0 -1
- package/src/primitives/threadList/ThreadListLoadMore.tsx +24 -0
- package/src/primitives/threadList.ts +1 -0
- package/src/tests/BaseComposerRuntimeCore.test.ts +4 -0
- package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +138 -0
- package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +28 -17
- package/src/tests/auiV0Encode.test.ts +55 -0
- package/src/utils/hooks/useManagedRef.ts +1 -0
- package/src/utils/hooks/useOnResizeContent.ts +1 -2
- package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.d.ts +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.d.ts.map +0 -1
- package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.js +0 -3
- package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.js.map +0 -1
- package/dist/primitives/thread/ThreadViewportSlack.d.ts +0 -20
- package/dist/primitives/thread/ThreadViewportSlack.d.ts.map +0 -1
- package/dist/primitives/thread/ThreadViewportSlack.js +0 -80
- package/dist/primitives/thread/ThreadViewportSlack.js.map +0 -1
- package/src/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.ts +0 -6
- package/src/primitives/thread/ThreadViewportSlack.tsx +0 -116
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
getActiveTopAnchorAnchorId,
|
|
4
|
+
getActiveTopAnchorTargetId,
|
|
5
|
+
getActiveTopAnchorTurn,
|
|
6
|
+
} from "./topAnchorTurn";
|
|
7
|
+
|
|
8
|
+
describe("topAnchorTurn", () => {
|
|
9
|
+
it("does not activate history-loaded messages", () => {
|
|
10
|
+
const messages = [
|
|
11
|
+
{ id: "user-1", role: "user" },
|
|
12
|
+
{ id: "assistant-1", role: "assistant" },
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
expect(getActiveTopAnchorTurn({ isRunning: false, messages })).toBe(null);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("activates the live user/assistant pair while running", () => {
|
|
19
|
+
const messages = [
|
|
20
|
+
{ id: "assistant-1", role: "assistant" },
|
|
21
|
+
{ id: "user-2", role: "user" },
|
|
22
|
+
{ id: "assistant-2", role: "assistant" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
expect(getActiveTopAnchorTurn({ isRunning: true, messages })).toEqual({
|
|
26
|
+
anchorId: "user-2",
|
|
27
|
+
targetId: "assistant-2",
|
|
28
|
+
});
|
|
29
|
+
expect(getActiveTopAnchorAnchorId({ isRunning: true, messages })).toBe(
|
|
30
|
+
"user-2",
|
|
31
|
+
);
|
|
32
|
+
expect(getActiveTopAnchorTargetId({ isRunning: true, messages })).toBe(
|
|
33
|
+
"assistant-2",
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("ignores running states without a trailing user/assistant pair", () => {
|
|
38
|
+
const messages = [
|
|
39
|
+
{ id: "user-1", role: "user" },
|
|
40
|
+
{ id: "assistant-1", role: "assistant" },
|
|
41
|
+
{ id: "user-2", role: "user" },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
expect(getActiveTopAnchorTurn({ isRunning: true, messages })).toBe(null);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
type TopAnchorTurnMessage = {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly role: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const getActiveTopAnchorTurn = ({
|
|
9
|
+
isRunning,
|
|
10
|
+
messages,
|
|
11
|
+
}: {
|
|
12
|
+
readonly isRunning: boolean;
|
|
13
|
+
readonly messages: readonly TopAnchorTurnMessage[];
|
|
14
|
+
}) => {
|
|
15
|
+
if (!isRunning) return null;
|
|
16
|
+
|
|
17
|
+
const target = messages.at(-1);
|
|
18
|
+
const anchor = messages.at(-2);
|
|
19
|
+
if (anchor?.role !== "user" || target?.role !== "assistant") return null;
|
|
20
|
+
|
|
21
|
+
return { anchorId: anchor.id, targetId: target.id };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getActiveTopAnchorAnchorId = (
|
|
25
|
+
options: Parameters<typeof getActiveTopAnchorTurn>[0],
|
|
26
|
+
) => getActiveTopAnchorTurn(options)?.anchorId;
|
|
27
|
+
|
|
28
|
+
export const getActiveTopAnchorTargetId = (
|
|
29
|
+
options: Parameters<typeof getActiveTopAnchorTurn>[0],
|
|
30
|
+
) => getActiveTopAnchorTurn(options)?.targetId;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert a supported CSS length string (`px`, `em`, `rem`) into pixels,
|
|
5
|
+
* resolving font-relative units against the supplied element's computed style.
|
|
6
|
+
* Unsupported or malformed values disable the tall-message clamp.
|
|
7
|
+
*
|
|
8
|
+
* Part of the top-anchor package's public input contract: consumers may pass
|
|
9
|
+
* clamp configuration as supported CSS-length strings, and this function is the
|
|
10
|
+
* single place that converts them into the pixel values the package operates on.
|
|
11
|
+
*/
|
|
12
|
+
export const parseCssLength = (value: string, element: HTMLElement): number => {
|
|
13
|
+
const match = value.trim().match(/^(\d+(?:\.\d+)?|\.\d+)(em|px|rem)$/);
|
|
14
|
+
if (!match) return Number.POSITIVE_INFINITY;
|
|
15
|
+
|
|
16
|
+
const num = Number(match[1]);
|
|
17
|
+
const unit = match[2];
|
|
18
|
+
|
|
19
|
+
if (unit === "px") return num;
|
|
20
|
+
if (unit === "em") {
|
|
21
|
+
const fontSize = parseFloat(getComputedStyle(element).fontSize) || 16;
|
|
22
|
+
return num * fontSize;
|
|
23
|
+
}
|
|
24
|
+
if (unit === "rem") {
|
|
25
|
+
const rootFontSize =
|
|
26
|
+
parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
27
|
+
return num * rootFontSize;
|
|
28
|
+
}
|
|
29
|
+
return Number.POSITIVE_INFINITY;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getAnchorId = (anchor: HTMLElement) => anchor.dataset.messageId;
|
|
33
|
+
|
|
34
|
+
export const createReserveElement = () => {
|
|
35
|
+
const reserve = document.createElement("div");
|
|
36
|
+
reserve.dataset.auiTopAnchorReserve = "";
|
|
37
|
+
reserve.style.height = "0px";
|
|
38
|
+
reserve.style.flexShrink = "0";
|
|
39
|
+
reserve.style.pointerEvents = "none";
|
|
40
|
+
reserve.setAttribute("aria-hidden", "true");
|
|
41
|
+
|
|
42
|
+
return reserve;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const setReserveHeight = (reserve: HTMLElement, height: number) => {
|
|
46
|
+
const nextHeight = `${height}px`;
|
|
47
|
+
if (reserve.style.height !== nextHeight) {
|
|
48
|
+
reserve.style.height = nextHeight;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return false;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const snapScrollTop = (top: number) => {
|
|
56
|
+
const pixelRatio = window.devicePixelRatio || 1;
|
|
57
|
+
return Math.round(top * pixelRatio) / pixelRatio;
|
|
58
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useLayoutEffect } from "react";
|
|
4
|
+
import { useThreadViewportStore } from "../../../context/react/ThreadViewportContext";
|
|
5
|
+
import { mountTopAnchorReserve } from "./mountTopAnchorReserve";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Mounts the top-turn-anchor reserve element against the active
|
|
9
|
+
* `ThreadViewport` store. Call this from inside the scrollable viewport so
|
|
10
|
+
* the reserve `<div>` is appended next to the streaming assistant message.
|
|
11
|
+
*/
|
|
12
|
+
export const useTopAnchorReserve = (enabled: boolean) => {
|
|
13
|
+
const threadViewportStore = useThreadViewportStore();
|
|
14
|
+
|
|
15
|
+
useLayoutEffect(() => {
|
|
16
|
+
if (!enabled) return;
|
|
17
|
+
return mountTopAnchorReserve(threadViewportStore);
|
|
18
|
+
}, [enabled, threadViewportStore]);
|
|
19
|
+
};
|
|
@@ -70,6 +70,15 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
|
|
|
70
70
|
div.scrollTo({ top: div.scrollHeight, behavior });
|
|
71
71
|
}, []);
|
|
72
72
|
|
|
73
|
+
const hasActiveTopAnchor = useCallback(() => {
|
|
74
|
+
const state = threadViewportStore.getState();
|
|
75
|
+
return (
|
|
76
|
+
state.turnAnchor === "top" &&
|
|
77
|
+
state.element.viewport === divRef.current &&
|
|
78
|
+
state.element.anchor !== null
|
|
79
|
+
);
|
|
80
|
+
}, [threadViewportStore]);
|
|
81
|
+
|
|
73
82
|
const handleScroll = () => {
|
|
74
83
|
const div = divRef.current;
|
|
75
84
|
if (!div) return;
|
|
@@ -101,7 +110,10 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
|
|
|
101
110
|
|
|
102
111
|
const resizeRef = useOnResizeContent(() => {
|
|
103
112
|
const scrollBehavior = scrollingToBottomBehaviorRef.current;
|
|
104
|
-
if (scrollBehavior) {
|
|
113
|
+
if (scrollBehavior && hasActiveTopAnchor()) {
|
|
114
|
+
// Let the top-anchor reserve own scrolling while a run starts to avoid a bottom-scroll race.
|
|
115
|
+
scrollingToBottomBehaviorRef.current = null;
|
|
116
|
+
} else if (scrollBehavior) {
|
|
105
117
|
scrollToBottom(scrollBehavior);
|
|
106
118
|
} else if (autoScroll && threadViewportStore.getState().isAtBottom) {
|
|
107
119
|
scrollToBottom("instant");
|
|
@@ -124,6 +136,8 @@ export const useThreadViewportAutoScroll = <TElement extends HTMLElement>({
|
|
|
124
136
|
// autoscroll on run start
|
|
125
137
|
useAuiEvent("thread.runStart", () => {
|
|
126
138
|
if (!scrollToBottomOnRunStart) return;
|
|
139
|
+
if (threadViewportStore.getState().turnAnchor === "top") return;
|
|
140
|
+
|
|
127
141
|
scrollingToBottomBehaviorRef.current = "auto";
|
|
128
142
|
requestAnimationFrame(() => {
|
|
129
143
|
scrollToBottom("auto");
|
package/src/primitives/thread.ts
CHANGED
|
@@ -4,7 +4,6 @@ export { ThreadPrimitiveIf as If } from "./thread/ThreadIf";
|
|
|
4
4
|
export { ThreadPrimitiveViewport as Viewport } from "./thread/ThreadViewport";
|
|
5
5
|
export { ThreadPrimitiveViewportProvider as ViewportProvider } from "../context/providers/ThreadViewportProvider";
|
|
6
6
|
export { ThreadPrimitiveViewportFooter as ViewportFooter } from "./thread/ThreadViewportFooter";
|
|
7
|
-
export { ThreadPrimitiveViewportSlack as ViewportSlack } from "./thread/ThreadViewportSlack";
|
|
8
7
|
export { ThreadPrimitiveMessages as Messages } from "./thread/ThreadMessages";
|
|
9
8
|
export { ThreadPrimitiveMessageByIndex as MessageByIndex } from "./thread/ThreadMessages";
|
|
10
9
|
export { ThreadPrimitiveScrollToBottom as ScrollToBottom } from "./thread/ThreadScrollToBottom";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ActionButtonElement,
|
|
5
|
+
type ActionButtonProps,
|
|
6
|
+
createActionButton,
|
|
7
|
+
} from "../../utils/createActionButton";
|
|
8
|
+
import { useThreadListLoadMore as useThreadListLoadMoreBehavior } from "@assistant-ui/core/react";
|
|
9
|
+
|
|
10
|
+
const useThreadListLoadMore = () => {
|
|
11
|
+
const { loadMore, disabled } = useThreadListLoadMoreBehavior();
|
|
12
|
+
if (disabled) return null;
|
|
13
|
+
return loadMore;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export namespace ThreadListPrimitiveLoadMore {
|
|
17
|
+
export type Element = ActionButtonElement;
|
|
18
|
+
export type Props = ActionButtonProps<typeof useThreadListLoadMore>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const ThreadListPrimitiveLoadMore = createActionButton(
|
|
22
|
+
"ThreadListPrimitive.LoadMore",
|
|
23
|
+
useThreadListLoadMore,
|
|
24
|
+
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ThreadListPrimitiveNew as New } from "./threadList/ThreadListNew";
|
|
2
2
|
export { ThreadListPrimitiveItems as Items } from "./threadList/ThreadListItems";
|
|
3
3
|
export { ThreadListPrimitiveItemByIndex as ItemByIndex } from "./threadList/ThreadListItems";
|
|
4
|
+
export { ThreadListPrimitiveLoadMore as LoadMore } from "./threadList/ThreadListLoadMore";
|
|
4
5
|
export { ThreadListPrimitiveRoot as Root } from "./threadList/ThreadListRoot";
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
|
|
3
|
+
import { act, render, waitFor } from "@testing-library/react";
|
|
4
|
+
import type { FC, PropsWithChildren } from "react";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import {
|
|
7
|
+
RuntimeAdapterProvider,
|
|
8
|
+
useRemoteThreadListRuntime,
|
|
9
|
+
useRuntimeAdapters,
|
|
10
|
+
} from "@assistant-ui/core/react";
|
|
11
|
+
import { makeAdapter } from "./remote-thread-list-test-helpers";
|
|
12
|
+
import { useLocalRuntime } from "../legacy-runtime/runtime-cores/local/useLocalRuntime";
|
|
13
|
+
import { AssistantRuntimeProvider } from "../context";
|
|
14
|
+
import type { ChatModelAdapter, RemoteThreadListAdapter } from "../index";
|
|
15
|
+
import type {
|
|
16
|
+
RuntimeAdapters as RuntimeAdaptersShape,
|
|
17
|
+
ThreadHistoryAdapter,
|
|
18
|
+
} from "@assistant-ui/core";
|
|
19
|
+
|
|
20
|
+
type CapturedAdapters = RuntimeAdaptersShape | null;
|
|
21
|
+
|
|
22
|
+
const noOpAdapter: ChatModelAdapter = {
|
|
23
|
+
async *run() {},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const dummyHistory: ThreadHistoryAdapter = {
|
|
27
|
+
load: async () => ({ messages: [] }),
|
|
28
|
+
append: async () => {},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const makeRuntimeHook = (capture: { adapters: CapturedAdapters }) =>
|
|
32
|
+
function useTestRuntimeHook() {
|
|
33
|
+
capture.adapters = useRuntimeAdapters();
|
|
34
|
+
return useLocalRuntime(noOpAdapter);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
async function renderAndWaitForBinder(
|
|
38
|
+
adapter: RemoteThreadListAdapter,
|
|
39
|
+
capture: { adapters: CapturedAdapters },
|
|
40
|
+
) {
|
|
41
|
+
const Inner: FC = () => {
|
|
42
|
+
const runtime = useRemoteThreadListRuntime({
|
|
43
|
+
runtimeHook: makeRuntimeHook(capture),
|
|
44
|
+
adapter,
|
|
45
|
+
});
|
|
46
|
+
return (
|
|
47
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
48
|
+
{null}
|
|
49
|
+
</AssistantRuntimeProvider>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// first thread instance arrives asynchronously via switchToNewThread.
|
|
54
|
+
await act(async () => {
|
|
55
|
+
render(<Inner />);
|
|
56
|
+
});
|
|
57
|
+
await waitFor(() => expect(capture.adapters).not.toBeNull());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const wrapInRuntimeAdapterProvider = (
|
|
61
|
+
history: ThreadHistoryAdapter,
|
|
62
|
+
): FC<PropsWithChildren> =>
|
|
63
|
+
function Provider({ children }) {
|
|
64
|
+
return (
|
|
65
|
+
<RuntimeAdapterProvider adapters={{ history }}>
|
|
66
|
+
{children}
|
|
67
|
+
</RuntimeAdapterProvider>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
describe("RemoteThreadListAdapter.unstable_Provider", () => {
|
|
72
|
+
it("makes RuntimeAdapterProvider context visible to the runtime hook", async () => {
|
|
73
|
+
const capture: { adapters: CapturedAdapters } = { adapters: null };
|
|
74
|
+
const adapter = makeAdapter({
|
|
75
|
+
unstable_Provider: wrapInRuntimeAdapterProvider(dummyHistory),
|
|
76
|
+
});
|
|
77
|
+
await renderAndWaitForBinder(adapter, capture);
|
|
78
|
+
|
|
79
|
+
expect(capture.adapters?.history).toBe(dummyHistory);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("preserves modelContext from the outer runtime-core RuntimeAdapterProvider", async () => {
|
|
83
|
+
const capture: { adapters: CapturedAdapters } = { adapters: null };
|
|
84
|
+
const adapter = makeAdapter({
|
|
85
|
+
unstable_Provider: wrapInRuntimeAdapterProvider(dummyHistory),
|
|
86
|
+
});
|
|
87
|
+
await renderAndWaitForBinder(adapter, capture);
|
|
88
|
+
|
|
89
|
+
expect(capture.adapters?.history).toBe(dummyHistory);
|
|
90
|
+
expect(capture.adapters?.modelContext).toBeDefined();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("returns no history when no Provider is supplied", async () => {
|
|
94
|
+
const capture: { adapters: CapturedAdapters } = { adapters: null };
|
|
95
|
+
const adapter = makeAdapter();
|
|
96
|
+
await renderAndWaitForBinder(adapter, capture);
|
|
97
|
+
|
|
98
|
+
expect(capture.adapters?.history).toBeUndefined();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("picks up a swapped Provider on re-render", async () => {
|
|
102
|
+
const capture: { adapters: CapturedAdapters } = { adapters: null };
|
|
103
|
+
const firstHistory: ThreadHistoryAdapter = {
|
|
104
|
+
load: async () => ({ messages: [] }),
|
|
105
|
+
append: async () => {},
|
|
106
|
+
};
|
|
107
|
+
const secondHistory: ThreadHistoryAdapter = {
|
|
108
|
+
load: async () => ({ messages: [] }),
|
|
109
|
+
append: async () => {},
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const Inner: FC<{ history: ThreadHistoryAdapter }> = ({ history }) => {
|
|
113
|
+
const adapter = makeAdapter({
|
|
114
|
+
unstable_Provider: wrapInRuntimeAdapterProvider(history),
|
|
115
|
+
});
|
|
116
|
+
const runtime = useRemoteThreadListRuntime({
|
|
117
|
+
runtimeHook: makeRuntimeHook(capture),
|
|
118
|
+
adapter,
|
|
119
|
+
});
|
|
120
|
+
return (
|
|
121
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
122
|
+
{null}
|
|
123
|
+
</AssistantRuntimeProvider>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let result: ReturnType<typeof render>;
|
|
128
|
+
await act(async () => {
|
|
129
|
+
result = render(<Inner history={firstHistory} />);
|
|
130
|
+
});
|
|
131
|
+
await waitFor(() => expect(capture.adapters?.history).toBe(firstHistory));
|
|
132
|
+
|
|
133
|
+
await act(async () => {
|
|
134
|
+
result!.rerender(<Inner history={secondHistory} />);
|
|
135
|
+
});
|
|
136
|
+
await waitFor(() => expect(capture.adapters?.history).toBe(secondHistory));
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @vitest-environment jsdom
|
|
2
2
|
|
|
3
|
-
import { render } from "@testing-library/react";
|
|
3
|
+
import { act, render } from "@testing-library/react";
|
|
4
4
|
import { type FC, type PropsWithChildren, useState } from "react";
|
|
5
|
-
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
import { useRemoteThreadListRuntime } from "@assistant-ui/core/react";
|
|
7
7
|
import { makeAdapter } from "./remote-thread-list-test-helpers";
|
|
8
8
|
import type { AssistantRuntime } from "@assistant-ui/core";
|
|
@@ -39,14 +39,13 @@ const RuntimeCapture: FC<{
|
|
|
39
39
|
return null;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
};
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
vi.useRealTimers();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("useRemoteThreadListRuntime with unstable_Provider", () => {
|
|
47
|
+
it("composer.setText works when unstable_Provider renders children unconditionally", () => {
|
|
48
|
+
const Provider: FC<PropsWithChildren> = ({ children }) => <>{children}</>;
|
|
50
49
|
const adapter = makeAdapter({ unstable_Provider: Provider });
|
|
51
50
|
|
|
52
51
|
const runtimeRef: { current: AssistantRuntime | null } = { current: null };
|
|
@@ -61,19 +60,31 @@ describe("useRemoteThreadListRuntime with a deferred unstable_Provider", () => {
|
|
|
61
60
|
expect(() => runtime!.thread.composer.setText("hello")).not.toThrow();
|
|
62
61
|
});
|
|
63
62
|
|
|
64
|
-
it("
|
|
65
|
-
|
|
63
|
+
it("warns in dev when unstable_Provider defers children", () => {
|
|
64
|
+
vi.useFakeTimers();
|
|
65
|
+
const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
66
|
+
|
|
67
|
+
const Provider: FC<PropsWithChildren> = ({ children }) => {
|
|
68
|
+
const [ready] = useState(false);
|
|
69
|
+
if (!ready) return null;
|
|
70
|
+
return <>{children}</>;
|
|
71
|
+
};
|
|
66
72
|
const adapter = makeAdapter({ unstable_Provider: Provider });
|
|
67
73
|
|
|
68
|
-
const runtimeRef: { current: AssistantRuntime | null } = { current: null };
|
|
69
74
|
render(
|
|
70
75
|
<RuntimeProvider adapter={adapter}>
|
|
71
|
-
<
|
|
76
|
+
<div />
|
|
72
77
|
</RuntimeProvider>,
|
|
73
78
|
);
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
act(() => {
|
|
81
|
+
vi.advanceTimersByTime(150);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(warn).toHaveBeenCalledWith(
|
|
85
|
+
expect.stringContaining("did not render its `children` synchronously"),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
warn.mockRestore();
|
|
78
89
|
});
|
|
79
90
|
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { auiV0Encode } from "../legacy-runtime/cloud/auiV0";
|
|
3
|
+
|
|
4
|
+
describe("auiV0Encode", () => {
|
|
5
|
+
it("preserves document source parts in the legacy cloud encoder", () => {
|
|
6
|
+
const encoded = auiV0Encode({
|
|
7
|
+
id: "m1",
|
|
8
|
+
createdAt: new Date("2026-03-15T00:00:00.000Z"),
|
|
9
|
+
role: "assistant",
|
|
10
|
+
status: { type: "complete", reason: "stop" },
|
|
11
|
+
metadata: {
|
|
12
|
+
unstable_state: undefined,
|
|
13
|
+
unstable_annotations: [],
|
|
14
|
+
unstable_data: [],
|
|
15
|
+
steps: [],
|
|
16
|
+
custom: {},
|
|
17
|
+
},
|
|
18
|
+
content: [
|
|
19
|
+
{
|
|
20
|
+
type: "source",
|
|
21
|
+
sourceType: "document",
|
|
22
|
+
id: "doc_123",
|
|
23
|
+
title: "proposal.pdf",
|
|
24
|
+
mediaType: "application/pdf",
|
|
25
|
+
filename: "proposal.pdf",
|
|
26
|
+
providerMetadata: {
|
|
27
|
+
openai: {
|
|
28
|
+
type: "file_citation",
|
|
29
|
+
fileId: "file_123",
|
|
30
|
+
index: 0,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(encoded.content).toEqual([
|
|
38
|
+
{
|
|
39
|
+
type: "source",
|
|
40
|
+
sourceType: "document",
|
|
41
|
+
id: "doc_123",
|
|
42
|
+
title: "proposal.pdf",
|
|
43
|
+
mediaType: "application/pdf",
|
|
44
|
+
filename: "proposal.pdf",
|
|
45
|
+
providerMetadata: {
|
|
46
|
+
openai: {
|
|
47
|
+
type: "file_citation",
|
|
48
|
+
fileId: "file_123",
|
|
49
|
+
index: 0,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -13,8 +13,7 @@ export const useOnResizeContent = (callback: () => void) => {
|
|
|
13
13
|
|
|
14
14
|
const mutationObserver = new MutationObserver((mutations) => {
|
|
15
15
|
// Filter out style-only attribute mutations to prevent feedback loops
|
|
16
|
-
// with
|
|
17
|
-
// to viewport changes
|
|
16
|
+
// with code paths that write styles in response to viewport changes.
|
|
18
17
|
const hasRelevantMutation = mutations.some(
|
|
19
18
|
(m) => m.type !== "attributes" || m.attributeName !== "style",
|
|
20
19
|
);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getExternalStoreMessage.d.ts","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getExternalStoreMessage.js","sourceRoot":"","sources":["../../../../src/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type FC, type ReactNode } from "react";
|
|
2
|
-
export type ThreadViewportSlackProps = {
|
|
3
|
-
/** Threshold at which the user message height clamps to the offset */
|
|
4
|
-
fillClampThreshold?: string | undefined;
|
|
5
|
-
/** Offset used when clamping large user messages */
|
|
6
|
-
fillClampOffset?: string | undefined;
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* A slot component that provides minimum height to enable scroll anchoring.
|
|
11
|
-
*
|
|
12
|
-
* When using `turnAnchor="top"`, this component ensures there is
|
|
13
|
-
* enough scroll room below the anchor point (last user message) for it to scroll
|
|
14
|
-
* to the top of the viewport. The min-height is applied only to the last
|
|
15
|
-
* assistant message.
|
|
16
|
-
*
|
|
17
|
-
* This component is used internally by MessagePrimitive.Root.
|
|
18
|
-
*/
|
|
19
|
-
export declare const ThreadPrimitiveViewportSlack: FC<ThreadViewportSlackProps>;
|
|
20
|
-
//# sourceMappingURL=ThreadViewportSlack.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadViewportSlack.d.ts","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadViewportSlack.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,EAAE,EACP,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AA2Bf,MAAM,MAAM,wBAAwB,GAAG;IACrC,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,oDAAoD;IACpD,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,EAAE,EAAE,CAAC,wBAAwB,CA2DrE,CAAC"}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Slot } from "radix-ui";
|
|
4
|
-
import { createContext, useCallback, useContext, } from "react";
|
|
5
|
-
import { useThreadViewportStore } from "../../context/react/ThreadViewportContext.js";
|
|
6
|
-
import { useAuiState } from "@assistant-ui/store";
|
|
7
|
-
import { useManagedRef } from "../../utils/hooks/useManagedRef.js";
|
|
8
|
-
const SlackNestingContext = createContext(false);
|
|
9
|
-
const parseCssLength = (value, element) => {
|
|
10
|
-
const match = value.match(/^([\d.]+)(em|px|rem)$/);
|
|
11
|
-
if (!match)
|
|
12
|
-
return 0;
|
|
13
|
-
const num = parseFloat(match[1]);
|
|
14
|
-
const unit = match[2];
|
|
15
|
-
if (unit === "px")
|
|
16
|
-
return num;
|
|
17
|
-
if (unit === "em") {
|
|
18
|
-
const fontSize = parseFloat(getComputedStyle(element).fontSize) || 16;
|
|
19
|
-
return num * fontSize;
|
|
20
|
-
}
|
|
21
|
-
if (unit === "rem") {
|
|
22
|
-
const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
23
|
-
return num * rootFontSize;
|
|
24
|
-
}
|
|
25
|
-
return 0;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* A slot component that provides minimum height to enable scroll anchoring.
|
|
29
|
-
*
|
|
30
|
-
* When using `turnAnchor="top"`, this component ensures there is
|
|
31
|
-
* enough scroll room below the anchor point (last user message) for it to scroll
|
|
32
|
-
* to the top of the viewport. The min-height is applied only to the last
|
|
33
|
-
* assistant message.
|
|
34
|
-
*
|
|
35
|
-
* This component is used internally by MessagePrimitive.Root.
|
|
36
|
-
*/
|
|
37
|
-
export const ThreadPrimitiveViewportSlack = ({ children, fillClampThreshold = "10em", fillClampOffset = "6em", }) => {
|
|
38
|
-
const shouldApplySlack = useAuiState(
|
|
39
|
-
// only add slack to the last assistant message following a user message (valid turn)
|
|
40
|
-
(s) => s.message.isLast &&
|
|
41
|
-
s.message.role === "assistant" &&
|
|
42
|
-
s.message.index >= 1 &&
|
|
43
|
-
s.thread.messages.at(s.message.index - 1)?.role === "user");
|
|
44
|
-
const threadViewportStore = useThreadViewportStore({ optional: true });
|
|
45
|
-
const isNested = useContext(SlackNestingContext);
|
|
46
|
-
const callback = useCallback((el) => {
|
|
47
|
-
if (!threadViewportStore || isNested)
|
|
48
|
-
return;
|
|
49
|
-
const updateMinHeight = () => {
|
|
50
|
-
const state = threadViewportStore.getState();
|
|
51
|
-
if (state.turnAnchor === "top" && shouldApplySlack) {
|
|
52
|
-
const { viewport, inset, userMessage } = state.height;
|
|
53
|
-
const threshold = parseCssLength(fillClampThreshold, el);
|
|
54
|
-
const offset = parseCssLength(fillClampOffset, el);
|
|
55
|
-
const clampAdjustment = userMessage <= threshold ? userMessage : offset;
|
|
56
|
-
const minHeight = Math.max(0, viewport - inset - clampAdjustment);
|
|
57
|
-
el.style.minHeight = `${minHeight}px`;
|
|
58
|
-
el.style.flexShrink = "0";
|
|
59
|
-
el.style.transition = "min-height 0s";
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
el.style.minHeight = "";
|
|
63
|
-
el.style.flexShrink = "";
|
|
64
|
-
el.style.transition = "";
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
updateMinHeight();
|
|
68
|
-
return threadViewportStore.subscribe(updateMinHeight);
|
|
69
|
-
}, [
|
|
70
|
-
threadViewportStore,
|
|
71
|
-
shouldApplySlack,
|
|
72
|
-
isNested,
|
|
73
|
-
fillClampThreshold,
|
|
74
|
-
fillClampOffset,
|
|
75
|
-
]);
|
|
76
|
-
const ref = useManagedRef(callback);
|
|
77
|
-
return (_jsx(SlackNestingContext.Provider, { value: true, children: _jsx(Slot.Root, { ref: ref, children: children }) }));
|
|
78
|
-
};
|
|
79
|
-
ThreadPrimitiveViewportSlack.displayName = "ThreadPrimitive.ViewportSlack";
|
|
80
|
-
//# sourceMappingURL=ThreadViewportSlack.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadViewportSlack.js","sourceRoot":"","sources":["../../../src/primitives/thread/ThreadViewportSlack.tsx"],"names":[],"mappings":"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"}
|