🏬 Emoji Mart™

exclude-unsupported-native-emojis
Etienne Lemay 2016-07-27 11:35:12 -04:00
parent 760d140410
commit 9648c7d8e2
14 changed files with 106 additions and 107 deletions

View File

@ -1,7 +1,7 @@
<h1 align="center">⛏ EmojiPicker ⛏</h1> <h1 align="center">🏬 Emoji Mart</h1>
```jsx ```jsx
import {Picker} from 'emoji-picker' import {Picker} from 'emoji-mart'
<Picker <Picker
emojiSize={24} emojiSize={24}

View File

@ -1,9 +1,9 @@
.emoji-picker, .emoji-mart,
.emoji-picker * { .emoji-mart * {
box-sizing: border-box; box-sizing: border-box;
} }
.emoji-picker { .emoji-mart {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
font-size: 16px; font-size: 16px;
display: inline-block; display: inline-block;
@ -13,27 +13,27 @@
background: #fff; background: #fff;
} }
.emoji-picker .emoji-picker-emoji { .emoji-mart .emoji-mart-emoji {
padding: 6px; padding: 6px;
} }
.emoji-picker-bar:first-child { .emoji-mart-bar:first-child {
border-top-left-radius: 5px; border-top-left-radius: 5px;
border-top-right-radius: 5px; border-top-right-radius: 5px;
} }
.emoji-picker-bar:last-child { .emoji-mart-bar:last-child {
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
} }
.emoji-picker-anchors { .emoji-mart-anchors {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 0 6px; padding: 0 6px;
color: #858585; color: #858585;
} }
.emoji-picker-anchor { .emoji-mart-anchor {
position: relative; position: relative;
flex: 1; flex: 1;
text-align: center; text-align: center;
@ -41,33 +41,33 @@
overflow: hidden; overflow: hidden;
transition: color .1s ease-out; transition: color .1s ease-out;
} }
.emoji-picker-anchor:hover, .emoji-mart-anchor:hover,
.emoji-picker-anchor-selected { .emoji-mart-anchor-selected {
color: #464646; color: #464646;
} }
.emoji-picker-anchor-selected .emoji-picker-anchor-bar { .emoji-mart-anchor-selected .emoji-mart-anchor-bar {
bottom: 0; bottom: 0;
} }
.emoji-picker-anchor-bar { .emoji-mart-anchor-bar {
position: absolute; position: absolute;
bottom: -3px; left: 0; bottom: -3px; left: 0;
width: 100%; height: 3px; width: 100%; height: 3px;
background-color: #464646; background-color: #464646;
} }
.emoji-picker-anchors i { .emoji-mart-anchors i {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
max-width: 22px; max-width: 22px;
} }
.emoji-picker-anchors svg { .emoji-mart-anchors svg {
fill: currentColor; fill: currentColor;
} }
.emoji-picker-scroll { .emoji-mart-scroll {
overflow: scroll; overflow: scroll;
height: 270px; height: 270px;
padding: 0 6px 6px 6px; padding: 0 6px 6px 6px;
@ -75,7 +75,7 @@
border-width: 1px 0; border-width: 1px 0;
} }
.emoji-picker-search { .emoji-mart-search {
font-size: 16px; font-size: 16px;
display: block; display: block;
width: 100%; width: 100%;
@ -86,12 +86,12 @@
outline: 0; outline: 0;
} }
.emoji-picker-category .emoji-picker-emoji span { .emoji-mart-category .emoji-mart-emoji span {
z-index: 1; z-index: 1;
position: relative; position: relative;
} }
.emoji-picker-category .emoji-picker-emoji:hover:before { .emoji-mart-category .emoji-mart-emoji:hover:before {
z-index: 0; z-index: 0;
content: ""; content: "";
position: absolute; position: absolute;
@ -101,14 +101,14 @@
border-radius: 100%; border-radius: 100%;
} }
.emoji-picker-category-label { .emoji-mart-category-label {
z-index: 2; z-index: 2;
position: relative; position: relative;
position: -webkit-sticky; position: -webkit-sticky;
top: 0; top: 0;
} }
.emoji-picker-category-label span { .emoji-mart-category-label span {
display: block; display: block;
width: 100%; width: 100%;
font-weight: 500; font-weight: 500;
@ -117,84 +117,85 @@
background-color: rgba(255, 255, 255, .95); background-color: rgba(255, 255, 255, .95);
} }
.emoji-picker-emoji { .emoji-mart-emoji {
position: relative; position: relative;
display: inline-block; display: inline-block;
font-size: 0; font-size: 0;
} }
.emoji-picker-no-results { .emoji-mart-no-results {
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
padding-top: 70px; padding-top: 70px;
color: #858585; color: #858585;
} }
.emoji-picker-no-results span { .emoji-mart-no-results span {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
.emoji-picker-preview { .emoji-mart-preview {
position: relative; position: relative;
height: 70px; height: 70px;
} }
.emoji-picker-preview-emoji, .emoji-mart-preview-emoji,
.emoji-picker-preview-data, .emoji-mart-preview-data,
.emoji-picker-preview-skins { .emoji-mart-preview-skins {
position: absolute; position: absolute;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
} }
.emoji-picker-preview-emoji { .emoji-mart-preview-emoji {
left: 12px; left: 12px;
} }
.emoji-picker-preview-data { .emoji-mart-preview-data {
left: 68px; right: 12px; left: 68px; right: 12px;
word-break: break-word; word-break: break-word;
} }
.emoji-picker-preview-skins { .emoji-mart-preview-skins {
right: 30px; right: 30px;
text-align: right; text-align: right;
} }
.emoji-picker-preview-name { .emoji-mart-preview-name {
font-size: 14px; font-size: 14px;
} }
.emoji-picker-preview-shortname { .emoji-mart-preview-shortname {
font-size: 12px; font-size: 12px;
color: #888; color: #888;
} }
.emoji-picker-preview-shortname + .emoji-picker-preview-shortname, .emoji-mart-preview-shortname + .emoji-mart-preview-shortname,
.emoji-picker-preview-shortname + .emoji-picker-preview-emoticon, .emoji-mart-preview-shortname + .emoji-mart-preview-emoticon,
.emoji-picker-preview-emoticon + .emoji-picker-preview-emoticon { .emoji-mart-preview-emoticon + .emoji-mart-preview-emoticon {
margin-left: .5em; margin-left: .5em;
} }
.emoji-picker-preview-emoticon { .emoji-mart-preview-emoticon {
font-size: 11px; font-size: 11px;
color: #bbb; color: #bbb;
} }
.emoji-picker-title span { .emoji-mart-title span {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
.emoji-picker-title .emoji-picker-emoji { .emoji-mart-title .emoji-mart-emoji {
padding: 0; padding: 0;
} }
.emoji-picker-title-label { .emoji-mart-title-label {
color: #999A9C;
font-size: 26px; font-size: 26px;
font-weight: 500; font-weight: 300;
} }
.emoji-picker-skin-swatches { .emoji-mart-skin-swatches {
font-size: 0; font-size: 0;
padding: 2px 0; padding: 2px 0;
border: 1px solid #d9d9d9; border: 1px solid #d9d9d9;
@ -202,16 +203,16 @@
background-color: #fff; background-color: #fff;
} }
.emoji-picker-skin-swatches-opened .emoji-picker-skin-swatch { .emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch {
width: 16px; width: 16px;
padding: 0 2px; padding: 0 2px;
} }
.emoji-picker-skin-swatches-opened .emoji-picker-skin-swatch-selected:after { .emoji-mart-skin-swatches-opened .emoji-mart-skin-swatch-selected:after {
opacity: .75; opacity: .75;
} }
.emoji-picker-skin-swatch { .emoji-mart-skin-swatch {
display: inline-block; display: inline-block;
width: 0; width: 0;
vertical-align: middle; vertical-align: middle;
@ -220,19 +221,19 @@
transition-timing-function: ease-out; transition-timing-function: ease-out;
} }
.emoji-picker-skin-swatch:nth-child(1) { transition-delay: 0 } .emoji-mart-skin-swatch:nth-child(1) { transition-delay: 0 }
.emoji-picker-skin-swatch:nth-child(2) { transition-delay: .03s } .emoji-mart-skin-swatch:nth-child(2) { transition-delay: .03s }
.emoji-picker-skin-swatch:nth-child(3) { transition-delay: .06s } .emoji-mart-skin-swatch:nth-child(3) { transition-delay: .06s }
.emoji-picker-skin-swatch:nth-child(4) { transition-delay: .09s } .emoji-mart-skin-swatch:nth-child(4) { transition-delay: .09s }
.emoji-picker-skin-swatch:nth-child(5) { transition-delay: .12s } .emoji-mart-skin-swatch:nth-child(5) { transition-delay: .12s }
.emoji-picker-skin-swatch:nth-child(6) { transition-delay: .15s } .emoji-mart-skin-swatch:nth-child(6) { transition-delay: .15s }
.emoji-picker-skin-swatch-selected { .emoji-mart-skin-swatch-selected {
position: relative; position: relative;
width: 16px; width: 16px;
padding: 0 2px; padding: 0 2px;
} }
.emoji-picker-skin-swatch-selected:after { .emoji-mart-skin-swatch-selected:after {
content: ""; content: "";
position: absolute; position: absolute;
top: 50%; left: 50%; top: 50%; left: 50%;
@ -245,16 +246,16 @@
transition: opacity .2s ease-out; transition: opacity .2s ease-out;
} }
.emoji-picker-skin { .emoji-mart-skin {
display: inline-block; display: inline-block;
width: 100%; padding-top: 100%; width: 100%; padding-top: 100%;
max-width: 12px; max-width: 12px;
border-radius: 100%; border-radius: 100%;
} }
.emoji-picker-skin-tone-1 { background-color: #ffc93a } .emoji-mart-skin-tone-1 { background-color: #ffc93a }
.emoji-picker-skin-tone-2 { background-color: #fadcbc } .emoji-mart-skin-tone-2 { background-color: #fadcbc }
.emoji-picker-skin-tone-3 { background-color: #e0bb95 } .emoji-mart-skin-tone-3 { background-color: #e0bb95 }
.emoji-picker-skin-tone-4 { background-color: #bf8f68 } .emoji-mart-skin-tone-4 { background-color: #bf8f68 }
.emoji-picker-skin-tone-5 { background-color: #9b643d } .emoji-mart-skin-tone-5 { background-color: #9b643d }
.emoji-picker-skin-tone-6 { background-color: #594539 } .emoji-mart-skin-tone-6 { background-color: #594539 }

View File

@ -1,8 +1,8 @@
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>EmojiPicker</title> <title>Emoji Mart | One component to pick them all</title>
<link rel="stylesheet" href="../css/emoji-picker.css"> <link rel="stylesheet" href="../css/emoji-mart.css">
</head> </head>
<body> <body>
<div></div> <div></div>

View File

@ -27,7 +27,7 @@ class Example extends React.Component {
render() { render() {
return <div> return <div>
<h1>EmojiPicker</h1> <h1>Emoji Mart</h1>
<div> <div>
{['Apple', 'Google', 'Twitter', 'EmojiOne'].map((set) => { {['Apple', 'Google', 'Twitter', 'EmojiOne'].map((set) => {
@ -57,11 +57,9 @@ class Example extends React.Component {
margin: '1em', margin: '1em',
width: '460px', width: '460px',
}}> }}>
<Operator>import</Operator> &#123;Picker&#125; <Operator>from</Operator> <String>'emoji-picker'</String> <Operator>import</Operator> &#123;Picker&#125; <Operator>from</Operator> <String>'emoji-mart'</String>
<br /> <br />
<br /><Operator>&lt;</Operator><Variable>Picker</Variable> <br /><Operator>&lt;</Operator><Variable>Picker</Variable>
<br /> title<Operator>=</Operator><String>'EmojiPicker'</String>
<br /> emoji<Operator>=</Operator><String>'tophat'</String>
<br /> emojiSize<Operator>=</Operator>&#123;<Variable>{this.state.emojiSize}</Variable>&#125; <input type='range' data-key='emojiSize' onChange={this.handleInput.bind(this)} min='16' max='64' value={this.state.emojiSize} /> <br /> emojiSize<Operator>=</Operator>&#123;<Variable>{this.state.emojiSize}</Variable>&#125; <input type='range' data-key='emojiSize' onChange={this.handleInput.bind(this)} min='16' max='64' value={this.state.emojiSize} />
<br /> perLine<Operator>=</Operator>&#123;<Variable>{this.state.perLine}</Variable>&#125; {this.state.perLine < 10 ? ' ' : ' '} <input type='range' data-key='perLine' onChange={this.handleInput.bind(this)} min='7' max='16' value={this.state.perLine} /> <br /> perLine<Operator>=</Operator>&#123;<Variable>{this.state.perLine}</Variable>&#125; {this.state.perLine < 10 ? ' ' : ' '} <input type='range' data-key='perLine' onChange={this.handleInput.bind(this)} min='7' max='16' value={this.state.perLine} />
<br /> skin<Operator>=</Operator>&#123;<Variable>{this.state.skin}</Variable>&#125; <input type='range' data-key='skin' onChange={this.handleInput.bind(this)} min='1' max='6' value={this.state.skin} /> <br /> skin<Operator>=</Operator>&#123;<Variable>{this.state.skin}</Variable>&#125; <input type='range' data-key='skin' onChange={this.handleInput.bind(this)} min='1' max='6' value={this.state.skin} />

View File

@ -1,11 +1,11 @@
{ {
"name": "emoji-picker", "name": "emoji-mart",
"version": "0.1.5", "version": "0.1.5",
"description": "Customizable Slack-like emoji picker for React", "description": "Customizable Slack-like emoji picker for React",
"main": "dist/emoji-picker.js", "main": "dist/emoji-mart.js",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@github.com:missive/emoji-picker.git" "url": "git@github.com:missive/emoji-mart.git"
}, },
"keywords": [ "keywords": [
"react", "react",
@ -15,9 +15,9 @@
"author": "Etienne Lemay", "author": "Etienne Lemay",
"license": "ISC", "license": "ISC",
"bugs": { "bugs": {
"url": "https://github.com/missive/emoji-picker/issues" "url": "https://github.com/missive/emoji-mart/issues"
}, },
"homepage": "https://github.com/missive/emoji-picker", "homepage": "https://github.com/missive/emoji-mart",
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"react": "^0.14.0 || ^15.0.0-0" "react": "^0.14.0 || ^15.0.0-0"
@ -38,7 +38,7 @@
"react-dom": "15.2.0", "react-dom": "15.2.0",
"rimraf": "2.5.2", "rimraf": "2.5.2",
"svg-inline-loader": "0.4.1", "svg-inline-loader": "0.4.1",
"svg-inline-react": "1.0.1", "svg-inline-react": "1.0.2",
"webpack": "1.12.14" "webpack": "1.12.14"
}, },
"scripts": { "scripts": {

View File

@ -21,7 +21,7 @@ export default class Anchors extends React.Component {
var { categories, onAnchorClick, color } = this.props, var { categories, onAnchorClick, color } = this.props,
{ selected } = this.state { selected } = this.state
return <div className='emoji-picker-anchors'> return <div className='emoji-mart-anchors'>
{categories.map((category, i) => { {categories.map((category, i) => {
var { name, anchor } = category, var { name, anchor } = category,
isSelected = name == selected isSelected = name == selected
@ -35,11 +35,11 @@ export default class Anchors extends React.Component {
key={name} key={name}
title={name} title={name}
onClick={() => onAnchorClick(category, i)} onClick={() => onAnchorClick(category, i)}
className={`emoji-picker-anchor ${isSelected ? 'emoji-picker-anchor-selected' : ''}`} className={`emoji-mart-anchor ${isSelected ? 'emoji-mart-anchor-selected' : ''}`}
style={{ color: isSelected ? color : null }} style={{ color: isSelected ? color : null }}
> >
<InlineSVG src={SVGs[name]} /> <InlineSVG src={SVGs[name]} />
<span className='emoji-picker-anchor-bar' style={{ backgroundColor: color }}></span> <span className='emoji-mart-anchor-bar' style={{ backgroundColor: color }}></span>
</span> </span>
) )
})} })}

View File

@ -131,8 +131,8 @@ export default class Category extends React.Component {
} }
} }
return <div ref='container' className='emoji-picker-category' style={containerStyles}> return <div ref='container' className='emoji-mart-category' style={containerStyles}>
<div style={labelStyles} data-name={name} className='emoji-picker-category-label'> <div style={labelStyles} data-name={name} className='emoji-mart-category-label'>
<span style={labelSpanStyles} ref='label'>{LABELS[name]}</span> <span style={labelSpanStyles} ref='label'>{LABELS[name]}</span>
</div> </div>
@ -145,14 +145,14 @@ export default class Category extends React.Component {
)} )}
{emojis && !emojis.length && {emojis && !emojis.length &&
<div className='emoji-picker-no-results'> <div className='emoji-mart-no-results'>
<Emoji <Emoji
{...emojiProps} {...emojiProps}
size={22} size={22}
emoji='sleuth_or_spy' emoji='sleuth_or_spy'
/> />
<span className='emoji-picker-no-results-label'> <span className='emoji-mart-no-results-label'>
No emoji found No emoji found
</span> </span>
</div> </div>

View File

@ -65,7 +65,7 @@ export default class Emoji extends React.Component {
onClick={this.handleClick.bind(this)} onClick={this.handleClick.bind(this)}
onMouseEnter={this.handleOver.bind(this)} onMouseEnter={this.handleOver.bind(this)}
onMouseLeave={this.handleLeave.bind(this)} onMouseLeave={this.handleLeave.bind(this)}
className='emoji-picker-emoji'> className='emoji-mart-emoji'>
<span style={{ <span style={{
width: size, width: size,
height: size, height: size,

View File

@ -220,8 +220,8 @@ export default class Picker extends React.Component {
{ skin } = this.state, { skin } = this.state,
width = (perLine * (emojiSize + 12)) + 12 + 2 width = (perLine * (emojiSize + 12)) + 12 + 2
return <div style={{...style, width: width}} className='emoji-picker'> return <div style={{...style, width: width}} className='emoji-mart'>
<div className='emoji-picker-bar'> <div className='emoji-mart-bar'>
<Anchors <Anchors
ref='anchors' ref='anchors'
color={color} color={color}
@ -230,7 +230,7 @@ export default class Picker extends React.Component {
/> />
</div> </div>
<div ref="scroll" className='emoji-picker-scroll' onScroll={this.handleScroll.bind(this)}> <div ref="scroll" className='emoji-mart-scroll' onScroll={this.handleScroll.bind(this)}>
<Search <Search
ref='search' ref='search'
onSearch={this.handleSearch.bind(this)} onSearch={this.handleSearch.bind(this)}
@ -256,7 +256,7 @@ export default class Picker extends React.Component {
})} })}
</div> </div>
<div className='emoji-picker-bar'> <div className='emoji-mart-bar'>
<Preview <Preview
ref='preview' ref='preview'
title={title} title={title}
@ -294,7 +294,7 @@ Picker.defaultProps = {
perLine: 9, perLine: 9,
style: {}, style: {},
skin: 1, skin: 1,
title: 'EmojiPicker', title: 'Emoji Mart™',
emoji: 'tophat', emoji: 'department_store',
color: '#ae65c5', color: '#ae65c5',
} }

View File

@ -26,8 +26,8 @@ export default class Preview extends React.Component {
} }
} }
return <div className='emoji-picker-preview'> return <div className='emoji-mart-preview'>
<div className='emoji-picker-preview-emoji'> <div className='emoji-mart-preview-emoji'>
<Emoji <Emoji
key={emoji.id} key={emoji.id}
emoji={emoji} emoji={emoji}
@ -35,36 +35,36 @@ export default class Preview extends React.Component {
/> />
</div> </div>
<div className='emoji-picker-preview-data'> <div className='emoji-mart-preview-data'>
<div className='emoji-picker-preview-name'>{emoji.name}</div> <div className='emoji-mart-preview-name'>{emoji.name}</div>
<div className='emoji-picker-preview-shortnames'> <div className='emoji-mart-preview-shortnames'>
{emojiData.short_names.map((short_name) => {emojiData.short_names.map((short_name) =>
<span key={short_name} className='emoji-picker-preview-shortname'>:{short_name}:</span> <span key={short_name} className='emoji-mart-preview-shortname'>:{short_name}:</span>
)} )}
</div> </div>
<div className='emoji-picker-preview-emoticons'> <div className='emoji-mart-preview-emoticons'>
{listedEmoticons.map((emoticon) => {listedEmoticons.map((emoticon) =>
<span key={emoticon} className='emoji-picker-preview-emoticon'>{emoticon}</span> <span key={emoticon} className='emoji-mart-preview-emoticon'>{emoticon}</span>
)} )}
</div> </div>
</div> </div>
</div> </div>
} else { } else {
return <div className='emoji-picker-preview'> return <div className='emoji-mart-preview'>
<div className='emoji-picker-preview-emoji'> <div className='emoji-mart-preview-emoji'>
<Emoji <Emoji
emoji={idleEmoji} emoji={idleEmoji}
{...emojiProps} {...emojiProps}
/> />
</div> </div>
<div className='emoji-picker-preview-data'> <div className='emoji-mart-preview-data'>
<span className='emoji-picker-title-label'> <span className='emoji-mart-title-label'>
{title} {title}
</span> </span>
</div> </div>
<div className='emoji-picker-preview-skins'> <div className='emoji-mart-preview-skins'>
<Skins <Skins
{...skinsProps} {...skinsProps}
/> />

View File

@ -19,7 +19,7 @@ export default class Search extends React.Component {
type='text' type='text'
onChange={this.handleChange.bind(this)} onChange={this.handleChange.bind(this)}
placeholder='Search' placeholder='Search'
className='emoji-picker-search' className='emoji-mart-search'
/> />
} }
} }

View File

@ -25,15 +25,15 @@ export default class Skins extends React.Component {
{ opened } = this.state { opened } = this.state
return <div> return <div>
<div className={`emoji-picker-skin-swatches ${opened ? 'emoji-picker-skin-swatches-opened' : ''}`}> <div className={`emoji-mart-skin-swatches ${opened ? 'emoji-mart-skin-swatches-opened' : ''}`}>
{Array(6).fill().map((_, i) => { {Array(6).fill().map((_, i) => {
var skinTone = i + 1, var skinTone = i + 1,
selected = skinTone == skin selected = skinTone == skin
return <span key={`skin-tone-${skinTone}`} className={`emoji-picker-skin-swatch ${selected ? 'emoji-picker-skin-swatch-selected' : ''}`}> return <span key={`skin-tone-${skinTone}`} className={`emoji-mart-skin-swatch ${selected ? 'emoji-mart-skin-swatch-selected' : ''}`}>
<span <span
onClick={() => this.handleClick(skinTone)} onClick={() => this.handleClick(skinTone)}
className={`emoji-picker-skin emoji-picker-skin-tone-${skinTone}`}> className={`emoji-mart-skin emoji-mart-skin-tone-${skinTone}`}>
</span> </span>
</span> </span>
})} })}

View File

@ -1,4 +1,4 @@
const NAMESPACE = 'emoji-picker' const NAMESPACE = 'emoji-mart'
function update(state) { function update(state) {
for (let key in state) { for (let key in state) {

View File

@ -4,8 +4,8 @@ module.exports = {
entry: path.resolve('src/index.js'), entry: path.resolve('src/index.js'),
output: { output: {
path: path.resolve('dist'), path: path.resolve('dist'),
filename: 'emoji-picker.js', filename: 'emoji-mart.js',
library: 'EmojiPicker', library: 'EmojiMart',
libraryTarget: 'umd', libraryTarget: 'umd',
}, },