{"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=\"`tabLabelRef-${indexTab}`\"\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=\"`emojiRef-${indexTab}`\"\n            type=\"button\"\n            :aria-label=\"emoji.name\"\n            @click=\"event => handleEmojiSelection(emoji, event)\"\n            @focusin=\"$emit('highlighted-emoji', emoji)\"\n            @focusout=\"$emit('highlighted-emoji', null)\"\n            @mouseover=\"$emit('highlighted-emoji', emoji)\"\n            @mouseleave=\"$emit('highlighted-emoji', 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=\"`filteredEmoji-${index}`\"\n            type=\"button\"\n            :aria-label=\"emoji.name\"\n            :class=\"{\n              'hover-emoji': (index === 0 && hoverFirstEmoji),\n            }\"\n            @click=\"event => handleEmojiSelection(emoji, event)\"\n            @focusin=\"$emit('highlighted-emoji', emoji)\"\n            @focusout=\"$emit('highlighted-emoji', 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>\n/* eslint-disable max-len */\n/* eslint-disable max-lines */\nimport { emojisGrouped as emojisImported } from '@dialpad/dialtone-emojis';\nimport { CDN_URL, EMOJIS_PER_ROW } from '@/components/emoji_picker/emoji_picker_constants';\n\nexport default {\n  name: 'EmojiSelector',\n\n  props: {\n    emojiFilter: {\n      type: String,\n      default: '',\n    },\n\n    skinTone: {\n      type: String,\n      required: true,\n    },\n\n    tabSetLabels: {\n      type: Array,\n      required: true,\n    },\n\n    selectedTabset: {\n      type: Object,\n      required: true,\n    },\n\n    searchResultsLabel: {\n      type: String,\n      required: true,\n    },\n\n    searchNoResultsLabel: {\n      type: String,\n      required: true,\n    },\n\n    recentlyUsedEmojis: {\n      type: Array,\n      default: () => [],\n    },\n  },\n\n  data () {\n    return {\n      tabLabelsRefs: [],\n      emojiRefs: [],\n      emojiFilteredRefs: [],\n      isFiltering: false,\n      hoverFirstEmoji: true,\n      fixedLabel: '',\n      filteredEmojis: [],\n      TABS_DATA: ['Recently used', 'People', 'Nature', 'Food', 'Activity', 'Travel', 'Objects', 'Symbols', 'Flags'],\n      tabLabelObserver: null,\n    };\n  },\n\n  computed: {\n    /* eslint-disable-next-line complexity */\n    currentEmojis () {\n      return [\n        ...this.emojis[`People${this.skinTone}`] || [],\n        ...this.emojis.Nature || [],\n        ...this.emojis.Food || [],\n        ...this.emojis[`Activity${this.skinTone}`] || [],\n        ...this.emojis.Travel || [],\n        ...this.emojis[`Objects${this.skinTone}`] || [],\n        ...this.emojis.Symbols || [],\n        ...this.emojis.Flags || [],\n      ];\n    },\n\n    emojis () {\n      return emojisImported;\n    },\n\n    CDN_URL () {\n      return CDN_URL;\n    },\n\n    tabLabels () {\n      return this.recentlyUsedEmojis.length\n        ? this.tabSetLabels.map((label) => ({ label }))\n        : this.tabSetLabels.slice(1).map((label) => ({ label }));\n    },\n\n    tabs () {\n      return this.recentlyUsedEmojis.length ? this.TABS_DATA : this.TABS_DATA.slice(1);\n    },\n  },\n\n  watch: {\n    currentEmojis: {\n      handler () {\n        this.searchByNameAndKeywords();\n      },\n\n      immediate: true,\n    },\n\n    recentlyUsedEmojis: {\n      handler (newValue) {\n        this.emojis['Recently used'] = newValue;\n      },\n\n      immediate: true,\n    },\n\n    emojiFilter: {\n      handler (newFilter) {\n        this.resetScroll();\n        if (newFilter) {\n          this.isFiltering = true;\n        } else {\n          this.isFiltering = false;\n          this.$emit('highlighted-emoji', null);\n        }\n\n        this.debouncedSearch();\n      },\n    },\n\n    selectedTabset: {\n      handler (newValue) {\n        this.scrollToTab(newValue.tabId);\n      },\n\n      deep: true,\n    },\n  },\n\n  created () {\n    this.debouncedSearch = this.debounce(this.searchByNameAndKeywords, 300);\n  },\n\n  mounted () {\n    this.$nextTick(() => {\n      this.setupEmojiRefs();\n      this.setupFilteredRefs();\n      this.setupTabLabelRefs();\n      this.setTabLabelObserver();\n    });\n  },\n\n  beforeDestroy () {\n    if (this.tabLabelObserver) {\n      this.tabLabelObserver.disconnect();\n    }\n  },\n\n  methods: {\n    setupTabLabelRefs () {\n      this.tabSetLabels?.forEach((_, index) => {\n        const refKey = `tabLabelRef-${index}`;\n        if (this.$refs[refKey]) {\n          this.$set(this.tabLabelsRefs, index, { ref: this.$refs[refKey] });\n        }\n      });\n    },\n\n    setupFilteredRefs () {\n      // it is necessary to clean the array before setting the new refs\n      this.emojiFilteredRefs = [];\n\n      this.filteredEmojis.forEach((emoji, index) => {\n        const refKey = `filteredEmoji-${index}`;\n        if (this.$refs[refKey]) {\n          this.setFilteredRef(this.$refs[refKey], index);\n        }\n      });\n    },\n\n    setupEmojiRefs () {\n      for (let i = 0; i < this.tabs.length; i++) {\n        const refKey = `emojiRef-${i}`;\n        if (this.$refs[refKey]) {\n          this.$refs[refKey].forEach((el, indexEmoji) => {\n            if (el) {\n              this.setEmojiRef(el, i, indexEmoji);\n            }\n          });\n        }\n      }\n    },\n\n    searchByNameAndKeywords () {\n      const searchStr = this.emojiFilter.toLowerCase();\n      this.filteredEmojis = this.currentEmojis.filter(function (obj) {\n        const nameIncludesSearchStr = obj.name.toLowerCase().includes(searchStr);\n        const keywordsIncludeSearchStr = obj.keywords.some(function (keyword) {\n          return keyword.toLowerCase().includes(searchStr);\n        });\n        return nameIncludesSearchStr || keywordsIncludeSearchStr;\n      });\n      this.$nextTick(function () {\n        if (searchStr) {\n          this.hoverEmoji(this.filteredEmojis[0], true);\n          this.setupFilteredRefs();\n        }\n      });\n    },\n\n    debounce: function (fn, delay) {\n      if (delay === undefined) { delay = 300; }\n      let timeout;\n      return function () {\n        const args = []; let len = arguments.length;\n        while (len--) args[len] = arguments[len];\n\n        clearTimeout(timeout);\n        timeout = setTimeout(function () {\n          fn.apply(undefined, args);\n        }, delay);\n      };\n    },\n\n    getImgSrc: function (emoji) {\n      return this.CDN_URL + emoji + '.png';\n    },\n\n    handleImageError: function (event) {\n      event.target.parentNode.style.display = 'none';\n    },\n\n    scrollToTab: function (tabIndex, focusFirstEmoji) {\n      const vm = this;\n      if (focusFirstEmoji === undefined) { focusFirstEmoji = true; }\n      const tabElement = vm.tabLabelsRefs[tabIndex - 1].ref[0];\n\n      vm.$nextTick(function () {\n        const container = vm.$refs.listRef;\n        const offsetTop = tabIndex === 1 ? 0 : tabElement.offsetTop - 15;\n\n        container.scrollTop = offsetTop;\n\n        if (focusFirstEmoji) {\n          vm.focusEmoji(tabIndex - 1, 0);\n        }\n      });\n    },\n\n    resetScroll: function () {\n      const container = this.$refs.listRef;\n      container.scrollTop = 0;\n    },\n\n    focusEmojiSelector: function () {\n      this.focusEmoji(0, 0);\n    },\n\n    hoverEmoji (emoji, isFirst) {\n      if (isFirst === undefined) { isFirst = false; }\n      this.hoverFirstEmoji = isFirst;\n      this.$emit('highlighted-emoji', emoji);\n    },\n\n    setEmojiRef: function (el, indexTab, indexEmoji) {\n      if (!this.emojiRefs[indexTab]) {\n        this.$set(this.emojiRefs, indexTab, []);\n      }\n      this.$set(this.emojiRefs[indexTab], indexEmoji, el);\n    },\n\n    setFilteredRef: function (el, index) {\n      this.$set(this.emojiFilteredRefs, index, el);\n    },\n\n    focusEmoji: function (indexTab, indexEmoji) {\n      // eslint-disable-next-line max-len\n      const emojiRef = this.isFiltering ? this.emojiFilteredRefs[indexEmoji]?.[0] : this.emojiRefs[indexTab] && this.emojiRefs[indexTab][indexEmoji];\n      if (emojiRef) {\n        emojiRef.focus();\n        return true;\n      }\n\n      return false;\n    },\n\n    // eslint-disable-next-line complexity\n    handleKeyDown: function (event, indexTab, indexEmoji, emoji) {\n      event.preventDefault();\n\n      if (event.key === 'ArrowUp') {\n        const position = indexEmoji % EMOJIS_PER_ROW;\n\n        if (indexTab === 0) {\n          // we are on the first emoji tab, then we should jump to the last row of the last emoji tab\n          const numberOfMissingEmojis =\n        EMOJIS_PER_ROW - (this.emojiRefs[this.emojiRefs.length - 1].length % EMOJIS_PER_ROW);\n\n          const emojiToJump =\n        this.emojiRefs[this.emojiRefs.length - 1].length + numberOfMissingEmojis - (EMOJIS_PER_ROW - position);\n\n          if (!this.focusEmoji(this.emojiRefs.length - 1, emojiToJump)) {\n            // if there is no emoji in this position, jump to the last emoji of the row\n            this.focusEmoji(this.emojiRefs.length - 1, this.emojiRefs[this.emojiRefs.length - 1].length - 1);\n          }\n          return;\n        }\n\n        // if we are not on the first tab, we should jump to the previous row of the current tab\n        if (!this.focusEmoji(indexTab, indexEmoji - EMOJIS_PER_ROW)) {\n          // if there is no previous row, we should jump to emoji in the sampe position of the previous tab\n          const previousTab = indexTab - 1 < 0 ? 0 : indexTab - 1;\n          const emojisInPreviousTab = this.emojiRefs[previousTab].length;\n          const lastEmojiPosition = emojisInPreviousTab - (emojisInPreviousTab % EMOJIS_PER_ROW) + position;\n\n          if (!this.focusEmoji(previousTab, lastEmojiPosition)) {\n            // if there is no emoji in this position, jump to the last emoji of the row\n            this.focusEmoji(indexTab - 1, this.emojiRefs[indexTab - 1].length - 1);\n          }\n        }\n      }\n\n      if (event.key === 'ArrowDown') {\n        if (!this.focusEmoji(indexTab, indexEmoji + EMOJIS_PER_ROW)) {\n          // if cannot go down\n\n          // Calculate position from cell 0 to cell 8\n          const position = indexEmoji % EMOJIS_PER_ROW;\n\n          // check if it exists a next row in the current tab\n          if (this.emojiRefs?.[indexTab]?.[indexEmoji + (EMOJIS_PER_ROW - position)]) {\n            // if it exists, we should focus the last emoji of the next row in the current tab\n            this.focusEmoji(indexTab, this.emojiRefs[indexTab].length - 1);\n            // if we are at the end of the list it will do nothing\n          } else {\n            // We don't have next row, we are in the last of the tab, then jump\n            // to the next tab but in the equal emoji position in row 0.\n\n            if (!this.focusEmoji(indexTab + 1, position)) {\n              // We are on the bottom!, should jump to the same position emoji in the first row of the first tabset\n              // if it doesn't has, jump to the last\n              if (!this.focusEmoji(0, position)) {\n                this.focusEmoji(0, this.emojiRefs[0].length - 1);\n              }\n            }\n          }\n        }\n      }\n\n      if (event.key === 'ArrowLeft') {\n        this.handleHorizontalNavigation('left', indexTab, indexEmoji);\n      }\n\n      if (event.key === 'ArrowRight') {\n        this.handleHorizontalNavigation('right', indexTab, indexEmoji);\n      }\n\n      if (event.key === 'Tab' && !event.shiftKey) {\n        if (this.focusEmoji(indexTab + 1, 0)) {\n          this.scrollToTab((indexTab + 1) + 1, false);\n        } else {\n          // We are on the last emoji tabset, jump to the skin selector\n          this.$emit('focus-skin-selector');\n        }\n      }\n\n      if (event.key === 'Tab' && event.shiftKey) {\n        if (this.focusEmoji(indexTab, 0) && indexTab > 0) {\n          this.scrollToTab(indexTab, true);\n        } else {\n          this.scrollToTab(1, false);\n          this.$emit('focus-search-input');\n        }\n      }\n\n      if (event.key === 'Enter') {\n        this.handleEmojiSelection(emoji, event);\n      }\n    },\n\n    /* eslint-disable-next-line complexity */\n    handleHorizontalNavigation: function (direction, indexTab, indexEmoji) {\n      if (this.isFiltering) {\n        if (direction === 'left') {\n          this.handleArrowLeftFiltered(indexTab, indexEmoji);\n        } else if (direction === 'right') {\n          this.handleArrowRightFiltered(indexTab, indexEmoji);\n        }\n      } else {\n        if (direction === 'left') {\n          this.handleArrowLeft(indexTab, indexEmoji);\n        } else if (direction === 'right') {\n          this.handleArrowRight(indexTab, indexEmoji);\n        }\n      }\n    },\n\n    handleArrowLeftFiltered: function (indexTab, indexEmoji) {\n      if (!this.focusEmoji(0, indexEmoji - 1)) {\n        this.focusEmoji(0, this.emojiFilteredRefs.length - 1);\n      }\n    },\n\n    handleArrowRightFiltered: function (indexTab, indexEmoji) {\n      if (!this.focusEmoji(0, indexEmoji + 1)) {\n        this.focusEmoji(0, 0);\n      }\n    },\n\n    handleArrowLeft: function (indexTab, indexEmoji) {\n      if (!this.focusEmoji(indexTab, indexEmoji - 1)) {\n        if (this.emojiRefs[indexTab - 1]) {\n          this.focusEmoji(indexTab - 1, this.emojiRefs[indexTab - 1].length - 1);\n        } else {\n          this.focusEmoji(this.emojiRefs.length - 1, this.emojiRefs[this.emojiRefs.length - 1].length - 1);\n        }\n      }\n    },\n\n    handleArrowRight: function (indexTab, indexEmoji) {\n      if (!this.focusEmoji(indexTab, indexEmoji + 1)) {\n        if (!this.focusEmoji(indexTab + 1, 0)) {\n          this.focusEmoji(0, 0);\n        }\n      }\n    },\n\n    handleEmojiSelection (emoji, event) {\n      this.$emit('selected-emoji', { ...emoji, shift_key: event.shiftKey });\n    },\n\n    /* eslint-disable-next-line complexity */\n    handleKeyDownFilteredEmojis (event, indexEmoji, emoji) {\n      event.preventDefault();\n      this.hoverFirstEmoji = false;\n\n      if (event.key === 'ArrowUp') {\n        const position = indexEmoji % EMOJIS_PER_ROW;\n        if (!this.focusEmoji(0, indexEmoji - EMOJIS_PER_ROW)) {\n          const lastEmojiPosition =\n          this.emojiFilteredRefs.length - (this.emojiFilteredRefs.length % EMOJIS_PER_ROW) + position;\n\n          this.focusEmoji(0, lastEmojiPosition);\n\n          if (!this.focusEmoji(0, lastEmojiPosition)) {\n            this.focusEmoji(0, this.emojiFilteredRefs.length - 1);\n          }\n        }\n      }\n\n      if (event.key === 'ArrowDown') {\n        if (!this.focusEmoji(0, indexEmoji + EMOJIS_PER_ROW)) {\n          const position = indexEmoji % EMOJIS_PER_ROW;\n\n          if (this.emojiFilteredRefs?.[indexEmoji + (EMOJIS_PER_ROW - position)]) {\n            this.focusEmoji(0, this.emojiFilteredRefs.length - 1);\n          } else {\n            this.focusEmoji(0, position);\n          }\n        }\n      }\n\n      if (event.key === 'ArrowLeft') {\n        this.handleHorizontalNavigation('left', 0, indexEmoji);\n      }\n\n      if (event.key === 'ArrowRight') {\n        this.handleHorizontalNavigation('right', 0, indexEmoji);\n      }\n\n      if (event.key === 'Tab') {\n        this.$emit('focus-skin-selector');\n      }\n\n      if (event.key === 'Enter') {\n        this.handleEmojiSelection(emoji, event);\n      }\n    },\n\n    setTabLabelObserver () {\n      this.tabLabelObserver = new IntersectionObserver(entries => {\n        /* eslint-disable-next-line complexity */\n        entries.forEach(entry => {\n          const { target } = entry;\n          const index = parseInt(target.dataset.index);\n\n          if (entry.isIntersecting && target.offsetTop <= this.$refs.tabCategoryRef?.offsetTop + 50) {\n            this.fixedLabel = this.tabLabels[index - 1]?.label ?? this.tabLabels[0]?.label;\n            this.$emit('scroll-into-tab', index - 1);\n          } else if (entry.boundingClientRect.bottom <= this.$refs.tabCategoryRef?.getBoundingClientRect().bottom) {\n            this.$emit('scroll-into-tab', index);\n            this.fixedLabel = this.tabLabels[index]?.label;\n          } else if (index === 1) {\n            this.$emit('scroll-into-tab', index);\n            this.fixedLabel = this.tabLabels[0]?.label;\n          }\n        });\n      });\n\n      this.tabLabelObserver.observe(this.$refs.tabCategoryRef);\n\n      Array.from(this.$refs.listRef.children).forEach((child, index) => {\n        this.tabLabelObserver.observe(child);\n        child.dataset.index = index;\n      });\n    },\n\n    focusLastEmoji () {\n      this.scrollToTab(this.tabs.length, true);\n    },\n\n  },\n\n};\n</script>\n"],"names":["emojisImported","CDN_URL","EMOJIS_PER_ROW"],"mappings":"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"}