diff --git a/README.md b/README.md index 64dae25..a33fb54 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ import { Picker } from 'emoji-mart' | **title** | | `Emoji Mart™` | The title shown when no emojis are hovered | | **notFoundEmoji** | | `sleuth_or_spy` | The emoji shown when there are no search results | | **notFound** | | | [Not Found](#not-found) | +| **icons** | | `{}` | [Custom icons](#custom-icons) | #### I18n ```js @@ -247,6 +248,23 @@ const notFound = () => , + foods: () => , + people: () => + } +} + + +``` + ## Headless search The `Picker` doesn’t have to be mounted for you to take advantage of the advanced search results. diff --git a/css/emoji-mart.css b/css/emoji-mart.css index aba92a5..c8a00f9 100644 --- a/css/emoji-mart.css +++ b/css/emoji-mart.css @@ -72,9 +72,11 @@ max-width: 22px; } -.emoji-mart-anchors svg { +.emoji-mart-anchors svg, +.emoji-mart-anchors img { fill: currentColor; - max-height: 18px; + height: 18px; + width: 18px; } .emoji-mart-scroll { diff --git a/src/components/anchors.js b/src/components/anchors.js index 13a484b..5008d6b 100644 --- a/src/components/anchors.js +++ b/src/components/anchors.js @@ -1,8 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { categories as icons } from '../svgs' - export default class Anchors extends React.PureComponent { constructor(props) { super(props) @@ -26,7 +24,7 @@ export default class Anchors extends React.PureComponent { } render() { - var { categories, onAnchorClick, color, i18n } = this.props, + var { categories, color, i18n, icons } = this.props, { selected } = this.state return ( @@ -50,7 +48,9 @@ export default class Anchors extends React.PureComponent { }`} style={{ color: isSelected ? color : null }} > -
+
+ {icons.categories[id]()} +
{}, + icons: {}, } diff --git a/src/components/picker/nimble-picker.js b/src/components/picker/nimble-picker.js index 45d6568..5d54057 100644 --- a/src/components/picker/nimble-picker.js +++ b/src/components/picker/nimble-picker.js @@ -3,6 +3,7 @@ import '../../vendor/raf-polyfill' import React from 'react' import PropTypes from 'prop-types' +import * as icons from '../../svgs' import store from '../../utils/store' import frequently from '../../utils/frequently' import { deepMerge, measureScrollbar } from '../../utils' @@ -48,6 +49,7 @@ export default class NimblePicker extends React.PureComponent { this.data = props.data this.i18n = deepMerge(I18N, props.i18n) + this.icons = deepMerge(icons, props.icons) this.state = { skin: props.skin || store.get('skin') || props.defaultSkin, firstRender: true, @@ -487,6 +489,7 @@ export default class NimblePicker extends React.PureComponent { color={color} categories={this.categories} onAnchorClick={this.handleAnchorClick} + icons={this.icons} />
diff --git a/src/components/search.js b/src/components/search.js index a2d7763..fc8f31d 100644 --- a/src/components/search.js +++ b/src/components/search.js @@ -81,8 +81,9 @@ export default class Search extends React.PureComponent { onClick={this.clear} onKeyUp={this.handleKeyUp} disabled={!isSearching} - dangerouslySetInnerHTML={{ __html: icon }} - /> + > + {icon()} + ) } diff --git a/src/svgs/index.js b/src/svgs/index.js index b6a7f74..5f1a024 100644 --- a/src/svgs/index.js +++ b/src/svgs/index.js @@ -1,29 +1,166 @@ +import React from 'react' + const categories = { - activity: ``, + activity: () => ( + + + + ), - custom: ``, + custom: () => ( + + + + + + + + ), - flags: ``, + flags: () => ( + + + + ), - foods: ``, + foods: () => ( + + + + ), - nature: ``, + nature: () => ( + + + + + ), - objects: ``, + objects: () => ( + + + + + ), - people: ``, + people: () => ( + + + + + ), - places: ``, + places: () => ( + + + + + ), - recent: ``, + recent: () => ( + + + + + ), - symbols: ``, + symbols: () => ( + + + + ), } const search = { - search: ``, + search: () => ( + + + + ), - delete: ``, + delete: () => ( + + + + ), } export { categories, search } diff --git a/src/utils/shared-props.js b/src/utils/shared-props.js index c2041be..fcea08f 100644 --- a/src/utils/shared-props.js +++ b/src/utils/shared-props.js @@ -73,6 +73,7 @@ const PickerPropTypes = { ), notFound: PropTypes.func, notFoundEmoji: PropTypes.string, + icons: PropTypes.object, } const PickerDefaultProps = { @@ -100,6 +101,7 @@ const PickerDefaultProps = { custom: [], notFound: () => {}, notFoundEmoji: 'sleuth_or_spy', + icons: {}, } export { diff --git a/stories/index.js b/stories/index.js index d639b61..0a4a6c2 100644 --- a/stories/index.js +++ b/stories/index.js @@ -1,11 +1,18 @@ -import React from 'react'; +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 { storiesOf } from '@storybook/react' +import { action } from '@storybook/addon-actions' +import { + withKnobs, + text, + boolean, + number, + select, + color, +} from '@storybook/addon-knobs' -import { Picker, Emoji, emojiIndex } from '../dist'; -import '../css/emoji-mart.css'; +import { Picker, Emoji, emojiIndex } from '../dist' +import '../css/emoji-mart.css' const SETS = ['apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'] const CUSTOM_EMOJIS = [ @@ -13,14 +20,14 @@ const CUSTOM_EMOJIS = [ name: 'Octocat', short_names: ['octocat'], keywords: ['github'], - imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7' + 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' - } + imageUrl: 'https://assets-cdn.github.com/images/icons/emoji/shipit.png?v7', + }, ] storiesOf('Picker', module) @@ -42,20 +49,137 @@ storiesOf('Picker', module) showPreview={boolean('Show preview', true)} showSkinTones={boolean('Show skin tones', true)} custom={CUSTOM_EMOJIS} - />)) - .add('with a custom not found image', () => ( - - } - />)) - .add('with a custom not found SVG', () => ( - Jira icon - } - /> - )); + /> + )) + .add('with a custom not found image', () => ( + ( + + )} + /> + )) + .add('with a custom not found SVG', () => ( + ( + + Jira icon + + + )} + /> + )) + .add('with-custom-icons', () => ( + ( + + ), + people: () => ( + + Reddit icon + + + ), + nature: () => ( + + + + + + ), + foods: () => ( + + Jira icon + + + ), + activity: () => ( + + ), + places: () => ( + + + Stack Overflow icon + + + + ), + objects: () => ( + + Atlassian icon + + + ), + symbols: () => ( + + HipChat icon + + + ), + flags: () => ( + + + + ), + custom: () => ( + + Trello icon + + + ), + }, + }} + /> + )) storiesOf('Emoji', module) .addDecorator(withKnobs) @@ -71,19 +195,27 @@ storiesOf('Emoji', module) return emoji ? `:${emoji.short_names[0]}:` : props.emoji }} /> - )); + )) storiesOf('Headless Search', module) .addDecorator(withKnobs) .add('default', () => { - let results = emojiIndex.search(text('Search', 'christmas'), { custom: CUSTOM_EMOJIS }) - if (!results) { return null } + let results = emojiIndex.search(text('Search', 'christmas'), { + custom: CUSTOM_EMOJIS, + }) + if (!results) { + return null + } - return
- {results.map((emoji) => { - return - - - })} -
- }); + return ( +
+ {results.map((emoji) => { + return ( + + + + ) + })} +
+ ) + })