-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.tsx
116 lines (101 loc) Β· 3.79 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import React, { useRef, useCallback, useState, ChangeEvent, KeyboardEvent } from 'react';
import ReactDOM from 'react-dom';
import type { EmojiObject } from '../src/index';
import { EmojiPicker, EmojiPickerRef, unifiedToNative, throttleIdleTask } from '../src/index';
import EmojiData from "../data/twemoji.json"
import './index.css';
import "../src/EmojiPicker.css"
import "../src/Emoji.css"
const copyToClipboard = async (string: string) => {
try {
// Try to use the Async Clipboard API with fallback to the legacy approach.
// @ts-ignore
const {state} = await navigator.permissions.query({name: 'clipboard-write'});
if (state !== 'granted') { throw new Error('Clipboard permission not granted'); }
await navigator.clipboard.writeText(string);
} catch {
const textArea = document.createElement('textarea');
textArea.value = string;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
}
};
function ExampleSetup() {
const picker = useRef<EmojiPickerRef>()
const input = useRef<HTMLInputElement>()
// need reference to same function to throttle
const throttledQuery = useCallback(throttleIdleTask((query: string) => picker.current?.search(query)), [picker.current]);
const inputProps = {
ref: input,
placeholder: "search-or-navigate",
onChange: (event: ChangeEvent<HTMLElement>) => throttledQuery((event.target as HTMLInputElement).value.toLowerCase()),
onKeyDown: (event: KeyboardEvent<HTMLElement>) => {
if (!["Enter", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return;
picker.current.handleKeyDownScroll(event);
if (event.key == "Enter" && !event.shiftKey) {
picker.current.search("");
input.current.value = "";
}
},
}
const onEmojiSelect = (emoji: EmojiObject) => {
const nativeEmoji = unifiedToNative(emoji.unicode);
copyToClipboard(nativeEmoji);
notification.show(`Copied ${nativeEmoji} to clipboard`);
console.log(emoji);
}
const emojiPickerProps = {
ref: picker,
emojiData: EmojiData,
onEmojiSelect,
showNavbar: true,
showFooter: true,
collapseHeightOnSearch: false,
}
/**
* Adaptation of show-and-hide popup from https://rsms.me/inter/#charset for React hooks.
* Ignore this if you're just using this website as an example of how to setup the emoji picker.
*/
const [notification] = useState(() => {
let timer = null
let visible = false
const show = (message) => {
const el = document.querySelector('#notification') as HTMLDivElement;
(el.firstChild as HTMLElement).innerText = message
el.classList.add('visible')
if (visible) {
hide()
setTimeout(() => show(message), 120)
return
}
visible = true
el.style.visibility = null
clearTimeout(timer)
timer = setTimeout(() => hide(), 1200)
}
const hide = () => {
const el = document.querySelector('#notification') as HTMLDivElement;
if (visible) {
el.classList.remove('visible')
visible = false
el.style.visibility = 'hidden'
}
}
return { show }
})
return (
<div style={{'display': 'flex', 'flexDirection': 'column', 'minHeight': '100vh', 'justifyContent': 'center', 'alignItems': 'center'}}>
<h1>Emoji Picker</h1>
<p>A virtualized <a href="https://twemoji.twitter.com/">twemoji</a> picker written in React and TypeScript.</p>
<EmojiPicker {...emojiPickerProps}/>
<input {...inputProps}/>
<a href="https://github.com/BrianHung/EmojiPicker">source code β</a>
<div id="notification">
<div></div>
</div>
</div>
)
}
ReactDOM.render(<ExampleSetup/>, document.getElementById('example-setup'));