{"version":3,"file":"emoji_selector.vue.cjs","sources":["../../../../components/emoji_picker/modules/emoji_selector.vue"],"sourcesContent":["<template>\n  <div\n    class=\"d-emoji-picker__selector\"\n  >\n    <div\n      id=\"d-emoji-picker-list\"\n      ref=\"listRef\"\n      class=\"d-emoji-picker__list\"\n    >\n      <p\n        v-if=\"emojiFilter\"\n        class=\"d-emoji-picker__search-label d-emoji-picker__alignment\"\n      >\n        {{ filteredEmojis.length > 0 ? searchResultsLabel : searchNoResultsLabel }}\n      </p>\n      <div\n        v-else\n        ref=\"tabCategoryRef\"\n        class=\"d-emoji-picker__category d-emoji-picker__alignment\"\n      >\n        <p>\n          {{ fixedLabel }}\n        </p>\n      </div>\n      <div\n        v-for=\"(tabLabel, indexTab) in tabLabels\"\n        v-show=\"!emojiFilter\"\n        :key=\"indexTab\"\n        :ref=\"tabLabel.ref\"\n        class=\"d-emoji-picker__alignment\"\n      >\n        <p\n          v-if=\"indexTab\"\n        >\n          {{ tabLabel.label }}\n        </p>\n        <div\n          class=\"d-emoji-picker__tab\"\n        >\n          <button\n            v-for=\"(emoji, indexEmoji) in\n            (emojis[tabs[indexTab] + skinTone] ? emojis[tabs[indexTab] + skinTone] : emojis[tabs[indexTab]])\"\n            :key=\"emoji.shortname\"\n            :ref=\"el => { if (el) setEmojiRef(el, indexTab, indexEmoji) }\"\n            type=\"button\"\n            :aria-label=\"emoji.name\"\n            @click=\"event => selectEmoji(emoji, event)\"\n            @focusin=\"highlightEmoji(emoji)\"\n            @focusout=\"highlightEmoji(null)\"\n            @mouseover=\"highlightEmoji(emoji)\"\n            @mouseleave=\"highlightEmoji(null)\"\n            @keydown=\"event => handleKeyDown(event, indexTab, indexEmoji, emoji)\"\n          >\n            <img\n              class=\"d-icon d-icon--size-500\"\n              :alt=\"emoji.name\"\n              :aria-label=\"emoji.name\"\n              :title=\"emoji.name\"\n              :src=\"getImgSrc(emoji.unicode_character)\"\n              @error=\"handleImageError\"\n            >\n          </button>\n        </div>\n      </div>\n      <div\n        v-if=\"emojiFilter\"\n        class=\"d-emoji-picker__alignment\"\n      >\n        <div\n          class=\"d-emoji-picker__tab \"\n          data-qa=\"filtered-emojis\"\n        >\n          <button\n            v-for=\"(emoji, index) in filteredEmojis\"\n            :key=\"emoji.shortname\"\n            :ref=\"el => { if (el) setFilteredRef(el, index) }\"\n            type=\"button\"\n            :aria-label=\"emoji.name\"\n            :class=\"{\n              'hover-emoji': (index === 0 && hoverFirstEmoji),\n            }\"\n            @click=\"event => selectEmoji(emoji, event)\"\n            @focusin=\"highlightEmoji(emoji)\"\n            @focusout=\"highlightEmoji(null)\"\n            @mouseover=\"hoverEmoji(emoji)\"\n            @mouseleave=\"hoverEmoji(null)\"\n            @keydown=\"event => handleKeyDownFilteredEmojis(event, index, emoji)\"\n          >\n            <img\n              class=\"d-icon d-icon--size-500\"\n              :alt=\"emoji.name\"\n              :aria-label=\"emoji.name\"\n              :title=\"emoji.name\"\n              :src=\"`${CDN_URL + emoji.unicode_character}.png`\"\n            >\n          </button>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\n/* eslint-disable max-len */\n/* eslint-disable max-lines */\nimport { emojisGrouped as emojis } from '@dialpad/dialtone-emojis';\nimport { computed, onMounted, onUnmounted, ref, watch, nextTick } from 'vue';\nimport { CDN_URL, ARROW_KEYS } from '@/components/emoji_picker/emoji_picker_constants';\nimport { useKeyboardNavigation } from '@/components/emoji_picker/composables/useKeyboardNavigation';\n\nconst props = defineProps({\n  /**\n   * The filter to apply to the emoji list\n   * @type {String}\n   * @default ''\n   */\n  emojiFilter: {\n    type: String,\n    default: '',\n  },\n\n  /**\n   * The skin tone to apply to the emoji list\n   * @type {String}\n   * @required\n   */\n  skinTone: {\n    type: String,\n    required: true,\n  },\n\n  /**\n   * The labels for the tabset\n   * @type {Array}\n   * @required\n   */\n  tabsetLabels: {\n    type: Array,\n    required: true,\n  },\n\n  selectedTabset: {\n    type: Object,\n    required: true,\n  },\n\n  /**\n   * The label for the search results tab\n   * @type {String}\n   * @required\n   */\n  searchResultsLabel: {\n    type: String,\n    required: true,\n  },\n\n  searchNoResultsLabel: {\n    type: String,\n    required: true,\n  },\n\n  /**\n   * The list of recently used emojis\n   * @type {Array}\n   */\n  recentlyUsedEmojis: {\n    type: Array,\n    default: () => [],\n  },\n});\n\nconst emits = defineEmits([\n  /**\n   * Emitted when the user hover over an emoji\n   * @event highlighted-emoji\n   * @param {Object} emoji - The emoji data that was hovered\n    */\n  'highlighted-emoji',\n\n  /**\n   * Emitted when the user select an emoji\n   * @event selected-emoji\n   * @param {Object} emoji - The emoji data that was selected\n    */\n  'selected-emoji',\n\n  /**\n   * Emitted when the user scroll into an emoji tab\n   * @event scroll-into-tab\n   * @param {Number} tab-index - The tab that was scrolled into\n    */\n  'scroll-into-tab',\n\n  /**\n   * Emitted when the user reach the end of the emoji list\n   * @event focus-skin-selector\n    */\n  'focus-skin-selector',\n\n  /**\n   * Emitted when the user shift tab in first tab of emoji selector\n   * @event focus-search-input\n    */\n  'focus-search-input',\n]);\n\nconst {\n  emojiFilteredRefs,\n  isFiltering,\n  hoverFirstEmoji,\n  setEmojiRef,\n  setFilteredRef,\n  focusEmoji,\n  handleArrowNavigationFiltered,\n  handleArrowNavigation,\n} = useKeyboardNavigation();\n\n/**\n * The ref for the tab category\n * This is used to display the fixed label\n */\nconst tabCategoryRef = ref(null);\n\n/**\n * The ref for the list\n * This is used to display the tabs\n */\nconst listRef = ref(null);\n\n/**\n * The ref for the tab label observer\n * This is used to update the fixed label\n */\nconst tabLabelObserver = ref(null);\n\n/**\n * The list of tabs\n * This is used to display the tabs\n */\nconst TABS_DATA = ['Recently used', 'People', 'Nature', 'Food', 'Activity', 'Travel', 'Objects', 'Symbols', 'Flags'];\n\n/**\n * The list of tab labels\n * This is used to display the tabs\n * This is a computed property because it will check if the recently used emojis list is empty\n * If it is empty, it will remove the recently used tab\n */\nconst tabLabels = computed(() => {\n  return props.recentlyUsedEmojis.length\n    ? props.tabsetLabels.map((label) => ({ label, ref: ref(null) }))\n    : props.tabsetLabels.slice(1).map((label) => ({ label, ref: ref(null) }));\n});\n\n/**\n * The label of the fixed tab\n * This is used to display the fixed label\n */\nconst fixedLabel = ref(tabLabels.value[0].label);\n\n/**\n * The list of tabs\n * This is used to display the tabs\n * This is a computed property because it will check if the recently used emojis list is empty\n * If it is empty, it will remove the recently used tab\n * The difference between this and the tab labels is that this one will set the structure of tabs\n * and the tab labels will set the labels\n */\nconst tabs = computed(() => {\n  return props.recentlyUsedEmojis.length ? TABS_DATA : TABS_DATA.slice(1);\n});\n\n/**\n * The list of current emojis that match the filter\n * This will be updated when the emojiFilter changes\n * This is used to display the search results\n * The difference between this and the current emojis list is that this one will not have the skin tone applied\n */\nconst filteredEmojis = ref([]);\n\n/**\n * The current emojis list we are displaying\n * This will be updated when the skin tone changes\n * The difference between this and the emojis list is that this one will have only the skin tone applied\n */\nconst currentEmojis = computed(() => {\n  return [\n    ...emojis[`People${props.skinTone}`],\n    ...emojis.Nature,\n    ...emojis.Food,\n    ...emojis[`Activity${props.skinTone}`],\n    ...emojis.Travel,\n    ...emojis[`Objects${props.skinTone}`],\n    ...emojis.Symbols,\n    ...emojis.Flags,\n  ];\n});\n\n/**\n * This will trigger the searchByNameAndKeywords function with debounce of 300 milliseconds\n */\nconst debouncedSearch = debounce(() => {\n  // We clean the emojiFilteredRefs to have an updated ref list for the search results\n  emojiFilteredRefs.value = [];\n  searchByNameAndKeywords();\n});\n\n/**\n * Update the current emojis list on skin tone changes\n * Also update the filtered emojis list\n * @listens skinTone\n */\nwatch(currentEmojis, () => {\n  searchByNameAndKeywords();\n}, { immediate: true });\n\n/**\n * Update the recently used emojis list on recently used emojis prop changes\n * @listens recentlyUsedEmojis\n */\nwatch(() => props.recentlyUsedEmojis,\n  () => {\n    emojis['Recently used'] = props.recentlyUsedEmojis;\n  }, { immediate: true });\n\n/**\n * Search for emojis by name and keywords\n * Will update the filtered emojis list on emojiFilter update\n * @listens emojiFilter\n */\nwatch(() => props.emojiFilter, () => {\n  resetScroll();\n  if (props.emojiFilter) {\n    isFiltering.value = true;\n  } else {\n    isFiltering.value = false;\n    // If the emoji filter is empty, emit null to remove the highlighted emoji\n    // of the previous search\n    highlightEmoji(null);\n  }\n  debouncedSearch();\n});\n\nwatch(\n  () => props.selectedTabset,\n  (tab) => {\n    scrollToTab(tab.tabId);\n  },\n  { deep: true },\n);\n\nfunction hoverEmoji (emoji, isFirst = false) {\n  hoverFirstEmoji.value = isFirst;\n  emits('highlighted-emoji', emoji);\n}\n\n/**\n * Filters an array of emoji objects based on a search string that matches both the name and keywords.\n * Will update the filtered emojis list\n */\nfunction searchByNameAndKeywords () {\n  const searchStr = props.emojiFilter.toLowerCase();\n  filteredEmojis.value = currentEmojis.value.filter(obj => {\n    const nameIncludesSearchStr = obj.name.toLowerCase().includes(searchStr);\n    const keywordsIncludeSearchStr = obj.keywords.some(keyword => keyword.toLowerCase().includes(searchStr));\n    return nameIncludesSearchStr || keywordsIncludeSearchStr;\n  });\n  nextTick(() => {\n    if (searchStr) {\n      hoverEmoji(filteredEmojis.value[0], true);\n    }\n  });\n}\n\nfunction debounce (fn, delay = 300) {\n  let timeout;\n\n  return (...args) => {\n    clearTimeout(timeout);\n    timeout = setTimeout(() => fn(...args), delay);\n  };\n}\n\nfunction getImgSrc (emoji) {\n  return `${CDN_URL + emoji}.png`;\n}\n\n/**\n * Handle image error - We hide the entire button if the image is not found\n */\nfunction handleImageError (event) {\n  event.target.parentNode.style.display = 'none';\n}\n\n/**\n * Scroll to the selected tab\n */\nfunction scrollToTab (tabIndex, focusFirstEmoji = true) {\n  const tabLabel = tabLabels.value[tabIndex - 1];\n  const tabElement = tabLabel.ref.value[0];\n\n  nextTick(() => {\n    const container = listRef.value;\n    const offsetTop = tabIndex === 1 ? 0 : tabElement.offsetTop - 15;\n\n    container.scrollTop = offsetTop;\n\n    if (focusFirstEmoji) {\n      focusEmoji((tabIndex - 1), 0);\n    }\n  });\n}\n\nfunction resetScroll () {\n  const container = listRef.value;\n\n  container.scrollTop = 0;\n}\n\n/**\n * This code creates an IntersectionObserver object that monitors the intersection between\n * the root element (tabCategoryRef) and its targets (the child elements of listRef),\n * and updates the value of the fixedLabel variable accordingly.\n */\nfunction setTabLabelObserver () {\n  /**\n   * The code extracts the target element and its index from the IntersectionObserverEntry object,\n   * and checks whether the target intersects with the root and is positioned above or below it.\n   */\n  tabLabelObserver.value = new IntersectionObserver(async (entries) => {\n    // eslint-disable-next-line complexity\n    entries.forEach(entry => {\n      const { target } = entry;\n      const index = parseInt(target.dataset.index);\n\n      /**\n       * If the target is positioned above the root,\n       * the code updates the value of the fixed label to the label of the previous tab,\n       * or the first tab if the current tab is the first one. If the target is positioned below the root, the code\n       * updates the value of the fixed label to the label of the current tab.\n       * If the target stops intersecting with the root and its index is 1 (the second tab),\n       * the code updates the value of the fixed label to the label of the first tab.\n       * NOTES:\n       * This last condition is needed because sometimes it is\n       * not detect the intersection between the root and the target.\n       * We also provide a 50 pixels offset to the root element in the first condition to always get the\n       * first tab if it has fewer emojis, because in some cases if you quickly scroll the observer does not detect it.\n       */\n      if (entry.isIntersecting && target.offsetTop <= tabCategoryRef.value.offsetTop + 50) {\n        fixedLabel.value = tabLabels.value[index - 1]?.label ?? tabLabels.value[0]?.label;\n        emits('scroll-into-tab', index - 1);\n      } else if (entry.boundingClientRect.bottom <= tabCategoryRef.value?.getBoundingClientRect().bottom) {\n        emits('scroll-into-tab', index);\n        fixedLabel.value = tabLabels.value[index]?.label;\n      } else if (index === 1) {\n        emits('scroll-into-tab', index);\n        fixedLabel.value = tabLabels.value[0]?.label;\n      }\n    });\n  });\n\n  /**\n   * The tabLabelObserver is set to observe the root element and all its children elements with\n   * the IntersectionObserver object, and sets their data-index attribute to their index.\n   */\n  tabLabelObserver.value.observe(tabCategoryRef.value);\n\n  Array.from(listRef.value.children).forEach((child, index) => {\n    tabLabelObserver.value.observe(child);\n    child.dataset.index = index;\n  });\n}\n\nconst handleKeyDownFilteredEmojis = (event, indexEmoji, emoji) => {\n  event.preventDefault();\n\n  if (Object.values(ARROW_KEYS).includes(event.key)) {\n    handleArrowNavigationFiltered(event.key, indexEmoji);\n    return;\n  }\n\n  switch (event.key) {\n    case 'Tab':\n      emits('focus-skin-selector');\n      break;\n    case 'Enter':\n      selectEmoji(emoji, event);\n      break;\n    default:\n      break;\n  }\n};\n\n/* eslint-disable-next-line complexity */\nconst handleKeyDown = (event, indexTab, indexEmoji, emoji) => {\n  event.preventDefault();\n\n  if (Object.values(ARROW_KEYS).includes(event.key)) {\n    handleArrowNavigation(event.key, indexTab, indexEmoji);\n    return;\n  }\n\n  switch (event.key) {\n    case 'Tab':\n      if (event.shiftKey) {\n        if (focusEmoji(indexTab, 0) && indexTab > 0) {\n          scrollToTab(indexTab, true);\n        } else {\n          scrollToTab(1, false);\n          emits('focus-search-input');\n        }\n      } else {\n        if (focusEmoji(indexTab + 1, 0)) {\n          scrollToTab(indexTab + 1 + 1, false);\n        } else {\n          // We are on the last emoji tabset, jump to the skin selector\n          emits('focus-skin-selector');\n        }\n      }\n      break;\n\n    case 'Enter':\n      selectEmoji(emoji, event);\n      break;\n\n    default:\n      break;\n  }\n};\n\nfunction selectEmoji (emoji, event) {\n  emits('selected-emoji', { ...emoji, shift_key: event.shiftKey });\n}\n\nfunction highlightEmoji (emoji) {\n  emits('highlighted-emoji', emoji);\n}\n\nfunction focusEmojiSelector () {\n  focusEmoji(0, 0);\n}\n\nfunction focusLastEmoji () {\n  scrollToTab(tabs.value.length, true);\n}\n\nonMounted(() => {\n  setTabLabelObserver();\n});\n\nonUnmounted(() => {\n  tabLabelObserver.value.disconnect();\n});\n\ndefineExpose({\n  focusEmojiSelector,\n  focusLastEmoji,\n});\n</script>\n"],"names":["useKeyboardNavigation","ref","computed","emojis","watch","nextTick","CDN_URL","ARROW_KEYS","onMounted","onUnmounted"],"mappings":"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"}