import { Feather } from "@expo/vector-icons"; import React, { useState } from "react"; import { Pressable, StyleSheet, Text, TextInput, View } from "react-native"; import { messageFitsLimit } from "../message-text"; import { colors, radii, spacing } from "../theme"; type Props = { value: string; onChangeText: (text: string) => void; onSubmit: () => void; disabled?: boolean; sending?: boolean; onAttach?: () => void; placeholder?: string; hint?: string; inputLabel?: string; maxLength?: number; }; export function ChatInputBar({ value, onChangeText, onSubmit, disabled, sending, onAttach, placeholder = "Напишите ваш вопрос...", hint = "Напишите сообщение или прикрепите документ", inputLabel = "Сообщение", maxLength, }: Props) { const [focused, setFocused] = useState(false); const withinLimit = maxLength === undefined || messageFitsLimit(value, maxLength); const canSend = Boolean(value.trim()) && withinLimit && !disabled && !sending; const nearLimit = maxLength !== undefined && value.length >= maxLength * 0.9; return ( { if (!value.trim()) setFocused(false); }} onChangeText={onChangeText} onFocus={() => setFocused(true)} onKeyPress={(event) => { if (event.nativeEvent.key !== "Enter") return; event.preventDefault(); if (canSend) onSubmit(); }} placeholder={placeholder} placeholderTextColor={colors.mutedForeground} returnKeyType="send" style={[styles.input, focused && styles.inputExpanded]} value={value} /> {onAttach && ( [styles.iconButton, pressed && styles.pressed]} > )} [ styles.sendButton, !canSend && styles.sendButtonDisabled, pressed && canSend && styles.pressed, ]} > {maxLength !== undefined ? ( {value.length}/{maxLength} ) : null} {hint ? {hint} : null} ); } const styles = StyleSheet.create({ wrapper: { paddingHorizontal: spacing.lg, paddingTop: spacing.sm, paddingBottom: spacing.lg, borderTopWidth: 1, borderTopColor: colors.border, backgroundColor: colors.background }, inputBox: { flexDirection: "row", alignItems: "flex-end", gap: spacing.sm, backgroundColor: colors.card, borderWidth: 2, borderColor: "rgba(3, 2, 19, 0.2)", borderRadius: radii.xl, padding: 10, }, inputBoxFocused: { borderColor: colors.primary }, input: { flex: 1, minHeight: 80, maxHeight: 256, fontSize: 16, color: colors.foreground, paddingVertical: spacing.sm, paddingHorizontal: spacing.sm, backgroundColor: "transparent", }, inputExpanded: { minHeight: 144 }, actions: { alignItems: "center", justifyContent: "flex-end", gap: spacing.sm }, iconButton: { width: 36, height: 36, borderRadius: radii.full, alignItems: "center", justifyContent: "center" }, sendButton: { width: 36, height: 36, borderRadius: radii.full, backgroundColor: colors.primary, alignItems: "center", justifyContent: "center" }, sendButtonDisabled: { opacity: 0.4 }, counter: { fontSize: 12, color: colors.mutedForeground, textAlign: "right", marginTop: spacing.xs }, counterWarning: { color: colors.warning }, counterError: { color: colors.destructive }, hint: { fontSize: 12, color: colors.mutedForeground, textAlign: "center", marginTop: spacing.sm }, pressed: { opacity: 0.7 }, });