commit
c5ca59284f
|
@ -0,0 +1,3 @@
|
|||
import '@storybook/addon-knobs/register';
|
||||
import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-options/register';
|
|
@ -0,0 +1,11 @@
|
|||
import { configure } from '@storybook/react';
|
||||
import { setOptions } from '@storybook/addon-options';
|
||||
|
||||
setOptions({
|
||||
name: 'Contribute on GitHub',
|
||||
url: 'https://github.com/missive/emoji-mart',
|
||||
downPanelInRight: true,
|
||||
sidebarAnimations: false,
|
||||
})
|
||||
|
||||
configure(() => require('../stories'), module);
|
|
@ -0,0 +1,39 @@
|
|||
const path = require('path')
|
||||
const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js');
|
||||
|
||||
module.exports = (baseConfig, env) => {
|
||||
const config = genDefaultConfig(baseConfig, env);
|
||||
|
||||
config.module.rules = [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, '../stories'),
|
||||
path.resolve(__dirname, '../src'),
|
||||
path.resolve(__dirname, '../node_modules/measure-scrollbar'),
|
||||
path.resolve(__dirname, '../data'),
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loaders: ['babel-loader?presets[]=react', 'svg-jsx-loader?es6=true'],
|
||||
include: [
|
||||
path.resolve(__dirname, '../src/svgs'),
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [ 'style-loader', 'css-loader' ],
|
||||
include: [
|
||||
path.resolve(__dirname, '../css'),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
config.devtool.sourcemaps = {
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
|
@ -218,8 +218,7 @@ Apple / Google / Twitter / EmojiOne / Messenger / Facebook
|
|||
## Development
|
||||
```sh
|
||||
$ yarn run build:data
|
||||
$ yarn start
|
||||
$ open example/index.html
|
||||
$ yarn storybook
|
||||
```
|
||||
|
||||
## 🎩 Hat tips!
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Emoji Mart | One component to pick them all</title>
|
||||
<link rel="stylesheet" href="../css/emoji-mart.css">
|
||||
<style>
|
||||
* {
|
||||
margin: 0; padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
button + button { margin-left: .5em }
|
||||
button {
|
||||
padding: .4em .6em;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgba(0, 0, 0, .1);
|
||||
background: #fff;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button[disabled] {
|
||||
border-color: #ae65c5;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.demo-title {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
margin-left: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div></div>
|
||||
<script src="./bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
313
example/index.js
313
example/index.js
|
@ -1,313 +0,0 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import { Picker, Emoji } from '../src'
|
||||
|
||||
const CUSTOM_EMOJIS = [
|
||||
{
|
||||
name: 'Octocat',
|
||||
short_names: ['octocat'],
|
||||
keywords: ['github'],
|
||||
imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7'
|
||||
},
|
||||
{
|
||||
name: 'Squirrel',
|
||||
short_names: ['shipit', 'squirrel'],
|
||||
keywords: ['github'],
|
||||
imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/shipit.png?v7'
|
||||
}
|
||||
]
|
||||
|
||||
const CATEGORIES = [
|
||||
'recent',
|
||||
'people',
|
||||
'nature',
|
||||
'foods',
|
||||
'activity',
|
||||
'places',
|
||||
'objects',
|
||||
'symbols',
|
||||
'flags',
|
||||
'custom',
|
||||
]
|
||||
|
||||
class Example extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
emojiSize: 24,
|
||||
perLine: 9,
|
||||
skin: 1,
|
||||
native: true,
|
||||
set: 'apple',
|
||||
hidden: false,
|
||||
currentEmoji: { id: '+1' },
|
||||
autoFocus: false,
|
||||
include: [],
|
||||
exclude: [],
|
||||
}
|
||||
}
|
||||
|
||||
handleInput(e) {
|
||||
var { currentTarget } = e,
|
||||
{ type } = currentTarget,
|
||||
key = currentTarget.getAttribute('data-key'),
|
||||
mount = currentTarget.getAttribute('data-mount'),
|
||||
state = {}
|
||||
|
||||
if (type == 'checkbox') {
|
||||
var { checked } = currentTarget,
|
||||
value = currentTarget.getAttribute('data-value')
|
||||
|
||||
if (value) {
|
||||
if (checked) {
|
||||
state[key] = this.state[key].concat(value)
|
||||
} else {
|
||||
state[key] = this.state[key].filter((item) => { return item != value })
|
||||
}
|
||||
} else {
|
||||
state[key] = checked
|
||||
}
|
||||
} else {
|
||||
var { value } = currentTarget
|
||||
state[key] = parseInt(value)
|
||||
}
|
||||
|
||||
if (mount) {
|
||||
this.setState({ hidden: true }, () => {
|
||||
state.hidden = false
|
||||
this.setState(state)
|
||||
})
|
||||
} else {
|
||||
this.setState(state)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<div>
|
||||
<h1 className='demo-title'>Emoji Mart</h1>
|
||||
|
||||
<iframe
|
||||
src='https://ghbtns.com/github-btn.html?user=missive&repo=emoji-mart&type=star&count=true'
|
||||
frameBorder='0'
|
||||
scrolling='0'
|
||||
width='170px'
|
||||
height='20px'
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
{['native', 'apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'].map((set) => {
|
||||
var props = { disabled: !this.state.native && set == this.state.set }
|
||||
|
||||
if (set == 'native' && this.state.native) {
|
||||
props.disabled = true
|
||||
}
|
||||
|
||||
return <button
|
||||
key={set}
|
||||
value={set}
|
||||
onClick={() => {
|
||||
if (set == 'native') {
|
||||
this.setState({ native: true })
|
||||
} else {
|
||||
this.setState({ set: set, native: false })
|
||||
}
|
||||
}}
|
||||
{...props}>
|
||||
{set}
|
||||
</button>
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<button
|
||||
onClick={() => this.setState({ hidden: !this.state.hidden })}
|
||||
>{this.state.hidden ? 'Mount' : 'Unmount'}</button>
|
||||
</div>
|
||||
|
||||
<pre style={{
|
||||
fontSize: 18,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
margin: '1em',
|
||||
width: '460px',
|
||||
}}>
|
||||
<Operator>import</Operator> {Picker} <Operator>from</Operator> <String>'emoji-mart'</String>
|
||||
<br />
|
||||
<br /><Operator><</Operator><Variable>Picker</Variable>
|
||||
<br /> emojiSize<Operator>=</Operator>{<Variable>{this.state.emojiSize}</Variable>} <input type='range' data-key='emojiSize' data-mount={true} onChange={this.handleInput.bind(this)} min='16' max='64' value={this.state.emojiSize} />
|
||||
<br /> perLine<Operator>=</Operator>{<Variable>{this.state.perLine}</Variable>} {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>{<Variable>{this.state.skin}</Variable>} <input type='range' data-key='skin' onChange={this.handleInput.bind(this)} min='1' max='6' value={this.state.skin} />
|
||||
<br /> set<Operator>=</Operator><String>'{this.state.set}'</String>
|
||||
<br /> custom<Operator>=</Operator>{<Variable>{'[…]'}</Variable>}
|
||||
<br /> autoFocus<Operator>=</Operator>{<Variable>{this.state.autoFocus ? 'true' : 'false'}</Variable>}{this.state.autoFocus ? ' ' : ''} <input type='checkbox' data-key='autoFocus' data-mount={true} onChange={this.handleInput.bind(this)} checked={this.state.autoFocus} />
|
||||
<div style={{ opacity: this.state.exclude.length ? 0.6 : 1 }}> include<Operator>=</Operator>[
|
||||
{[0, 2, 4, 6, 8].map((i) => {
|
||||
let category1 = CATEGORIES[i],
|
||||
category2 = CATEGORIES[i + 1]
|
||||
|
||||
return <div key={i}>
|
||||
<label style={{ width: '200px', display: 'inline-block' }}> <input type='checkbox' data-key='include' data-value={category1} data-mount={true} onChange={this.handleInput.bind(this)} disabled={this.state.exclude.length} /> <String>'{category1}'</String></label>
|
||||
{category2 && <label><input type='checkbox' data-key='include' data-value={category2} data-mount={true} onChange={this.handleInput.bind(this)} disabled={this.state.exclude.length} /> <String>'{category2}'</String></label>}
|
||||
</div>
|
||||
})}
|
||||
]
|
||||
</div>
|
||||
<div style={{ opacity: this.state.include.length ? 0.6 : 1 }}> exclude<Operator>=</Operator>[
|
||||
{[0, 2, 4, 6, 8].map((i) => {
|
||||
let category1 = CATEGORIES[i],
|
||||
category2 = CATEGORIES[i + 1]
|
||||
|
||||
return <div key={i}>
|
||||
<label style={{ width: '200px', display: 'inline-block' }}> <input type='checkbox' data-key='exclude' data-value={category1} data-mount={true} onChange={this.handleInput.bind(this)} disabled={this.state.include.length} /> <String>'{category1}'</String></label>
|
||||
{category2 && <label><input type='checkbox' data-key='exclude' data-value={category2} data-mount={true} onChange={this.handleInput.bind(this)} disabled={this.state.include.length} /> <String>'{category2}'</String></label>}
|
||||
</div>
|
||||
})}
|
||||
]
|
||||
</div>
|
||||
<Operator>/></Operator>
|
||||
</pre>
|
||||
|
||||
{!this.state.hidden &&
|
||||
<Picker
|
||||
emojiSize={this.state.emojiSize}
|
||||
perLine={this.state.perLine}
|
||||
skin={this.state.skin}
|
||||
native={this.state.native}
|
||||
set={this.state.set}
|
||||
custom={CUSTOM_EMOJIS}
|
||||
autoFocus={this.state.autoFocus}
|
||||
include={this.state.include}
|
||||
exclude={this.state.exclude}
|
||||
onClick={(emoji) => {
|
||||
this.setState({ currentEmoji: emoji })
|
||||
console.log(emoji)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
||||
<div>
|
||||
<pre style={{
|
||||
fontSize: 18,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
margin: '1em',
|
||||
width: '370px',
|
||||
}}>
|
||||
<Operator>import</Operator> {Emoji} <Operator>from</Operator> <String>'emoji-mart'</String>
|
||||
<br />
|
||||
<br /><Operator><</Operator><Variable>Emoji</Variable>
|
||||
<br /> emoji<Operator>=</Operator>{this.state.currentEmoji.custom ? (<Variable>{'{…}'}</Variable>) : (<String>'{this.state.currentEmoji.id}'</String>)}
|
||||
<br /> size<Operator>=</Operator>{<Variable>{64}</Variable>}
|
||||
<br /><Operator>/></Operator>
|
||||
</pre>
|
||||
|
||||
<span style={{ display: 'inline-block', marginTop: 60 }}>
|
||||
{Emoji({
|
||||
emoji: this.state.currentEmoji.custom ? this.state.currentEmoji : this.state.currentEmoji.id,
|
||||
size: 64,
|
||||
set: this.state.set,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<pre style={{
|
||||
fontSize: 18,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
margin: '1em',
|
||||
width: '370px',
|
||||
}}>
|
||||
<br /><Operator><</Operator><Variable>Emoji</Variable>
|
||||
<br /> emoji<Operator>=</Operator><String>':{this.state.currentEmoji.id}:'</String>
|
||||
<br /> size<Operator>=</Operator>{<Variable>{64}</Variable>}
|
||||
<br /><Operator>/></Operator>
|
||||
</pre>
|
||||
|
||||
<span style={{ display: 'inline-block', marginTop: 40 }}>
|
||||
{Emoji({
|
||||
emoji: `:${this.state.currentEmoji.id}:`,
|
||||
size: 64,
|
||||
set: this.state.set,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<pre style={{
|
||||
fontSize: 18,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
margin: '1em',
|
||||
width: '370px',
|
||||
}}>
|
||||
<br /><Operator><</Operator><Variable>Emoji</Variable>
|
||||
<br /> emoji<Operator>=</Operator><String>':{this.state.currentEmoji.id}::skin-tone-3:'</String>
|
||||
<br /> size<Operator>=</Operator>{<Variable>{64}</Variable>}
|
||||
<br /><Operator>/></Operator>
|
||||
</pre>
|
||||
|
||||
<span style={{ display: 'inline-block', marginTop: 40 }}>
|
||||
{Emoji({
|
||||
emoji: `:${this.state.currentEmoji.id}::skin-tone-3:`,
|
||||
size: 64,
|
||||
set: this.state.set,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<pre style={{
|
||||
fontSize: 18,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'top',
|
||||
margin: '1em',
|
||||
width: '370px',
|
||||
}}>
|
||||
<br /><Operator><</Operator><Variable>Emoji</Variable>
|
||||
<br /> emoji<Operator>=</Operator><String>':{this.state.currentEmoji.id}::skin-tone-3:'</String>
|
||||
<br /> size<Operator>=</Operator>{<Variable>{64}</Variable>}
|
||||
<br /> native<Operator>=</Operator>{<Variable>{'true'}</Variable>}
|
||||
<br /><Operator>/></Operator>
|
||||
</pre>
|
||||
|
||||
<span style={{ display: 'inline-block', marginTop: 60 }}>
|
||||
{Emoji({
|
||||
emoji: `:${this.state.currentEmoji.id}::skin-tone-3:`,
|
||||
size: 64,
|
||||
native: true,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
class Operator extends React.Component {
|
||||
render() {
|
||||
return <span style={{color: '#a71d5d'}}>
|
||||
{this.props.children}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
class Variable extends React.Component {
|
||||
render() {
|
||||
return <span style={{color: '#0086b3'}}>
|
||||
{this.props.children}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
class String extends React.Component {
|
||||
render() {
|
||||
return <span style={{color: '#183691'}}>
|
||||
{this.props.children}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Example />, document.querySelector('div'))
|
|
@ -1,53 +0,0 @@
|
|||
var path = require('path')
|
||||
var pack = require('../package.json')
|
||||
var webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
entry: path.resolve('example/index.js'),
|
||||
output: {
|
||||
path: path.resolve('example'),
|
||||
filename: 'bundle.js',
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: 'babel-loader',
|
||||
include: [
|
||||
path.resolve('src'),
|
||||
path.resolve('node_modules/measure-scrollbar'),
|
||||
path.resolve('data'),
|
||||
path.resolve('example'),
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader'
|
||||
},
|
||||
{
|
||||
loader: 'svg-jsx-loader',
|
||||
options: {
|
||||
es6: true
|
||||
}
|
||||
},
|
||||
],
|
||||
include: [
|
||||
path.resolve('src/svgs'),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js'],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
EMOJI_DATASOURCE_VERSION: `'${pack.devDependencies['emoji-datasource']}'`,
|
||||
}),
|
||||
],
|
||||
}
|
14
package.json
14
package.json
|
@ -25,6 +25,11 @@
|
|||
"react": "^0.14.0 || ^15.0.0-0 || ^16.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "^3.2.11",
|
||||
"@storybook/addon-knobs": "^3.2.10",
|
||||
"@storybook/addon-links": "^3.2.10",
|
||||
"@storybook/addon-options": "3.2.10",
|
||||
"@storybook/react": "^3.2.11",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "6.7.2",
|
||||
"babel-loader": "^7.1.2",
|
||||
|
@ -59,17 +64,18 @@
|
|||
"clean": "rimraf data/data.js dist/",
|
||||
"clean:dist": "rm -rf dist/",
|
||||
"build:data": "node scripts/build-data",
|
||||
"build:example": "node scripts/build-example",
|
||||
"build:dist": "npm run clean:dist && babel src --out-dir dist --copy-files --ignore webpack.config.js",
|
||||
"build": "npm run build:data && npm run build:example && npm run build:dist",
|
||||
"build": "npm run build:data && npm run build:dist",
|
||||
"watch": "babel src --watch --out-dir dist --copy-files --ignore webpack.config.js",
|
||||
"start": "npm run watch",
|
||||
"stats": "webpack --config ./example/webpack.config.js --json > stats.json",
|
||||
"stats": "webpack --config ./src/webpack.config.js --json > stats.json",
|
||||
"react:clean": "rimraf node_modules/{react,react-dom,react-addons-test-utils}",
|
||||
"react:14": "npm run react:clean && npm i react@^0.14 react-dom@^0.14 react-addons-test-utils@^0.14 --save-dev",
|
||||
"react:15": "npm run react:clean && npm i react@^15 react-dom@^15 react-addons-test-utils@^15 --save-dev",
|
||||
"test": "NODE_ENV=test karma start && size-limit",
|
||||
"prepublish": "npm run clean && npm run build"
|
||||
"prepublish": "npm run clean && npm run build",
|
||||
"storybook": "start-storybook -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"size-limit": [
|
||||
{
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
var path = require('path')
|
||||
var webpack = require('webpack')
|
||||
var config = require('../example/webpack.config.js')
|
||||
|
||||
webpack(config, (err, stats) => {
|
||||
if (err) throw err
|
||||
|
||||
console.log(
|
||||
stats.toString({
|
||||
colors: true,
|
||||
hash: true,
|
||||
version: false,
|
||||
timings: true,
|
||||
assets: true,
|
||||
chunks: false,
|
||||
chunkModules: false,
|
||||
modules: false,
|
||||
children: false,
|
||||
cached: false,
|
||||
reasons: false,
|
||||
source: false,
|
||||
errorDetails: false,
|
||||
chunkOrigins: false,
|
||||
})
|
||||
)
|
||||
})
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { withKnobs, text, boolean, number, select, color } from '@storybook/addon-knobs';
|
||||
|
||||
import { Picker, Emoji } from '../src';
|
||||
import '../css/emoji-mart.css';
|
||||
|
||||
const SETS = ['apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook']
|
||||
|
||||
storiesOf('Picker', module)
|
||||
.addDecorator(withKnobs)
|
||||
.add('default', () => (
|
||||
<Picker
|
||||
onClick={action('clicked')}
|
||||
native={boolean('Unicode', true)}
|
||||
set={select('Emoji pack', SETS, SETS[0])}
|
||||
emojiSize={number('Emoji size', 24)}
|
||||
perLine={number('Per line', 9)}
|
||||
title={text('Idle text', 'Your Title Here')}
|
||||
emoji={text('Idle emoji', 'department_store')}
|
||||
skin={number('Skin tone', 1)}
|
||||
color={color('Highlight color', '#ae65c5')}
|
||||
/>
|
||||
));
|
||||
|
||||
storiesOf('Emoji', module)
|
||||
.addDecorator(withKnobs)
|
||||
.add('default', () => (
|
||||
<Emoji
|
||||
native={boolean('Unicode', true)}
|
||||
set={select('Emoji pack', SETS, SETS[0])}
|
||||
emoji={text('Emoji', '+1')}
|
||||
size={number('Emoji size', 64)}
|
||||
skin={number('Skin tone', 1)}
|
||||
/>
|
||||
));
|
Loading…
Reference in New Issue