@assistant-ui/react
Version:
TypeScript/React library for AI Chat
80 lines (79 loc) • 2.87 kB
JavaScript
"use client";
// src/primitives/thread/ThreadViewportSlack.tsx
import { Slot } from "@radix-ui/react-slot";
import {
createContext,
useCallback,
useContext
} from "react";
import { useThreadViewportStore } from "../../context/react/ThreadViewportContext.js";
import { useAssistantState } from "../../context/index.js";
import { useManagedRef } from "../../utils/hooks/useManagedRef.js";
import { jsx } from "react/jsx-runtime";
var SlackNestingContext = createContext(false);
var parseCssLength = (value, element) => {
const match = value.match(/^([\d.]+)(em|px|rem)$/);
if (!match) return 0;
const num = parseFloat(match[1]);
const unit = match[2];
if (unit === "px") return num;
if (unit === "em") {
const fontSize = parseFloat(getComputedStyle(element).fontSize) || 16;
return num * fontSize;
}
if (unit === "rem") {
const rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
return num * rootFontSize;
}
return 0;
};
var ThreadPrimitiveViewportSlack = ({
children,
fillClampThreshold = "10em",
fillClampOffset = "6em"
}) => {
const isLast = useAssistantState(
// only add slack if the message is the last message and we already have at least 3 messages
({ message }) => message.isLast && message.index >= 2
);
const threadViewportStore = useThreadViewportStore({ optional: true });
const isNested = useContext(SlackNestingContext);
const callback = useCallback(
(el) => {
if (!threadViewportStore || isNested) return;
const updateMinHeight = () => {
const state = threadViewportStore.getState();
if (state.turnAnchor === "top" && isLast) {
const { viewport, inset, userMessage } = state.height;
const threshold = parseCssLength(fillClampThreshold, el);
const offset = parseCssLength(fillClampOffset, el);
const clampAdjustment = userMessage <= threshold ? userMessage : offset;
const minHeight = Math.max(0, viewport - inset - clampAdjustment);
el.style.minHeight = `${minHeight}px`;
el.style.flexShrink = "0";
el.style.transition = "min-height 0s";
} else {
el.style.minHeight = "";
el.style.flexShrink = "";
el.style.transition = "";
}
};
updateMinHeight();
return threadViewportStore.subscribe(updateMinHeight);
},
[
threadViewportStore,
isLast,
isNested,
fillClampThreshold,
fillClampOffset
]
);
const ref = useManagedRef(callback);
return /* @__PURE__ */ jsx(SlackNestingContext.Provider, { value: true, children: /* @__PURE__ */ jsx(Slot, { ref, children }) });
};
ThreadPrimitiveViewportSlack.displayName = "ThreadPrimitive.ViewportSlack";
export {
ThreadPrimitiveViewportSlack
};
//# sourceMappingURL=ThreadViewportSlack.js.map