1
+ import { useEffect , useState , useRef } from "react" ;
1
2
import FormInputs from "../FormInputs/FormInputs" ;
2
3
import useForm from "../../hooks/useForm" ;
4
+ import "emoji-mart/css/emoji-mart.css" ;
5
+ import { Picker , Emoji , emojiIndex } from "emoji-mart" ;
3
6
import styles from "./ChatInput.module.css" ;
4
7
import { messageInputs } from "../../data/messageInputs" ;
8
+ import { emojiTrayMap } from "../../data/emojiTrayMap" ;
5
9
6
10
const ChatInput = ( ) => {
7
- const { values, handleChange, clearInput} = useForm ( { message : "" } ) ;
11
+ const { values, handleChange, handleAdd, clearInput} = useForm ( { message : "" } ) ;
12
+ const [ showEmojis , setShowEmojis ] = useState ( false ) ;
13
+ const [ trayEmoji , setTrayEmoji ] = useState ( "blush" ) ;
14
+ const hasConvertedRef = useRef ( false ) ;
15
+ const nodeRef = useRef ( null ) ;
8
16
9
17
const formInputs = messageInputs . map ( input => {
10
18
return {
@@ -13,12 +21,118 @@ const ChatInput = () => {
13
21
}
14
22
} ) ;
15
23
24
+ useEffect ( ( ) => {
25
+ if ( ! hasConvertedRef . current ) {
26
+ convertInputToEmoji ( values . message ) ;
27
+ }
28
+ else {
29
+ hasConvertedRef . current = false ;
30
+ }
31
+ } , [ values ] ) ;
32
+
33
+ useEffect ( ( ) => {
34
+ if ( showEmojis ) {
35
+ window . addEventListener ( "mousedown" , handleClickOutside ) ;
36
+ }
37
+ else {
38
+ window . removeEventListener ( "mousedown" , handleClickOutside ) ;
39
+ }
40
+
41
+ return ( ) => {
42
+ window . removeEventListener ( "mousedown" , handleClickOutside ) ;
43
+ }
44
+ } , [ showEmojis ] ) ;
45
+
46
+ const handleClickOutside = ( e ) => {
47
+ if ( nodeRef . current . contains ( e . target ) ) return ;
48
+
49
+ setShowEmojis ( false ) ;
50
+ } ;
51
+
52
+ const handleClick = ( ) => {
53
+ setShowEmojis ( ! showEmojis ) ;
54
+ } ;
55
+
56
+ const handleEmojiHover = ( ) => {
57
+ let newEmoji = emojiTrayMap [ Math . floor ( Math . random ( ) * emojiTrayMap . length ) ] ;
58
+ while ( newEmoji === trayEmoji ) {
59
+ newEmoji = emojiTrayMap [ Math . floor ( Math . random ( ) * emojiTrayMap . length ) ] ;
60
+ }
61
+ setTrayEmoji ( newEmoji ) ;
62
+ } ;
63
+
64
+ const handleEmoji = ( e ) => {
65
+ const pseudoTarget = { target : { value : e . native , name : "message" } } ;
66
+ handleAdd ( pseudoTarget ) ;
67
+ } ;
68
+
69
+ const convertInputToEmoji = ( userText ) => {
70
+ if ( ! userText . length ) return ;
71
+ const textArray = userText . split ( " " ) ;
72
+ let newValues = [ ] ;
73
+
74
+ for ( let value of textArray ) {
75
+ if ( value [ 0 ] !== ":" ) {
76
+ newValues . push ( value ) ;
77
+ continue ;
78
+ }
79
+
80
+ let emojiArray = [ ] ;
81
+ let isEmojiCode = value [ value . length - 1 ] === ":" && value . length > 1 ;
82
+
83
+ if ( isEmojiCode ) value = value . replaceAll ( ":" , "" ) ;
84
+
85
+ emojiArray = emojiIndex . search ( value ) . filter ( emoji => {
86
+ if ( ! isEmojiCode && emoji . emoticons . length ) {
87
+ for ( let emoticon of emoji . emoticons ) {
88
+ if ( emoticon === value ) return emoji . native ;
89
+ }
90
+ }
91
+ if ( value === emoji . id ) return emoji . native ;
92
+ return false
93
+ } ) ;
94
+
95
+ if ( emojiArray . length ) newValues . push ( emojiArray [ 0 ] . native ) ;
96
+ else {
97
+ newValues . push ( value ) ;
98
+ }
99
+ }
100
+
101
+ let newText = newValues . join ( " " ) ;
102
+ if ( newText !== userText ) {
103
+ const pseudoTarget = { target : { value : newText , name : "message" } } ;
104
+ hasConvertedRef . current = true ;
105
+ handleChange ( pseudoTarget ) ;
106
+ }
107
+ } ;
108
+
16
109
return (
17
110
< div className = { styles . container } >
18
111
< div className = { styles . input__container } >
19
112
< FormInputs inputs = { formInputs } handleChange = { handleChange } clearInput = { clearInput } />
20
113
</ div >
21
114
< div className = { styles . controls__container } >
115
+ < div ref = { nodeRef } className = { styles . emoji__container } >
116
+ < button
117
+ type = "button"
118
+ title = { "Pick your emoji..." }
119
+ className = { styles . emoji__button }
120
+ onClick = { handleClick }
121
+ onMouseOver = { handleEmojiHover }
122
+ >
123
+ < Emoji emoji = { trayEmoji } size = { 18 } native = { true } />
124
+ </ button >
125
+ { showEmojis &&
126
+ < div className = { styles . emoji__mart } >
127
+ < Picker
128
+ title = { "Pick your emoji..." }
129
+ onSelect = { handleEmoji }
130
+ emoji = { "wave" }
131
+ native = { true }
132
+ />
133
+ </ div >
134
+ }
135
+ </ div >
22
136
< button type = "button" className = { styles . send__button } > < i className = "fas fa-play" > </ i > </ button >
23
137
</ div >
24
138
</ div >
0 commit comments