UNPKG

emoji-picker-react

Version:

Emoji Picker component for React Applications on the web

182 lines (138 loc) 4.61 kB
import { elementCountInRow } from './elementPositionInRow'; import { focusElement } from './focusElement'; import { scrollEmojiAboveLabel } from './scrollTo'; import { allVisibleEmojis, closestCategory, firstVisibleEmoji, lastVisibleEmoji, nextCategory, nextVisibleEmoji, NullableElement, prevCategory, prevVisibleEmoji, closestCategoryContent } from './selectors'; export function focusFirstVisibleEmoji(parent: NullableElement) { const emoji = firstVisibleEmoji(parent); focusElement(emoji); scrollEmojiAboveLabel(emoji); } export function focusAndClickFirstVisibleEmoji(parent: NullableElement) { const firstEmoji = firstVisibleEmoji(parent); focusElement(firstEmoji); firstEmoji?.click(); } export function focusLastVisibleEmoji(parent: NullableElement) { focusElement(lastVisibleEmoji(parent)); } export function focusNextVisibleEmoji(element: NullableElement) { if (!element) { return; } const next = nextVisibleEmoji(element); if (!next) { return focusFirstVisibleEmoji(nextCategory(element)); } focusElement(next); scrollEmojiAboveLabel(next); } export function focusPrevVisibleEmoji(element: NullableElement) { if (!element) { return; } const prev = prevVisibleEmoji(element); if (!prev) { return focusLastVisibleEmoji(prevCategory(element)); } focusElement(prev); scrollEmojiAboveLabel(prev); } export function focusVisibleEmojiOneRowUp( element: NullableElement, exitUp: () => void ) { if (!element) { return; } const prev = visibleEmojiOneRowUp(element); if (!prev) { return exitUp(); } focusElement(prev); scrollEmojiAboveLabel(prev); } export function focusVisibleEmojiOneRowDown(element: NullableElement) { if (!element) { return; } const next = visibleEmojiOneRowDown(element); return focusElement(next); } function visibleEmojiOneRowUp(element: HTMLElement) { if (!element) { return null; } const categoryContent = closestCategoryContent(element); const category = closestCategory(categoryContent); const countInRow = elementCountInRow(categoryContent, element); const emojisInCurrentCategory = allVisibleEmojis(category); const currentEmojiIndex = emojisInCurrentCategory.indexOf(element); const indexInRow = currentEmojiIndex % countInRow; if (currentEmojiIndex === -1) { return null; } if (emojisInCurrentCategory[currentEmojiIndex - countInRow]) { return emojisInCurrentCategory[currentEmojiIndex - countInRow]; } const prevVisibleCategory = prevCategory(category); if (!prevVisibleCategory) { return null; } const allPrevEmojis = allVisibleEmojis(prevVisibleCategory); // if there is an emoji in the same index of `indexInRow` in the previous category, return it // for this we need to find the last emoji in the previous category that shares the same indexInRow // this is by using the % operator to find the last emoji that matches const lastIndexInRow = (allPrevEmojis.length % countInRow) - 1; if (indexInRow > lastIndexInRow) { return allPrevEmojis.at(-1); } // otherwise, return the last emoji that shares the same indexInRow for (let i = allPrevEmojis.length - 1; i >= 0; i--) { if (i % countInRow === indexInRow) { return allPrevEmojis[i]; } } return allPrevEmojis.at(-1); } function visibleEmojiOneRowDown(element: HTMLElement) { if (!element) { return null; } const categoryContent = closestCategoryContent(element); const category = closestCategory(categoryContent); const countInRow = elementCountInRow(categoryContent, element); const emojisInCurrentCategory = allVisibleEmojis(category); const currentEmojiIndex = emojisInCurrentCategory.indexOf(element); if (currentEmojiIndex === -1) { return null; } // the remainder until the end of the row const remainder = countInRow - (currentEmojiIndex % countInRow) - 1; const firstInNextRow = currentEmojiIndex + remainder + 1; if (emojisInCurrentCategory[firstInNextRow]) { // if we have a next row, search in the next row for the last available emoji for (let p = currentEmojiIndex + countInRow; p % countInRow >= 0; p--) { if (emojisInCurrentCategory[p]) { return emojisInCurrentCategory[p]; } } } const indexInRow = currentEmojiIndex % countInRow; const nextVisibleCategory = nextCategory(category); const emojisInNextCategory = allVisibleEmojis(nextVisibleCategory); if (emojisInNextCategory[indexInRow]) { return emojisInNextCategory[indexInRow]; } return emojisInNextCategory.at(0) ?? null; }