@assistant-ui/react
Version:
TypeScript/React library for AI Chat
75 lines • 3.13 kB
JavaScript
"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { forwardRef } from "react";
import { composeEventHandlers } from "@radix-ui/primitive";
import { Primitive } from "@radix-ui/react-primitive";
import { useCallback } from "react";
import { useAssistantState, useAssistantApi } from "../../context/index.js";
/**
* Hook that provides copy functionality for action bar buttons.
*
* This hook returns a callback function that copies message content to the clipboard,
* or null if copying is not available. It handles both regular message content and
* composer text when in editing mode.
*
* @param options Configuration options
* @param options.copiedDuration Duration in milliseconds to show the copied state
* @returns A copy callback function, or null if copying is disabled
*
* @example
* ```tsx
* function CustomCopyButton() {
* const copy = useActionBarPrimitiveCopy({ copiedDuration: 2000 });
*
* return (
* <button onClick={copy} disabled={!copy}>
* {copy ? "Copy" : "Cannot Copy"}
* </button>
* );
* }
* ```
*/
const useActionBarPrimitiveCopy = ({ copiedDuration = 3000, } = {}) => {
const api = useAssistantApi();
const hasCopyableContent = useAssistantState(({ message }) => {
return ((message.role !== "assistant" || message.status?.type !== "running") &&
message.parts.some((c) => c.type === "text" && c.text.length > 0));
});
const isEditing = useAssistantState(({ composer }) => composer.isEditing);
const composerValue = useAssistantState(({ composer }) => composer.text);
const callback = useCallback(() => {
const valueToCopy = isEditing ? composerValue : api.message().getCopyText();
if (!valueToCopy)
return;
navigator.clipboard.writeText(valueToCopy).then(() => {
api.message().setIsCopied(true);
setTimeout(() => api.message().setIsCopied(false), copiedDuration);
});
}, [api, isEditing, composerValue, copiedDuration]);
if (!hasCopyableContent)
return null;
return callback;
};
/**
* A button component that copies message content to the clipboard.
*
* This component automatically handles copying message text to the clipboard
* and provides visual feedback through the data-copied attribute. It's disabled
* when there's no copyable content available.
*
* @example
* ```tsx
* <ActionBarPrimitive.Copy copiedDuration={2000}>
* Copy Message
* </ActionBarPrimitive.Copy>
* ```
*/
export const ActionBarPrimitiveCopy = forwardRef(({ copiedDuration, onClick, disabled, ...props }, forwardedRef) => {
const isCopied = useAssistantState(({ message }) => message.isCopied);
const callback = useActionBarPrimitiveCopy({ copiedDuration });
return (_jsx(Primitive.button, { type: "button", ...(isCopied ? { "data-copied": "true" } : {}), ...props, ref: forwardedRef, disabled: disabled || !callback, onClick: composeEventHandlers(onClick, () => {
callback?.();
}) }));
});
ActionBarPrimitiveCopy.displayName = "ActionBarPrimitive.Copy";
//# sourceMappingURL=ActionBarCopy.js.map