react-mention-input 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/MentionInput.css +9 -0
- package/dist/MentionInput.d.ts +5 -1
- package/dist/MentionInput.js +50 -43
- package/dist/ShowMessageCard.css +6 -0
- package/dist/ShowMessageCard.js +1 -1
- package/package.json +1 -1
- package/src/MentionInput.css +9 -0
- package/src/MentionInput.tsx +70 -50
- package/src/ShowMessageCard.css +6 -0
- package/src/ShowMessageCard.tsx +7 -3
package/README.md
CHANGED
|
@@ -37,7 +37,8 @@ A customizable input component with @mention functionality.
|
|
|
37
37
|
| `suggestionListClassName` | `string` | Custom class name for the suggestion list. |
|
|
38
38
|
| `suggestionItemClassName` | `string` | Custom class name for each suggestion item. |
|
|
39
39
|
| `sendButtonIcon` | `ReactNode` | Custom icon for the send button (MUI icon or image path). |
|
|
40
|
-
| `onSendMessage` | `(
|
|
40
|
+
| `onSendMessage` | `(obj: {messageText: string, messageHTML: string}) => void` | Callback function triggered on sending a message, providing both plain text and HTML. |
|
|
41
|
+
| `suggestionPosition` | `'top' | 'bottom' | 'left' | 'right'` | Position of the suggestion dropdown relative to the input. Default is `bottom`. |
|
|
41
42
|
|
|
42
43
|
#### Example Usage
|
|
43
44
|
|
|
@@ -51,8 +52,9 @@ const users = [
|
|
|
51
52
|
];
|
|
52
53
|
|
|
53
54
|
function App() {
|
|
54
|
-
const handleSendMessage = (
|
|
55
|
-
console.log('Message
|
|
55
|
+
const handleSendMessage = ({messageText, messageHTML}) => {
|
|
56
|
+
console.log('Message Text:', messageText);
|
|
57
|
+
console.log('Message HTML:', messageHTML);
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
return (
|
|
@@ -61,6 +63,7 @@ function App() {
|
|
|
61
63
|
placeholder="Type @ to mention someone..."
|
|
62
64
|
sendButtonIcon={<SendIcon />} // Optional MUI icon or image path
|
|
63
65
|
onSendMessage={handleSendMessage}
|
|
66
|
+
suggestionPosition="top" // Customize suggestion position (top, bottom, left, right)
|
|
64
67
|
/>
|
|
65
68
|
);
|
|
66
69
|
}
|
package/dist/MentionInput.css
CHANGED
package/dist/MentionInput.d.ts
CHANGED
|
@@ -14,7 +14,11 @@ interface MentionInputProps {
|
|
|
14
14
|
suggestionListClassName?: string;
|
|
15
15
|
suggestionItemClassName?: string;
|
|
16
16
|
sendButtonIcon?: ReactNode;
|
|
17
|
-
onSendMessage?: (
|
|
17
|
+
onSendMessage?: (obj: {
|
|
18
|
+
messageText: string;
|
|
19
|
+
messageHTML: string;
|
|
20
|
+
}) => void;
|
|
21
|
+
suggestionPosition?: 'top' | 'bottom' | 'left' | 'right';
|
|
18
22
|
}
|
|
19
23
|
declare const MentionInput: React.FC<MentionInputProps>;
|
|
20
24
|
export default MentionInput;
|
package/dist/MentionInput.js
CHANGED
|
@@ -2,17 +2,23 @@ import React, { useState, useRef } from "react";
|
|
|
2
2
|
import ReactDOM from "react-dom";
|
|
3
3
|
import "./MentionInput.css";
|
|
4
4
|
var MentionInput = function (_a) {
|
|
5
|
-
var users = _a.users, _b = _a.placeholder, placeholder = _b === void 0 ? "Type a message..." : _b, containerClassName = _a.containerClassName, inputContainerClassName = _a.inputContainerClassName, inputClassName = _a.inputClassName, sendBtnClassName = _a.sendBtnClassName, suggestionListClassName = _a.suggestionListClassName, suggestionItemClassName = _a.suggestionItemClassName, sendButtonIcon = _a.sendButtonIcon, onSendMessage = _a.onSendMessage;
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var _f = useState('bottom'), tooltipPosition = _f[0], setTooltipPosition = _f[1];
|
|
5
|
+
var users = _a.users, _b = _a.placeholder, placeholder = _b === void 0 ? "Type a message..." : _b, containerClassName = _a.containerClassName, inputContainerClassName = _a.inputContainerClassName, inputClassName = _a.inputClassName, sendBtnClassName = _a.sendBtnClassName, suggestionListClassName = _a.suggestionListClassName, suggestionItemClassName = _a.suggestionItemClassName, sendButtonIcon = _a.sendButtonIcon, onSendMessage = _a.onSendMessage, _c = _a.suggestionPosition, suggestionPosition = _c === void 0 ? 'bottom' : _c;
|
|
6
|
+
var _d = useState(""), inputValue = _d[0], setInputValue = _d[1]; // Plain text
|
|
7
|
+
var _e = useState([]), suggestions = _e[0], setSuggestions = _e[1];
|
|
8
|
+
var _f = useState(false), showSuggestions = _f[0], setShowSuggestions = _f[1];
|
|
10
9
|
var inputRef = useRef(null);
|
|
11
10
|
var suggestionListRef = useRef(null);
|
|
12
11
|
var caretOffsetRef = useRef(0);
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
var highlightMentionsAndLinks = function (text) {
|
|
13
|
+
// Regular expression for detecting links
|
|
14
|
+
var linkRegex = /(https?:\/\/[^\s]+)/g;
|
|
15
|
+
// Regular expression for mentions
|
|
16
|
+
var mentionRegex = /@([^\s]+(?: [^\s]+)?)(?=\s|$)/g;
|
|
17
|
+
// First, highlight mentions
|
|
18
|
+
var highlightedText = text.replace(mentionRegex, '<span class="mention-highlight">@$1</span>');
|
|
19
|
+
// Then, highlight links
|
|
20
|
+
highlightedText = highlightedText.replace(linkRegex, '<a href="$1" target="_blank" rel="noopener noreferrer" class="link-highlight">$1</a>');
|
|
21
|
+
return highlightedText;
|
|
16
22
|
};
|
|
17
23
|
var restoreCaretPosition = function (node, caretOffset) {
|
|
18
24
|
var range = document.createRange();
|
|
@@ -56,12 +62,11 @@ var MentionInput = function (_a) {
|
|
|
56
62
|
var preCaretRange = range.cloneRange();
|
|
57
63
|
preCaretRange.selectNodeContents(inputRef.current);
|
|
58
64
|
preCaretRange.setEnd(range.startContainer, range.startOffset);
|
|
59
|
-
newCaretOffset = preCaretRange.toString().length;
|
|
65
|
+
newCaretOffset = preCaretRange.toString().length;
|
|
60
66
|
}
|
|
61
|
-
caretOffsetRef.current = newCaretOffset;
|
|
67
|
+
caretOffsetRef.current = newCaretOffset;
|
|
62
68
|
var plainText = inputRef.current.innerText;
|
|
63
69
|
setInputValue(plainText);
|
|
64
|
-
// Handle mentions and suggestions
|
|
65
70
|
var mentionMatch = plainText.slice(0, newCaretOffset).match(/@(\S*)$/);
|
|
66
71
|
if (mentionMatch) {
|
|
67
72
|
var query_1 = mentionMatch[1].toLowerCase();
|
|
@@ -73,49 +78,22 @@ var MentionInput = function (_a) {
|
|
|
73
78
|
setShowSuggestions(false);
|
|
74
79
|
}
|
|
75
80
|
var previousHTML = inputRef.current.innerHTML;
|
|
76
|
-
var htmlWithHighlights =
|
|
81
|
+
var htmlWithHighlights = highlightMentionsAndLinks(plainText); // Updated function
|
|
77
82
|
if (previousHTML !== htmlWithHighlights) {
|
|
78
83
|
inputRef.current.innerHTML = htmlWithHighlights;
|
|
79
84
|
}
|
|
80
85
|
restoreCaretPosition(inputRef.current, newCaretOffset);
|
|
81
86
|
};
|
|
82
|
-
var handleSuggestionClick = function (user) {
|
|
83
|
-
if (!inputRef.current)
|
|
84
|
-
return;
|
|
85
|
-
var plainText = inputValue; // Current input value
|
|
86
|
-
var caretOffset = caretOffsetRef.current; // Use ref value for caret offset
|
|
87
|
-
var mentionMatch = plainText.slice(0, caretOffset).match(/@(\S*)$/);
|
|
88
|
-
if (!mentionMatch)
|
|
89
|
-
return;
|
|
90
|
-
var mentionIndex = plainText.slice(0, caretOffset).lastIndexOf("@");
|
|
91
|
-
var newValue = plainText.substring(0, mentionIndex + 1) + user.name + plainText.substring(caretOffset);
|
|
92
|
-
setInputValue(newValue);
|
|
93
|
-
inputRef.current.innerText = newValue;
|
|
94
|
-
var htmlWithHighlights = highlightMentions(newValue);
|
|
95
|
-
inputRef.current.innerHTML = htmlWithHighlights;
|
|
96
|
-
setShowSuggestions(false);
|
|
97
|
-
var mentionEnd = mentionIndex + user.name.length + 1;
|
|
98
|
-
restoreCaretPosition(inputRef.current, mentionEnd);
|
|
99
|
-
};
|
|
100
|
-
var handleSendMessage = function () {
|
|
101
|
-
if (inputValue.trim() && onSendMessage) {
|
|
102
|
-
onSendMessage(inputValue.trim());
|
|
103
|
-
setInputValue("");
|
|
104
|
-
setShowSuggestions(false);
|
|
105
|
-
if (inputRef.current)
|
|
106
|
-
inputRef.current.innerText = "";
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
87
|
var renderSuggestions = function () {
|
|
110
88
|
if (!showSuggestions || !inputRef.current)
|
|
111
89
|
return null;
|
|
112
90
|
var inputRect = inputRef.current.getBoundingClientRect();
|
|
113
91
|
var styles = {
|
|
114
92
|
position: 'absolute',
|
|
115
|
-
zIndex: 1000
|
|
93
|
+
zIndex: 1000,
|
|
116
94
|
};
|
|
117
|
-
//
|
|
118
|
-
switch (
|
|
95
|
+
// Use suggestionPosition prop to adjust tooltip position
|
|
96
|
+
switch (suggestionPosition) {
|
|
119
97
|
case 'top':
|
|
120
98
|
styles.left = "".concat(inputRect.left, "px");
|
|
121
99
|
styles.top = "".concat(inputRect.top - 150, "px");
|
|
@@ -135,10 +113,39 @@ var MentionInput = function (_a) {
|
|
|
135
113
|
default:
|
|
136
114
|
break;
|
|
137
115
|
}
|
|
138
|
-
console.log("document.body", document.body);
|
|
139
116
|
return ReactDOM.createPortal(React.createElement("ul", { className: "suggestion-list ".concat(suggestionListClassName || ''), ref: suggestionListRef, style: styles }, suggestions.map(function (user) { return (React.createElement("li", { key: user.id, onClick: function () { return handleSuggestionClick(user); }, className: "suggestion-item ".concat(suggestionItemClassName || ''), role: "option", tabIndex: 0, "aria-selected": "false" }, user.name)); })), window.document.body // Render in portal
|
|
140
117
|
);
|
|
141
118
|
};
|
|
119
|
+
var handleSuggestionClick = function (user) {
|
|
120
|
+
if (!inputRef.current)
|
|
121
|
+
return;
|
|
122
|
+
var plainText = inputValue;
|
|
123
|
+
var caretOffset = caretOffsetRef.current;
|
|
124
|
+
var mentionMatch = plainText.slice(0, caretOffset).match(/@(\S*)$/);
|
|
125
|
+
if (!mentionMatch)
|
|
126
|
+
return;
|
|
127
|
+
var mentionIndex = plainText.slice(0, caretOffset).lastIndexOf("@");
|
|
128
|
+
var newValue = plainText.substring(0, mentionIndex + 1) + user.name + plainText.substring(caretOffset);
|
|
129
|
+
setInputValue(newValue);
|
|
130
|
+
inputRef.current.innerText = newValue;
|
|
131
|
+
var htmlWithHighlights = highlightMentionsAndLinks(newValue);
|
|
132
|
+
inputRef.current.innerHTML = htmlWithHighlights;
|
|
133
|
+
setShowSuggestions(false);
|
|
134
|
+
var mentionEnd = mentionIndex + user.name.length + 1;
|
|
135
|
+
restoreCaretPosition(inputRef.current, mentionEnd);
|
|
136
|
+
};
|
|
137
|
+
var handleSendMessage = function () {
|
|
138
|
+
if (inputRef.current) {
|
|
139
|
+
var messageText = inputRef.current.innerText.trim(); // Plain text
|
|
140
|
+
var messageHTML = inputRef.current.innerHTML.trim(); // HTML with <span> highlighting
|
|
141
|
+
if (messageText && onSendMessage) {
|
|
142
|
+
onSendMessage({ messageText: messageText, messageHTML: messageHTML }); // Pass both plain text and HTML
|
|
143
|
+
setInputValue(""); // Clear state
|
|
144
|
+
setShowSuggestions(false); // Hide suggestions
|
|
145
|
+
inputRef.current.innerText = ""; // Clear input field
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
142
149
|
return (React.createElement("div", { className: "mention-container ".concat(containerClassName || "") },
|
|
143
150
|
React.createElement("div", { className: "mention-input-container ".concat(inputContainerClassName || "") },
|
|
144
151
|
React.createElement("div", { ref: inputRef, contentEditable: true, suppressContentEditableWarning: true, className: "mention-input ".concat(inputClassName || ""), onInput: handleInputChange }),
|
package/dist/ShowMessageCard.css
CHANGED
package/dist/ShowMessageCard.js
CHANGED
|
@@ -44,6 +44,6 @@ export var ShowMessageCard = function (_a) {
|
|
|
44
44
|
React.createElement("h3", { className: "message-card-name ".concat(nameClassName || ""), style: nameStyle }, item[nameKey]),
|
|
45
45
|
React.createElement("p", { className: "message-card-date ".concat(dateClassName || ""), style: dateStyle }, item[dateKey]))),
|
|
46
46
|
React.createElement("div", { className: "message-card-body ".concat(bodyClassName || ""), style: bodyStyle },
|
|
47
|
-
React.createElement("p", { className: "message-card-comment ".concat(commentClassName || ""), style: commentStyle
|
|
47
|
+
React.createElement("p", { className: "message-card-comment ".concat(commentClassName || ""), style: commentStyle, dangerouslySetInnerHTML: { __html: item[commentKey] } }))));
|
|
48
48
|
})));
|
|
49
49
|
};
|
package/package.json
CHANGED
package/src/MentionInput.css
CHANGED
package/src/MentionInput.tsx
CHANGED
|
@@ -16,8 +16,9 @@ interface MentionInputProps {
|
|
|
16
16
|
sendBtnClassName?: string;
|
|
17
17
|
suggestionListClassName?: string;
|
|
18
18
|
suggestionItemClassName?: string;
|
|
19
|
-
sendButtonIcon?: ReactNode; //
|
|
20
|
-
onSendMessage?: (
|
|
19
|
+
sendButtonIcon?: ReactNode; // Button icon (MUI icon or image path)
|
|
20
|
+
onSendMessage?: (obj:{messageText: string, messageHTML: string}) => void;
|
|
21
|
+
suggestionPosition?: 'top' | 'bottom' | 'left' | 'right'; // New prop for tooltip position
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const MentionInput: React.FC<MentionInputProps> = ({
|
|
@@ -31,24 +32,36 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
31
32
|
suggestionItemClassName,
|
|
32
33
|
sendButtonIcon,
|
|
33
34
|
onSendMessage,
|
|
35
|
+
suggestionPosition = 'bottom', // Default position is bottom
|
|
34
36
|
}) => {
|
|
35
37
|
const [inputValue, setInputValue] = useState<string>(""); // Plain text
|
|
36
38
|
const [suggestions, setSuggestions] = useState<User[]>([]);
|
|
37
39
|
const [showSuggestions, setShowSuggestions] = useState<boolean>(false);
|
|
38
|
-
const [tooltipPosition, setTooltipPosition] = useState<'top' | 'bottom' | 'left' | 'right'>(
|
|
39
|
-
'bottom'
|
|
40
|
-
);
|
|
41
40
|
|
|
42
41
|
const inputRef = useRef<HTMLDivElement>(null);
|
|
43
42
|
const suggestionListRef = useRef<HTMLUListElement>(null);
|
|
44
43
|
const caretOffsetRef = useRef<number>(0);
|
|
45
|
-
|
|
46
44
|
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const highlightMentionsAndLinks = (text: string): string => {
|
|
46
|
+
// Regular expression for detecting links
|
|
47
|
+
const linkRegex = /(https?:\/\/[^\s]+)/g;
|
|
48
|
+
|
|
49
|
+
// Regular expression for mentions
|
|
50
|
+
const mentionRegex = /@([^\s]+(?: [^\s]+)?)(?=\s|$)/g;
|
|
51
|
+
|
|
52
|
+
// First, highlight mentions
|
|
53
|
+
let highlightedText = text.replace(
|
|
54
|
+
mentionRegex,
|
|
50
55
|
'<span class="mention-highlight">@$1</span>'
|
|
51
56
|
);
|
|
57
|
+
|
|
58
|
+
// Then, highlight links
|
|
59
|
+
highlightedText = highlightedText.replace(
|
|
60
|
+
linkRegex,
|
|
61
|
+
'<a href="$1" target="_blank" rel="noopener noreferrer" class="link-highlight">$1</a>'
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return highlightedText;
|
|
52
65
|
};
|
|
53
66
|
|
|
54
67
|
const restoreCaretPosition = (node: HTMLElement, caretOffset: number) => {
|
|
@@ -93,15 +106,14 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
93
106
|
const preCaretRange = range.cloneRange();
|
|
94
107
|
preCaretRange.selectNodeContents(inputRef.current);
|
|
95
108
|
preCaretRange.setEnd(range.startContainer, range.startOffset);
|
|
96
|
-
newCaretOffset = preCaretRange.toString().length;
|
|
109
|
+
newCaretOffset = preCaretRange.toString().length;
|
|
97
110
|
}
|
|
98
111
|
|
|
99
|
-
caretOffsetRef.current = newCaretOffset;
|
|
112
|
+
caretOffsetRef.current = newCaretOffset;
|
|
100
113
|
|
|
101
114
|
const plainText = inputRef.current.innerText;
|
|
102
115
|
setInputValue(plainText);
|
|
103
116
|
|
|
104
|
-
// Handle mentions and suggestions
|
|
105
117
|
const mentionMatch = plainText.slice(0, newCaretOffset).match(/@(\S*)$/);
|
|
106
118
|
if (mentionMatch) {
|
|
107
119
|
const query = mentionMatch[1].toLowerCase();
|
|
@@ -114,47 +126,14 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
114
126
|
}
|
|
115
127
|
|
|
116
128
|
const previousHTML = inputRef.current.innerHTML;
|
|
117
|
-
const htmlWithHighlights =
|
|
129
|
+
const htmlWithHighlights = highlightMentionsAndLinks(plainText); // Updated function
|
|
118
130
|
if (previousHTML !== htmlWithHighlights) {
|
|
119
131
|
inputRef.current.innerHTML = htmlWithHighlights;
|
|
120
132
|
}
|
|
121
133
|
|
|
122
134
|
restoreCaretPosition(inputRef.current, newCaretOffset);
|
|
123
135
|
};
|
|
124
|
-
|
|
125
|
-
const handleSuggestionClick = (user: User) => {
|
|
126
|
-
if (!inputRef.current) return;
|
|
127
|
-
|
|
128
|
-
const plainText = inputValue; // Current input value
|
|
129
|
-
const caretOffset = caretOffsetRef.current; // Use ref value for caret offset
|
|
130
|
-
const mentionMatch = plainText.slice(0, caretOffset).match(/@(\S*)$/);
|
|
131
|
-
|
|
132
|
-
if (!mentionMatch) return;
|
|
133
|
-
|
|
134
|
-
const mentionIndex = plainText.slice(0, caretOffset).lastIndexOf("@");
|
|
135
136
|
|
|
136
|
-
const newValue =
|
|
137
|
-
plainText.substring(0, mentionIndex + 1) + user.name + plainText.substring(caretOffset);
|
|
138
|
-
|
|
139
|
-
setInputValue(newValue);
|
|
140
|
-
inputRef.current.innerText = newValue;
|
|
141
|
-
|
|
142
|
-
const htmlWithHighlights = highlightMentions(newValue);
|
|
143
|
-
inputRef.current.innerHTML = htmlWithHighlights;
|
|
144
|
-
|
|
145
|
-
setShowSuggestions(false);
|
|
146
|
-
|
|
147
|
-
const mentionEnd = mentionIndex + user.name.length + 1;
|
|
148
|
-
restoreCaretPosition(inputRef.current, mentionEnd);
|
|
149
|
-
};
|
|
150
|
-
const handleSendMessage = () => {
|
|
151
|
-
if (inputValue.trim() && onSendMessage) {
|
|
152
|
-
onSendMessage(inputValue.trim());
|
|
153
|
-
setInputValue("");
|
|
154
|
-
setShowSuggestions(false);
|
|
155
|
-
if (inputRef.current) inputRef.current.innerText = "";
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
137
|
|
|
159
138
|
const renderSuggestions = () => {
|
|
160
139
|
if (!showSuggestions || !inputRef.current) return null;
|
|
@@ -162,11 +141,11 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
162
141
|
const inputRect = inputRef.current.getBoundingClientRect();
|
|
163
142
|
const styles: React.CSSProperties = {
|
|
164
143
|
position: 'absolute',
|
|
165
|
-
zIndex: 1000
|
|
144
|
+
zIndex: 1000,
|
|
166
145
|
};
|
|
167
146
|
|
|
168
|
-
//
|
|
169
|
-
switch (
|
|
147
|
+
// Use suggestionPosition prop to adjust tooltip position
|
|
148
|
+
switch (suggestionPosition) {
|
|
170
149
|
case 'top':
|
|
171
150
|
styles.left = `${inputRect.left}px`;
|
|
172
151
|
styles.top = `${inputRect.top - 150}px`;
|
|
@@ -187,7 +166,6 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
187
166
|
break;
|
|
188
167
|
}
|
|
189
168
|
|
|
190
|
-
console.log("document.body",document.body);
|
|
191
169
|
return ReactDOM.createPortal(
|
|
192
170
|
<ul
|
|
193
171
|
className={`suggestion-list ${suggestionListClassName || ''}`}
|
|
@@ -211,6 +189,48 @@ const MentionInput: React.FC<MentionInputProps> = ({
|
|
|
211
189
|
);
|
|
212
190
|
};
|
|
213
191
|
|
|
192
|
+
const handleSuggestionClick = (user: User) => {
|
|
193
|
+
if (!inputRef.current) return;
|
|
194
|
+
|
|
195
|
+
const plainText = inputValue;
|
|
196
|
+
const caretOffset = caretOffsetRef.current;
|
|
197
|
+
const mentionMatch = plainText.slice(0, caretOffset).match(/@(\S*)$/);
|
|
198
|
+
|
|
199
|
+
if (!mentionMatch) return;
|
|
200
|
+
|
|
201
|
+
const mentionIndex = plainText.slice(0, caretOffset).lastIndexOf("@");
|
|
202
|
+
|
|
203
|
+
const newValue =
|
|
204
|
+
plainText.substring(0, mentionIndex + 1) + user.name + plainText.substring(caretOffset);
|
|
205
|
+
|
|
206
|
+
setInputValue(newValue);
|
|
207
|
+
inputRef.current.innerText = newValue;
|
|
208
|
+
|
|
209
|
+
const htmlWithHighlights = highlightMentionsAndLinks(newValue);
|
|
210
|
+
inputRef.current.innerHTML = htmlWithHighlights;
|
|
211
|
+
|
|
212
|
+
setShowSuggestions(false);
|
|
213
|
+
|
|
214
|
+
const mentionEnd = mentionIndex + user.name.length + 1;
|
|
215
|
+
restoreCaretPosition(inputRef.current, mentionEnd);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const handleSendMessage = () => {
|
|
219
|
+
if (inputRef.current) {
|
|
220
|
+
const messageText = inputRef.current.innerText.trim(); // Plain text
|
|
221
|
+
const messageHTML = inputRef.current.innerHTML.trim(); // HTML with <span> highlighting
|
|
222
|
+
|
|
223
|
+
if (messageText && onSendMessage) {
|
|
224
|
+
onSendMessage({messageText, messageHTML}); // Pass both plain text and HTML
|
|
225
|
+
setInputValue(""); // Clear state
|
|
226
|
+
setShowSuggestions(false); // Hide suggestions
|
|
227
|
+
inputRef.current.innerText = ""; // Clear input field
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
214
234
|
return (
|
|
215
235
|
<div className={`mention-container ${containerClassName || ""}`}>
|
|
216
236
|
<div className={`mention-input-container ${inputContainerClassName || ""}`}>
|
package/src/ShowMessageCard.css
CHANGED
package/src/ShowMessageCard.tsx
CHANGED
|
@@ -146,12 +146,17 @@ export const ShowMessageCard: React.FC<ShowMessageCardProps> = ({
|
|
|
146
146
|
className={`message-card-body ${bodyClassName || ""}`}
|
|
147
147
|
style={bodyStyle}
|
|
148
148
|
>
|
|
149
|
-
<p
|
|
149
|
+
{/* <p
|
|
150
150
|
className={`message-card-comment ${commentClassName || ""}`}
|
|
151
151
|
style={commentStyle}
|
|
152
152
|
>
|
|
153
153
|
{item[commentKey]}
|
|
154
|
-
</p>
|
|
154
|
+
</p> */}
|
|
155
|
+
<p
|
|
156
|
+
className={`message-card-comment ${commentClassName || ""}`}
|
|
157
|
+
style={commentStyle}
|
|
158
|
+
dangerouslySetInnerHTML={{ __html: item[commentKey] }}
|
|
159
|
+
></p>
|
|
155
160
|
</div>
|
|
156
161
|
</div>
|
|
157
162
|
);
|
|
@@ -160,4 +165,3 @@ export const ShowMessageCard: React.FC<ShowMessageCardProps> = ({
|
|
|
160
165
|
);
|
|
161
166
|
};
|
|
162
167
|
|
|
163
|
-
|