@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
JavaScript
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