diff --git a/README.md b/README.md index af47fb83..5eeaefea 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ function App() { | **onAddCustomEmoji** | `null` | | Callback when the *Add custom emoji* button is clicked. The button will only be displayed if this callback is provided. It is displayed when search returns no results. | | **autoFocus** | `false` | | Whether the picker should automatically focus on the search input | | **categoryIcons** | `{}` | | [Custom category icons](#custom-category-icons) | +| **dynamicWidth** | `false` | | Whether the picker should calculate `perLine` dynamically based on the width of ``. When enabled, `perLine` is ignored | | **emojiButtonColors** | `[]` | i.e. `#f00`, `pink`, `rgba(155,223,88,.7)` | An array of color that affects the hover background color | | **emojiButtonRadius** | `100%` | i.e. `6px`, `1em`, `100%` | The radius of the emoji buttons | | **emojiButtonSize** | `36` | | The size of the emoji buttons | diff --git a/packages/emoji-mart/src/components/Picker/Picker.tsx b/packages/emoji-mart/src/components/Picker/Picker.tsx index d603eb54..04de8250 100644 --- a/packages/emoji-mart/src/components/Picker/Picker.tsx +++ b/packages/emoji-mart/src/components/Picker/Picker.tsx @@ -18,8 +18,11 @@ export default class Picker extends Component { constructor(props) { super() + this.observers = [] + this.state = { pos: [-1, -1], + perLine: this.initDynamicPerLine(props), visibleRows: { 0: true }, ...this.getInitialState(props), } @@ -33,7 +36,6 @@ export default class Picker extends Component { } componentWillMount() { - this.observers = [] this.dir = I18n.rtl ? 'rtl' : 'ltr' this.refs = { menu: createRef(), @@ -133,10 +135,17 @@ export default class Picker extends Component { this.observeRows() } - unobserve() { + unobserve({ except = [] } = {}) { + if (!Array.isArray(except)) { + except = [except] + } + for (const observer of this.observers) { + if (except.includes(observer)) continue observer.disconnect() } + + this.observers = [].concat(except) } initGrid() { @@ -173,7 +182,7 @@ export default class Picker extends Component { let row = addRow(rows, category) for (let emoji of category.emojis) { - if (row.length == this.props.perLine) { + if (row.length == this.getPerLine()) { row = addRow(rows, category) } @@ -235,6 +244,36 @@ export default class Picker extends Component { } } + initDynamicPerLine(props = this.props) { + if (!props.dynamicWidth) return + const { element, emojiButtonSize } = props + + const calculatePerLine = () => { + const { width } = element.getBoundingClientRect() + return Math.floor(width / emojiButtonSize) + } + + const observer = new ResizeObserver(() => { + this.unobserve({ except: observer }) + this.setState({ perLine: calculatePerLine() }, () => { + this.initGrid() + this.forceUpdate(() => { + this.observeCategories() + this.observeRows() + }) + }) + }) + + observer.observe(element) + this.observers.push(observer) + + return calculatePerLine() + } + + getPerLine() { + return this.state.perLine || this.props.perLine + } + getEmojiByPos([p1, p2]) { const grid = this.state.searchResults || this.grid const emoji = grid[p1] && grid[p1][p2] @@ -349,7 +388,7 @@ export default class Picker extends Component { let row = null for (let emoji of searchResults) { - if (!grid.length || row.length == this.props.perLine) { + if (!grid.length || row.length == this.getPerLine()) { row = [] row.__categoryId = 'search' row.__index = grid.length @@ -852,6 +891,7 @@ export default class Picker extends Component { renderCategories() { const { categories } = Data const hidden = !!this.state.searchResults + const perLine = this.getPerLine() return (
{visible && emojiIds.map((emojiId, ii) => { + if (!emojiId) { + return ( +
+ ) + } + const emoji = SearchIndex.get(emojiId) return this.renderEmojiButton(emoji, { @@ -1048,9 +1103,6 @@ export default class Picker extends Component {
diff --git a/packages/emoji-mart/src/components/Picker/PickerProps.ts b/packages/emoji-mart/src/components/Picker/PickerProps.ts index 45a15179..6a50e1d3 100644 --- a/packages/emoji-mart/src/components/Picker/PickerProps.ts +++ b/packages/emoji-mart/src/components/Picker/PickerProps.ts @@ -2,6 +2,9 @@ export default { autoFocus: { value: false, }, + dynamicWidth: { + value: false, + }, emojiButtonColors: { value: null, }, diff --git a/packages/emoji-mart/src/components/Picker/PickerStyles.scss b/packages/emoji-mart/src/components/Picker/PickerStyles.scss index 0284754b..6d217b2e 100644 --- a/packages/emoji-mart/src/components/Picker/PickerStyles.scss +++ b/packages/emoji-mart/src/components/Picker/PickerStyles.scss @@ -451,6 +451,10 @@ button { .skin-tone-5 { background-color: #a46134 } .skin-tone-6 { background-color: #5d4437 } +[data-index] { + justify-content: space-between; +} + [data-emoji-set="twitter"] { .skin-tone:after { border-color: rgba(0,0,0, .5);