UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

135 lines (131 loc) 3.95 kB
import { cs } from "../utils/styles.js"; import { inputColors } from "../input/consts.js"; import { useStyleConfig } from "../core/theme.js"; import styled from "../core/styled.js"; import vui from "../core/vui.js"; import { Box } from "../box/box.js"; import { Icon } from "../icon/icon.js"; import { Button } from "../button/button.js"; import { HelpText } from "../input/helpText.js"; import { ChatInputButton } from "./chatInputButton.js"; import { useEffect, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/chat/chatInput.tsx const CustomTextarea = styled.textareaBox` border-radius: none; border-width: 0; outline: none; padding: 0 8px; resize: none; transition-duration: 0; width: 100%; min-height: 1.5em; overflow-y: hidden; &::placeholder { padding-top: 8px; } /* Disabled state styles */ &[aria-disabled='true'] { opacity: 0.5; cursor: not-allowed; background-color: sandstone.79; border-color: sandstone.79; } `; /** * Displays a chat input interface. */ const ChatInput = vui((props, ref) => { const { helpText, placeholder = "Type your message", status = "default", maxTextareaHeight = 120, processingMessage = "Generating message", onNewTopicClick, onSend, onStop, ...rest } = props; const [value, setValue] = useState(""); const styles = useStyleConfig("Chat", props); useEffect(() => { if (status === "default") setValue(""); }, [status]); const onKeyDown = (e) => { if (e.key === "Enter" && e.ctrlKey) { e.stopPropagation(); if (value?.length && status === "default") onSend?.(value); } if (e.key === "Escape") { e.stopPropagation(); if (status === "processing") onStop?.(); } }; const handleTextareaChange = (e) => { const textarea = e.target; textarea.placeholder = ""; if (textarea.scrollHeight <= maxTextareaHeight) { textarea.style.height = "auto"; textarea.style.maxHeight = "auto"; textarea.style.height = `${textarea.scrollHeight}px`; textarea.style.maxHeight = `${textarea.scrollHeight}px`; textarea.style.lineHeight = "2.2"; } if (status === "default") setValue(textarea.value); }; const isDisabled = status === "disabled"; return /* @__PURE__ */ jsxs(Box, { className: cs("vui-chat-input"), justifyContent: "space-between", ref, ...styles?.input, ...rest, children: [!!onNewTopicClick && status === "default" && /* @__PURE__ */ jsx(Button, { animation: "fadeUp", icon: "uiPlus", mr: 1, onClick: () => onNewTopicClick?.() }), status === "processing" ? /* @__PURE__ */ jsxs(Box, { borderColor: inputColors.border, borderWidth: 1, center: true, justifyContent: "flex-start", py: .5, w: "100%", children: [/* @__PURE__ */ jsx(Icon, { mx: 1, name: "uiSpinnerThird", pathFill: ["blue.40", "blue.60"], size: "lg", variant: "spinning" }), /* @__PURE__ */ jsx(Box, { children: processingMessage })] }) : /* @__PURE__ */ jsxs(Box, { animation: "fadeUp", border: "0", column: true, outline: "none", w: "100%", children: [/* @__PURE__ */ jsxs(Box, { borderColor: inputColors.border, borderWidth: 1, center: true, focusWithinRingColor: inputColors.focus, justifyContent: "flex-start", position: "relative", w: "100%", children: [/* @__PURE__ */ jsx(CustomTextarea, { disabled: isDisabled, onChange: handleTextareaChange, onFocus: handleTextareaChange, onKeyDown, placeholder, value }), /* @__PURE__ */ jsx(ChatInputButton, { disabled: !value?.length, h: "100%", onSend: () => { if (value?.length) onSend?.(value); }, onStop, status })] }), !!helpText && /* @__PURE__ */ jsx(HelpText, { children: helpText })] })] }); }); ChatInput.displayName = "ChatInput"; //#endregion export { ChatInput, ChatInput as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=chatInput.js.map