emoji insertion support

This commit is contained in:
Red Adaya 2024-10-21 12:54:14 +08:00
parent 4c72acdd4d
commit a0d67a3c3d
2 changed files with 38 additions and 5 deletions

View File

@ -10,7 +10,7 @@ interface MultiLineInputProps {
value?: string;
className?: string;
onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
onFocus?: () => void;
onBlur?: () => void;
placeholder?: string;
@ -20,7 +20,6 @@ interface MultiLineInputProps {
disabled?: boolean;
rows?: number;
maxRows?: number;
inputRef?: React.MutableRefObject<HTMLTextAreaElement>;
manageFocus?: (isFocused: boolean) => void;
}

View File

@ -1,11 +1,12 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import { EmojiPalette } from "@/app/element/emojipalette";
import { EmojiPalette, type EmojiItem } from "@/app/element/emojipalette";
import { InputGroup } from "@/app/element/input";
import { MultiLineInput } from "@/app/element/multilineinput";
import * as keyutil from "@/util/keyutil";
import React, { useState } from "react";
import React, { useRef, useState } from "react";
import { throttle } from "throttle-debounce";
interface ChatBoxProps {
onSendMessage: (message: string) => void;
@ -13,6 +14,7 @@ interface ChatBoxProps {
const ChatBox = ({ onSendMessage }: ChatBoxProps) => {
const [message, setMessage] = useState("");
const multiLineInputRef = useRef<HTMLTextAreaElement>(null);
const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setMessage(e.target.value);
@ -27,16 +29,48 @@ const ChatBox = ({ onSendMessage }: ChatBoxProps) => {
return false;
};
const handleEmojiSelect = (emojiItem: EmojiItem) => {
if (multiLineInputRef.current) {
const { selectionStart, selectionEnd } = multiLineInputRef.current;
const currentValue = multiLineInputRef.current.value;
// Insert emoji at the current cursor position
const newValue =
currentValue.substring(0, selectionStart) + emojiItem.emoji + currentValue.substring(selectionEnd);
// Update the message state and textarea value
setMessage(newValue);
// Set the textarea value manually
multiLineInputRef.current.value = newValue;
// Move cursor after the inserted emoji
const cursorPosition = selectionStart + emojiItem.emoji.length;
// Use setTimeout to ensure the cursor positioning happens after rendering the new value
throttle(0, () => {
if (multiLineInputRef.current) {
multiLineInputRef.current.selectionStart = multiLineInputRef.current.selectionEnd = cursorPosition;
multiLineInputRef.current.focus(); // Make sure the textarea remains focused
}
})();
// Trigger onChange manually
multiLineInputRef.current.dispatchEvent(new Event("change", { bubbles: true }));
}
};
return (
<InputGroup className="chatbox">
<MultiLineInput
ref={multiLineInputRef}
className="input"
value={message}
onChange={handleInputChange}
onKeyDown={(e) => keyutil.keydownWrapper(handleKeyDown)(e)}
placeholder="Type a message..."
/>
<EmojiPalette placement="top-end" />
<EmojiPalette placement="top-end" onSelect={handleEmojiSelect} />
</InputGroup>
);
};