@dialpad/dialtone 9.54.0 → 9.54.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/dialtone.css +6 -6
- package/dist/css/dialtone.min.css +1 -1
- package/dist/tokens/css/variables-dark.css +1 -1
- package/dist/tokens/css/variables-expressive-dark.css +1 -1
- package/dist/tokens/css/variables-expressive-light.css +1 -1
- package/dist/tokens/css/variables-expressive-sm-dark.css +1 -1
- package/dist/tokens/css/variables-expressive-sm-light.css +1 -1
- package/dist/tokens/css/variables-light.css +1 -1
- package/dist/tokens/css/variables-tmo-dark.css +1 -1
- package/dist/tokens/css/variables-tmo-light.css +1 -1
- package/dist/tokens/less/variables-dark.less +1 -1
- package/dist/tokens/less/variables-expressive-dark.less +1 -1
- package/dist/tokens/less/variables-expressive-light.less +1 -1
- package/dist/tokens/less/variables-expressive-sm-dark.less +1 -1
- package/dist/tokens/less/variables-expressive-sm-light.less +1 -1
- package/dist/tokens/less/variables-light.less +1 -1
- package/dist/tokens/less/variables-tmo-dark.less +1 -1
- package/dist/tokens/less/variables-tmo-light.less +1 -1
- package/dist/vue2/component-documentation.json +1 -1
- package/dist/vue2/lib/emoji-picker.cjs +11 -21
- package/dist/vue2/lib/emoji-picker.cjs.map +1 -1
- package/dist/vue2/lib/emoji-picker.js +11 -21
- package/dist/vue2/lib/emoji-picker.js.map +1 -1
- package/dist/vue2/lib/tooltip.cjs +1 -1
- package/dist/vue2/lib/tooltip.cjs.map +1 -1
- package/dist/vue2/lib/tooltip.js +1 -1
- package/dist/vue2/lib/tooltip.js.map +1 -1
- package/dist/vue2/types/components/tooltip/tooltip.vue.d.ts +2 -2
- package/dist/vue3/component-documentation.json +1 -1
- package/dist/vue3/lib/emoji-picker.cjs +27 -49
- package/dist/vue3/lib/emoji-picker.cjs.map +1 -1
- package/dist/vue3/lib/emoji-picker.js +27 -49
- package/dist/vue3/lib/emoji-picker.js.map +1 -1
- package/dist/vue3/lib/tooltip.cjs +1 -1
- package/dist/vue3/lib/tooltip.cjs.map +1 -1
- package/dist/vue3/lib/tooltip.js +1 -1
- package/dist/vue3/lib/tooltip.js.map +1 -1
- package/dist/vue3/types/components/emoji_picker/modules/emoji_selector.vue.d.ts +1 -1
- package/dist/vue3/types/components/emoji_picker/modules/emoji_tabset.vue.d.ts +1 -1
- package/dist/vue3/types/components/emoji_picker/modules/emoji_tabset.vue.d.ts.map +1 -1
- package/dist/vue3/types/components/tooltip/tooltip.vue.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji-picker.js","sources":["../../components/emoji_picker/modules/emoji_search.vue","../../components/emoji_picker/modules/emoji_tabset.vue","../../components/emoji_picker/emoji_picker_constants.js","../../components/emoji_picker/composables/useKeyboardNavigation.js","../../components/emoji_picker/modules/emoji_selector.vue","../../components/emoji_picker/modules/emoji_skin_selector.vue","../../components/emoji_picker/emoji_picker.vue"],"sourcesContent":["<template>\n <div class=\"d-emoji-picker__search d-emoji-picker__alignment\">\n <dt-input\n id=\"searchInput\"\n ref=\"searchInput\"\n :placeholder=\"searchPlaceholderLabel\"\n :model-value=\"modelValue\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n @keydown.up=\"$emit('focus-tabset')\"\n @keydown.down.prevent=\"$emit('focus-emoji-selector')\"\n @keydown.enter=\"$emit('select-first-emoji')\"\n >\n <template #leftIcon>\n <dt-icon\n name=\"search\"\n size=\"200\"\n />\n </template>\n <template\n v-if=\"modelValue.length > 0\"\n #rightIcon\n >\n <dt-button\n importance=\"clear\"\n kind=\"muted\"\n @click=\"clearSearch\"\n >\n <template #icon>\n <dt-icon\n name=\"x-circle\"\n size=\"200\"\n />\n </template>\n </dt-button>\n </template>\n </dt-input>\n </div>\n</template>\n\n<script setup>\nimport { DtInput } from '@/components/input';\nimport { DtIcon } from '@/components/icon';\nimport { DtButton } from '@/components/button';\nimport { onMounted, ref } from 'vue';\n\ndefineProps({\n searchPlaceholderLabel: {\n type: String,\n required: true,\n },\n modelValue: {\n type: String,\n default: '',\n },\n});\n\nconst emits = defineEmits(['update:modelValue', 'focus-emoji-selector', 'focus-tabset', 'select-first-emoji']);\n\nconst searchInput = ref(null);\n\nfunction clearSearch () {\n emits('update:modelValue', '');\n focusSearchInput();\n}\n\nfunction focusSearchInput () {\n searchInput.value.focus();\n}\nonMounted(() => {\n focusSearchInput();\n});\n\ndefineExpose({\n focusSearchInput,\n});\n</script>\n","<template>\n <div class=\"d-emoji-picker__tabset\">\n <dt-tab-group\n tab-list-class=\"d-emoji-picker__tabset-list\"\n :selected=\"selectedTab\"\n >\n <template #tabs>\n <dt-tab\n v-for=\"(tab, index) in tabs\"\n :id=\"tab.id\"\n :ref=\"el => { if (el) setTabsetRef(el) }\"\n :key=\"tab.id\"\n :panel-id=\"tab.panelId\"\n :label=\"tab.label\"\n aria-controls=\"d-emoji-picker-list\"\n :tabindex=\"index + 1\"\n @click.capture.stop=\"selectTabset(tab.id)\"\n @keydown=\"handleKeyDown($event, tab.id)\"\n >\n <dt-icon\n size=\"400\"\n :name=\"tab.icon\"\n />\n </dt-tab>\n </template>\n </dt-tab-group>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref, toRefs, watch } from 'vue';\nimport { DtTab, DtTabGroup } from '@/components/tabs';\nimport { DtIcon } from '@/components/icon';\nimport { EMOJI_PICKER_CATEGORIES } from '@/components/emoji_picker';\n\nconst props = defineProps({\n /**\n * Whether to show the recently used tab or not\n * @type {Boolean}\n * @default false\n */\n showRecentlyUsedTab: {\n type: Boolean,\n default: false,\n },\n\n scrollIntoTab: {\n type: Number,\n required: true,\n },\n\n isScrolling: {\n type: Boolean,\n default: false,\n },\n\n emojiFilter: {\n type: String,\n default: '',\n },\n\n /**\n * The labels for the aria-label\n * @type {Array}\n * @required\n */\n tabsetLabels: {\n type: Array,\n required: true,\n },\n});\n\nconst emits = defineEmits([\n /**\n * Emitted when a tab is selected\n * @event selected-tabset\n * @param {String} tabId - The name of the tab that was selected\n */\n 'selected-tabset',\n\n 'shift-tab-key-pressed',\n 'tab-key-pressed',\n 'arrow-down-key-pressed',\n]);\n\nconst TABS_DATA = [\n { label: EMOJI_PICKER_CATEGORIES.MOST_RECENTLY_USED, icon: 'clock' },\n { label: EMOJI_PICKER_CATEGORIES.SMILEYS_AND_PEOPLE, icon: 'satisfied' },\n { label: EMOJI_PICKER_CATEGORIES.NATURE, icon: 'living-thing' },\n { label: EMOJI_PICKER_CATEGORIES.FOOD, icon: 'food' },\n { label: EMOJI_PICKER_CATEGORIES.ACTIVITY, icon: 'object' },\n { label: EMOJI_PICKER_CATEGORIES.TRAVEL, icon: 'transportation' },\n { label: EMOJI_PICKER_CATEGORIES.OBJECTS, icon: 'lightbulb' },\n { label: EMOJI_PICKER_CATEGORIES.SYMBOLS, icon: 'heart' },\n { label: EMOJI_PICKER_CATEGORIES.FLAGS, icon: 'flag' },\n];\n\nconst tabs = computed(() => {\n const tabsData = props.showRecentlyUsedTab ? TABS_DATA : TABS_DATA.slice(1);\n\n return tabsData.map((tab, index) => ({\n ...tab,\n label: props.tabsetLabels[index],\n id: (index + 1).toString(),\n panelId: (index + 1).toString(),\n }));\n});\n\nconst isSearching = computed(() => props.emojiFilter.length > 0);\n\nconst selectedTab = ref('1');\n\nconst { isScrolling } = toRefs(props);\n\nconst tabsetRef = ref([]);\n\nwatch(() => props.scrollIntoTab,\n () => {\n if (!isScrolling.value && !isSearching.value) {\n selectedTab.value = (props.scrollIntoTab + 1).toString();\n }\n });\n\nwatch(isSearching,\n () => {\n if (isSearching.value) {\n selectedTab.value = null;\n }\n });\n\n/**\n * We are using .capture.stop modifiers on the click event\n * because we don't want to trigger the click event of the\n * dt-tab component\n */\nfunction selectTabset (id) {\n if (!isScrolling.value) {\n selectedTab.value = id;\n }\n emits('selected-tabset', id);\n}\n\nfunction setTabsetRef (ref) {\n // We push the $el, because $el is the button inside the dt-tab component\n // and we need the button to focus it\n tabsetRef.value.push(ref.$el);\n}\n\nfunction focusTabset () {\n tabsetRef.value[0].focus();\n}\n\nfunction handleKeyDown (event, tabId) {\n if (event.key === 'Enter') {\n selectTabset(tabId);\n // We blur because seems like the tab component override the selected prop, and it removes the selected style\n tabsetRef.value[tabId - 1].blur();\n }\n\n if (event.key === 'Tab') {\n event.preventDefault();\n if (event.shiftKey) {\n emits('shift-tab-key-pressed');\n } else {\n emits('tab-key-pressed');\n }\n }\n\n if (event.key === 'ArrowDown') {\n // Jump to search input\n emits('arrow-down-key-pressed');\n }\n}\n\ndefineExpose({\n focusTabset,\n});\n</script>\n","export const ARROW_KEYS = {\n ARROW_UP: 'ArrowUp',\n ARROW_DOWN: 'ArrowDown',\n ARROW_LEFT: 'ArrowLeft',\n ARROW_RIGHT: 'ArrowRight',\n};\n\nexport const CDN_URL = 'https://static.dialpadcdn.com/joypixels/png/unicode/32/';\nexport const EMOJIS_PER_ROW = 9;\nexport const EMOJI_PICKER_SKIN_TONE_MODIFIERS = {\n DEFAULT: 'Default',\n LIGHT: 'Light',\n MEDIUM_LIGHT: 'MediumLight',\n MEDIUM: 'Medium',\n MEDIUM_DARK: 'MediumDark',\n DARK: 'Dark',\n};\n\nexport const EMOJI_PICKER_CATEGORIES = {\n MOST_RECENTLY_USED: 'Most recently used',\n SMILEYS_AND_PEOPLE: 'Smileys and people',\n NATURE: 'Nature',\n FOOD: 'Food',\n ACTIVITY: 'Activity',\n TRAVEL: 'Travel',\n OBJECTS: 'Objects',\n SYMBOLS: 'Symbols',\n FLAGS: 'Flags',\n};\n\nexport default {\n EMOJI_PICKER_SKIN_TONE_MODIFIERS,\n EMOJI_PICKER_CATEGORIES,\n};\n","import { ref } from 'vue';\nimport { EMOJIS_PER_ROW, ARROW_KEYS } from '@/components/emoji_picker/emoji_picker_constants';\n\nexport function useKeyboardNavigation () {\n const emojiRefs = ref([]);\n const emojiFilteredRefs = ref([]);\n const isFiltering = ref(false);\n const hoverFirstEmoji = ref(true);\n\n function _handleArrowLeft (indexTab, indexEmoji) {\n if (!focusEmoji(indexTab, indexEmoji - 1)) {\n if (emojiRefs.value[indexTab - 1]) {\n focusEmoji(indexTab - 1, emojiRefs.value[indexTab - 1].length - 1);\n } else {\n focusEmoji(emojiRefs.value.length - 1, emojiRefs.value[emojiRefs.value.length - 1].length - 1);\n }\n }\n }\n\n function _handleArrowRight (indexTab, indexEmoji) {\n if (!focusEmoji(indexTab, indexEmoji + 1)) {\n if (!focusEmoji(indexTab + 1, 0)) {\n focusEmoji(0, 0);\n }\n }\n }\n\n function _handleArrowLeftFiltered (indexTab, indexEmoji) {\n if (!focusEmoji(0, indexEmoji - 1)) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n }\n }\n\n function _handleArrowRightFiltered (indexTab, indexEmoji) {\n if (!focusEmoji(0, indexEmoji + 1)) {\n focusEmoji(0, 0);\n }\n }\n\n function _handleHorizontalNavigation (direction, indexTab, indexEmoji) {\n if (isFiltering.value) {\n if (direction === 'left') {\n _handleArrowLeftFiltered(indexTab, indexEmoji);\n } else if (direction === 'right') {\n _handleArrowRightFiltered(indexTab, indexEmoji);\n }\n } else {\n if (direction === 'left') {\n _handleArrowLeft(indexTab, indexEmoji);\n } else if (direction === 'right') {\n _handleArrowRight(indexTab, indexEmoji);\n }\n }\n }\n\n function focusEmoji (indexTab, indexEmoji) {\n const emojiRef = isFiltering.value\n ? emojiFilteredRefs.value?.[indexEmoji]\n : emojiRefs.value?.[indexTab]?.[indexEmoji];\n\n if (emojiRef) {\n emojiRef.focus();\n return true;\n }\n\n return false;\n }\n\n function setEmojiRef (el, indexTab, indexEmoji) {\n if (!emojiRefs.value[indexTab]) {\n emojiRefs.value[indexTab] = [];\n }\n emojiRefs.value[indexTab][indexEmoji] = el;\n }\n\n function setFilteredRef (el, index) {\n emojiFilteredRefs.value[index] = el;\n }\n\n function handleArrowNavigationFiltered (key, indexEmoji) {\n hoverFirstEmoji.value = false;\n\n if (key === ARROW_KEYS.ARROW_UP) {\n const position = indexEmoji % EMOJIS_PER_ROW;\n\n if (!focusEmoji(0, indexEmoji - EMOJIS_PER_ROW)) {\n const lastEmojiPosition =\n emojiFilteredRefs.value.length - (emojiFilteredRefs.value.length % EMOJIS_PER_ROW) + position;\n\n focusEmoji(0, lastEmojiPosition);\n\n if (!focusEmoji(0, lastEmojiPosition)) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n }\n }\n }\n\n if (key === ARROW_KEYS.ARROW_DOWN) {\n if (!focusEmoji(0, indexEmoji + EMOJIS_PER_ROW)) {\n const position = indexEmoji % EMOJIS_PER_ROW;\n\n if (emojiFilteredRefs.value?.[indexEmoji + (EMOJIS_PER_ROW - position)]) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n } else {\n focusEmoji(0, position);\n }\n }\n }\n\n if (key === ARROW_KEYS.ARROW_LEFT) {\n _handleHorizontalNavigation('left', 0, indexEmoji);\n }\n\n if (key === ARROW_KEYS.ARROW_RIGHT) {\n _handleHorizontalNavigation('right', 0, indexEmoji);\n }\n }\n\n function handleArrowNavigation (key, indexTab, indexEmoji) {\n if (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 - (emojiRefs.value[emojiRefs.value.length - 1].length % EMOJIS_PER_ROW);\n\n const emojiToJump =\n emojiRefs.value[emojiRefs.value.length - 1].length + numberOfMissingEmojis - (EMOJIS_PER_ROW - position);\n\n if (!focusEmoji(emojiRefs.value.length - 1, emojiToJump)) {\n // if there is no emoji in this position, jump to the last emoji of the row\n focusEmoji(emojiRefs.value.length - 1, emojiRefs.value[emojiRefs.value.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 (!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 = emojiRefs.value[previousTab].length;\n const lastEmojiPosition = emojisInPreviousTab - (emojisInPreviousTab % EMOJIS_PER_ROW) + position;\n\n if (!focusEmoji(previousTab, lastEmojiPosition)) {\n // if there is no emoji in this position, jump to the last emoji of the row\n focusEmoji(indexTab - 1, emojiRefs.value[indexTab - 1].length - 1);\n }\n }\n }\n\n if (key === 'ArrowDown') {\n if (!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 (emojiRefs.value?.[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 focusEmoji(indexTab, emojiRefs.value[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 (!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 (!focusEmoji(0, position)) {\n focusEmoji(0, emojiRefs.value[0].length - 1);\n }\n }\n }\n }\n }\n\n if (key === 'ArrowLeft') {\n _handleHorizontalNavigation('left', indexTab, indexEmoji);\n }\n\n if (key === 'ArrowRight') {\n _handleHorizontalNavigation('right', indexTab, indexEmoji);\n }\n }\n\n return {\n emojiFilteredRefs,\n isFiltering,\n hoverFirstEmoji,\n setEmojiRef,\n setFilteredRef,\n focusEmoji,\n handleArrowNavigationFiltered,\n handleArrowNavigation,\n };\n}\n","<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=\"selectEmoji(emoji)\"\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=\"selectEmoji(emoji)\"\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\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 scrollTo function starts scrolling and stops scrolling\n * @event is-scrolling\n * @param {Boolean} is-scrolling - Whether the user is scrolling with the scroll-to\n */\n 'is-scrolling',\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 shift-tab-key-pressed\n */\n 'shift-tab-key-pressed',\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 - 20;\n\n /**\n * This variable is used to check if the user is scrolling inside the emoji picker\n * This is used to check if the user is scrolling using the scrollTo function\n * This is useful because this flag will prevent to update the fixed label when the user is scrolling\n * using the scrollTo function\n */\n let isScrolling = true;\n\n let prevScrollTop = container.scrollTop;\n emits('is-scrolling', true);\n\n /**\n * This event listener checks whether the user is scrolling up or down by comparing the current scrollTop\n * to prevScrollTop. If the scrollToTab function is scrolling from bottom to top and has reached the desired\n * position (scrollTop <= offsetTop),or if the scrollToTab function is scrolling from top to bottom and has\n * passed the desired position(scrollTop >= offsetTop), then isScrolling is set to false.\n */\n container.addEventListener('scroll', () => {\n if (isScrolling) {\n const scrollTop = container.scrollTop;\n if (\n (prevScrollTop < scrollTop && scrollTop >= offsetTop) ||\n (prevScrollTop > scrollTop && scrollTop <= offsetTop)\n ) {\n isScrolling = false;\n emits('is-scrolling', false);\n }\n prevScrollTop = scrollTop;\n }\n });\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(entries => {\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);\n break;\n default:\n break;\n }\n};\n\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('shift-tab-key-pressed');\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);\n break;\n\n default:\n break;\n }\n};\n\nfunction selectEmoji (emoji) {\n emits('selected-emoji', emoji);\n}\n\nfunction highlightEmoji (emoji) {\n emits('highlighted-emoji', emoji);\n}\n\nfunction focusEmojiSelector () {\n focusEmoji(0, 0);\n}\n\nfunction focusLastEmoji () {\n focusEmoji(tabs.value.length - 1, 0);\n}\n\nonMounted(() => {\n setTabLabelObserver();\n});\n\nonUnmounted(() => {\n tabLabelObserver.value.disconnect();\n});\n\ndefineExpose({\n focusEmojiSelector,\n focusLastEmoji,\n});\n</script>\n","<template>\n <div data-qa=\"skin-selector\">\n <div\n v-show=\"isOpen\"\n class=\"d-emoji-picker__skin-list\"\n >\n <button\n v-for=\"(skin, index) in skinList\"\n :ref=\"el => { if (el) setSkinsRef(el) }\"\n :key=\"skin.name\"\n :class=\"{\n 'selected': skinSelected.skinCode === skin.skinCode,\n }\"\n @keydown=\"event => handleKeyDown(event, skin, index)\"\n @click=\"selectSkin(skin)\"\n >\n <img\n class=\"d-icon d-icon--size-500\"\n :alt=\"skin.name\"\n :aria-label=\"skin.name\"\n :title=\"skin.name\"\n :src=\"`${CDN_URL + skin.unicode_output}.png`\"\n >\n </button>\n </div>\n <div\n v-show=\"!isOpen\"\n class=\"d-emoji-picker__skin-selected\"\n >\n <dt-tooltip placement=\"top-end\">\n {{ skinSelectorButtonTooltipLabel }}\n <template #anchor>\n <button\n ref=\"skinSelectorRef\"\n :aria-label=\"skinSelectorButtonTooltipLabel\"\n tabindex=\"-1\"\n @click=\"toggleSkinList\"\n @keydown=\"event => handleKeyDown(event)\"\n >\n <img\n class=\"d-icon d-icon--size-500\"\n :alt=\"skinSelected.name\"\n :aria-label=\"skinSelected.name\"\n :title=\"skinSelected.name\"\n :src=\"`${CDN_URL + skinSelected.unicode_output}.png`\"\n >\n </button>\n </template>\n </dt-tooltip>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, nextTick, ref, watchEffect } from 'vue';\nimport { CDN_URL, EMOJI_PICKER_SKIN_TONE_MODIFIERS } from '@/components/emoji_picker';\nimport { DtTooltip } from '@/components/tooltip';\n\nconst props = defineProps({\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 isHovering: {\n type: Boolean,\n default: false,\n },\n\n skinSelectorButtonTooltipLabel: {\n type: String,\n required: true,\n },\n});\n\nconst emits = defineEmits([\n /**\n * The skin tone that was selected\n * @event skin-tone\n * @type {Number}\n */\n 'skin-tone',\n 'focus-tabset',\n 'focus-last-emoji',\n]);\n\nconst skinList = [\n {\n name: ':wave_tone1:',\n unicode_output: '1f44b-1f3fb',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.LIGHT,\n skinCode: '_tone1',\n },\n {\n name: ':wave_tone2:',\n unicode_output: '1f44b-1f3fc',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM_LIGHT,\n skinCode: '_tone2',\n },\n {\n name: ':wave_tone3:',\n unicode_output: '1f44b-1f3fd',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM,\n skinCode: '_tone3',\n },\n {\n name: ':wave_tone4:',\n unicode_output: '1f44b-1f3fe',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM_DARK,\n skinCode: '_tone4',\n },\n {\n name: ':wave_tone5:',\n unicode_output: '1f44b-1f3ff',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.DARK,\n skinCode: '_tone5',\n },\n {\n name: ':wave:',\n unicode_output: '1f44b',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.DEFAULT,\n skinCode: '',\n },\n];\n\nconst isOpen = ref(false);\n\nconst skinSelectorRef = ref(null);\n\nconst skinsRef = ref([]);\n\n/**\n * It will close the skin selector if the user is hovering over the emoji list\n */\nwatchEffect(\n () => props.isHovering && (isOpen.value = false),\n);\n\n/**\n * It will initially display props.skinTone. If a new skin tone is selected,\n * it will display that until props.skinTone changes.\n */\nconst skinPassedIn = computed(() => skinList.find((skin) => skin.skinTone === props.skinTone));\nconst skinSelected = ref(skinPassedIn.value);\nwatchEffect(() => skinPassedIn.value && (skinSelected.value = skinPassedIn.value));\n\nfunction setSkinsRef (ref) {\n skinsRef.value.push(ref);\n}\nfunction focusSkinSelector () {\n skinSelectorRef.value.focus();\n}\n\nfunction selectSkin (skin) {\n skinSelected.value = skin;\n isOpen.value = false;\n emits('skin-tone', skin.skinTone);\n nextTick(() => focusSkinSelector());\n}\n\nconst handleKeyDown = (event, skin, index) => {\n event.preventDefault();\n\n if (event.key === 'ArrowLeft') {\n if (index === 0) skinsRef.value[skinsRef.value.length - 1]?.focus();\n skinsRef.value[index - 1]?.focus();\n }\n\n if (event.key === 'ArrowRight') {\n skinsRef.value[index + 1]?.focus();\n }\n\n if (event.key === 'Enter') {\n if (skin) { selectSkin(skin); } else {\n toggleSkinList();\n }\n }\n\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n emits('focus-last-emoji');\n } else {\n emits('focus-tabset');\n }\n }\n};\n\nfunction toggleSkinList () {\n isOpen.value = !isOpen.value;\n nextTick(() => skinsRef.value[0].focus());\n}\n\ndefineExpose({\n focusSkinSelector,\n});\n</script>\n","<template>\n <div\n class=\"d-emoji-picker\"\n >\n <div class=\"d-emoji-picker--header\">\n <emoji-tabset\n ref=\"tabsetRef\"\n :emoji-filter=\"internalSearchQuery\"\n :show-recently-used-tab=\"showRecentlyUsedTab\"\n :scroll-into-tab=\"scrollIntoTab\"\n :tabset-labels=\"tabSetLabels\"\n :is-scrolling=\"isScrolling\"\n @tab-key-pressed=\"focusNextSectionFromEmojiTabSet\"\n @shift-tab-key-pressed=\"$refs.skinSelectorRef.focusSkinSelector()\"\n @arrow-down-key-pressed=\"focusNextSectionFromEmojiTabSet\"\n @selected-tabset=\"scrollToSelectedTabset\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n <div class=\"d-emoji-picker--body\">\n <emoji-search\n v-if=\"showSearch\"\n ref=\"searchInputRef\"\n v-model=\"internalSearchQuery\"\n :search-placeholder-label=\"searchPlaceholderLabel\"\n @select-first-emoji=\"emits('selected-emoji', highlightedEmoji)\"\n @focus-tabset=\"$refs.tabsetRef.focusTabset()\"\n @focus-emoji-selector=\"$refs.emojiSelectorRef.focusEmojiSelector()\"\n @keydown.esc=\"emits('close')\"\n />\n <emoji-selector\n ref=\"emojiSelectorRef\"\n :emoji-filter=\"internalSearchQuery\"\n :skin-tone=\"skinTone\"\n :tabset-labels=\"tabSetLabels\"\n :search-results-label=\"searchResultsLabel\"\n :search-no-results-label=\"searchNoResultsLabel\"\n :recently-used-emojis=\"recentlyUsedEmojis\"\n :selected-tabset=\"selectedTabset\"\n @scroll-into-tab=\"updateScrollIntoTab\"\n @is-scrolling=\"updateIsScrolling\"\n @highlighted-emoji=\"updateHighlightedEmoji\"\n @selected-emoji=\"emits('selected-emoji', $event)\"\n @focus-skin-selector=\"$refs.skinSelectorRef.focusSkinSelector()\"\n @shift-tab-key-pressed=\"focusNextSectionFromEmojiSelector\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n <div class=\"d-emoji-picker--footer\">\n <emoji-description :emoji=\"highlightedEmoji\" />\n <emoji-skin-selector\n ref=\"skinSelectorRef\"\n :is-hovering=\"!!highlightedEmoji\"\n :skin-selector-button-tooltip-label=\"skinSelectorButtonTooltipLabel\"\n :skin-tone=\"skinTone\"\n @skin-tone=\"emits('skin-tone', $event)\"\n @focus-tabset=\"$refs.tabsetRef.focusTabset()\"\n @focus-last-emoji=\"$refs.emojiSelectorRef.focusLastEmoji()\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n </div>\n</template>\n\n<script setup>\nimport EmojiSearch from './modules/emoji_search.vue';\nimport EmojiTabset from './modules/emoji_tabset.vue';\nimport EmojiSelector from './modules/emoji_selector.vue';\nimport EmojiSkinSelector from './modules/emoji_skin_selector.vue';\nimport EmojiDescription from './modules/emoji_description.vue';\nimport { computed, ref, watch } from 'vue';\n\nconst props = defineProps({\n /**\n * The array with recently used emoji object\n * This list is necessary to fill the recently used tab\n * @type {Array}\n * @default []\n * @example\n * <dt-emoji-picker :recentlyUsedEmojis=\"[emojiObject, emojiObject]\" />\n */\n // TODO try to simplify this to achieve an array of unicode characters and not an entire emoji data object\n recentlyUsedEmojis: {\n type: Array,\n default: () => ([]),\n },\n\n /**\n * The placeholder text for the search input\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchPlaceholderLabel=\"'Search...'\" />\n */\n searchPlaceholderLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The label for the search results tab\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchResultsLabel=\"'Search results'\" />\n */\n searchResultsLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The label for the search no results\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchNoResultsLabel=\"'No results'\" />\n */\n searchNoResultsLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The list of tabsets to show, it is necessary to be updated with the correct language\n * It must respect the provided order.\n * @type {Array}\n * @required\n * @example\n * <dt-emoji-picker\n * :tabSetLabels=\"['Most recently used', 'Smileys and people', 'Nature',\n * 'Food', 'Activity', 'Travel', 'Objects', 'Symbols', 'Flags']\" />\n */\n tabSetLabels: {\n type: Array,\n required: true,\n },\n\n /**\n * The skin tone to show the emojis\n * This prop gives the possibility to use the skin tone selected by the user previously\n * @type {String}\n * @default 'Default'\n * @values 'Default', 'Light', 'MediumLight', 'Medium', 'MediumDark', 'Dark'\n * @example\n * <dt-emoji-picker :skinTone=\"'Default'\" />\n */\n skinTone: {\n type: String,\n default: 'Default',\n },\n\n /**\n * Tooltip shown when skin selector button is hovered.\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :skin-selector-button-tooltip-label=\"'Change default skin tone'\" />\n */\n skinSelectorButtonTooltipLabel: {\n type: String,\n required: true,\n },\n\n /**\n * Sets the search query that filters emojis.\n * @type {String}\n * @example\n * <dt-emoji-picker search-query=\"smile\" />\n */\n searchQuery: {\n type: String,\n default: '',\n },\n\n /**\n * Shows the search input\n * @type {Boolean}\n * @example\n * <dt-emoji-picker :show-search=\"false\" />\n */\n showSearch: {\n type: Boolean,\n default: true,\n },\n});\n\nconst emits = defineEmits(\n [\n /**\n * It will emit the selected emoji\n * @event selected-emoji\n * @param {Object} emoji - The selected emoji from the emoji selector\n */\n 'selected-emoji',\n\n /**\n * It will emit the selected skin tone\n * @event skin-tone\n * @param {String} skin - The selected skin tone from the skin selector\n */\n 'skin-tone',\n\n /**\n * Since the keyboard events are encapsulated, we emit this event to close the picker\n * @event close\n */\n 'close',\n ],\n);\n\nconst internalSearchQuery = ref(props.searchQuery.value);\nconst highlightedEmoji = ref(null);\nconst selectedTabset = ref({});\n\nconst scrollIntoTab = ref(0);\nconst isScrolling = ref(false);\n\nconst searchInputRef = ref(null);\nconst emojiSelectorRef = ref(null);\nconst tabsetRef = ref(null);\n\nconst showRecentlyUsedTab = computed(() => props.recentlyUsedEmojis.length > 0);\n\nwatch(\n () => props.searchQuery,\n (newValue) => {\n internalSearchQuery.value = newValue;\n },\n);\n\n/**\n * Handle the selected tabset event\n * We're creating a new object with the same value as selectedTabset and assigning it back to selectedTabset.\n * Vue will see this as a new object and trigger the watcher in the child component.\n * Using this method, we are able to trigger the watcher in the child component even if the value being passed is the\n * same as the previous value.\n * @event selectedTabset\n * @param tabName {String} - The name of the tab that was selected\n */\nfunction scrollToSelectedTabset (tabId) {\n internalSearchQuery.value = '';\n selectedTabset.value = tabId;\n selectedTabset.value = { ...selectedTabset.value, tabId };\n}\n\nfunction updateScrollIntoTab (value) {\n scrollIntoTab.value = value;\n}\n\nfunction updateIsScrolling (value) {\n isScrolling.value = value;\n}\nfunction updateHighlightedEmoji (emoji) {\n highlightedEmoji.value = emoji;\n}\n\nfunction focusNextSectionFromEmojiTabSet () {\n if (props.showSearch) {\n searchInputRef.value.focusSearchInput();\n } else {\n emojiSelectorRef.value.focusEmojiSelector();\n }\n}\n\nfunction focusNextSectionFromEmojiSelector () {\n if (props.showSearch) {\n searchInputRef.value.focusSearchInput();\n } else {\n tabsetRef.value.focusTabset();\n }\n}\n</script>\n"],"names":["ref","emojis"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"emoji-picker.js","sources":["../../components/emoji_picker/modules/emoji_search.vue","../../components/emoji_picker/modules/emoji_tabset.vue","../../components/emoji_picker/emoji_picker_constants.js","../../components/emoji_picker/composables/useKeyboardNavigation.js","../../components/emoji_picker/modules/emoji_selector.vue","../../components/emoji_picker/modules/emoji_skin_selector.vue","../../components/emoji_picker/emoji_picker.vue"],"sourcesContent":["<template>\n <div class=\"d-emoji-picker__search d-emoji-picker__alignment\">\n <dt-input\n id=\"searchInput\"\n ref=\"searchInput\"\n :placeholder=\"searchPlaceholderLabel\"\n :model-value=\"modelValue\"\n @update:model-value=\"$emit('update:modelValue', $event)\"\n @keydown.up=\"$emit('focus-tabset')\"\n @keydown.down.prevent=\"$emit('focus-emoji-selector')\"\n @keydown.enter=\"$emit('select-first-emoji')\"\n >\n <template #leftIcon>\n <dt-icon\n name=\"search\"\n size=\"200\"\n />\n </template>\n <template\n v-if=\"modelValue.length > 0\"\n #rightIcon\n >\n <dt-button\n importance=\"clear\"\n kind=\"muted\"\n @click=\"clearSearch\"\n >\n <template #icon>\n <dt-icon\n name=\"x-circle\"\n size=\"200\"\n />\n </template>\n </dt-button>\n </template>\n </dt-input>\n </div>\n</template>\n\n<script setup>\nimport { DtInput } from '@/components/input';\nimport { DtIcon } from '@/components/icon';\nimport { DtButton } from '@/components/button';\nimport { onMounted, ref } from 'vue';\n\ndefineProps({\n searchPlaceholderLabel: {\n type: String,\n required: true,\n },\n modelValue: {\n type: String,\n default: '',\n },\n});\n\nconst emits = defineEmits(['update:modelValue', 'focus-emoji-selector', 'focus-tabset', 'select-first-emoji']);\n\nconst searchInput = ref(null);\n\nfunction clearSearch () {\n emits('update:modelValue', '');\n focusSearchInput();\n}\n\nfunction focusSearchInput () {\n searchInput.value.focus();\n}\nonMounted(() => {\n focusSearchInput();\n});\n\ndefineExpose({\n focusSearchInput,\n});\n</script>\n","<template>\n <div class=\"d-emoji-picker__tabset\">\n <dt-tab-group\n tab-list-class=\"d-emoji-picker__tabset-list\"\n :selected=\"selectedTab\"\n >\n <template #tabs>\n <dt-tab\n v-for=\"(tab, index) in tabs\"\n :id=\"tab.id\"\n :ref=\"el => { if (el) setTabsetRef(el) }\"\n :key=\"tab.id\"\n :panel-id=\"tab.panelId\"\n :label=\"tab.label\"\n aria-controls=\"d-emoji-picker-list\"\n :tabindex=\"index + 1\"\n @click.capture.stop=\"selectTabset(tab.id)\"\n @keydown=\"handleKeyDown($event, tab.id)\"\n >\n <dt-icon\n size=\"400\"\n :name=\"tab.icon\"\n />\n </dt-tab>\n </template>\n </dt-tab-group>\n </div>\n</template>\n\n<script setup>\nimport { computed, ref, toRefs, watch } from 'vue';\nimport { DtTab, DtTabGroup } from '@/components/tabs';\nimport { DtIcon } from '@/components/icon';\nimport { EMOJI_PICKER_CATEGORIES } from '@/components/emoji_picker';\n\nconst props = defineProps({\n /**\n * Whether to show the recently used tab or not\n * @type {Boolean}\n * @default false\n */\n showRecentlyUsedTab: {\n type: Boolean,\n default: false,\n },\n\n scrollIntoTab: {\n type: Number,\n required: true,\n },\n\n isScrolling: {\n type: Boolean,\n default: false,\n },\n\n emojiFilter: {\n type: String,\n default: '',\n },\n\n /**\n * The labels for the aria-label\n * @type {Array}\n * @required\n */\n tabsetLabels: {\n type: Array,\n required: true,\n },\n});\n\nconst emits = defineEmits([\n /**\n * Emitted when a tab is selected\n * @event selected-tabset\n * @param {String} tabId - The name of the tab that was selected\n */\n 'selected-tabset',\n\n 'focus-search-input',\n 'focus-skin-selector',\n]);\n\nconst TABS_DATA = [\n { label: EMOJI_PICKER_CATEGORIES.MOST_RECENTLY_USED, icon: 'clock' },\n { label: EMOJI_PICKER_CATEGORIES.SMILEYS_AND_PEOPLE, icon: 'satisfied' },\n { label: EMOJI_PICKER_CATEGORIES.NATURE, icon: 'living-thing' },\n { label: EMOJI_PICKER_CATEGORIES.FOOD, icon: 'food' },\n { label: EMOJI_PICKER_CATEGORIES.ACTIVITY, icon: 'object' },\n { label: EMOJI_PICKER_CATEGORIES.TRAVEL, icon: 'transportation' },\n { label: EMOJI_PICKER_CATEGORIES.OBJECTS, icon: 'lightbulb' },\n { label: EMOJI_PICKER_CATEGORIES.SYMBOLS, icon: 'heart' },\n { label: EMOJI_PICKER_CATEGORIES.FLAGS, icon: 'flag' },\n];\n\nconst tabs = computed(() => {\n const tabsData = props.showRecentlyUsedTab ? TABS_DATA : TABS_DATA.slice(1);\n\n return tabsData.map((tab, index) => ({\n ...tab,\n label: props.tabsetLabels[index],\n id: (index + 1).toString(),\n panelId: (index + 1).toString(),\n }));\n});\n\nconst isSearching = computed(() => props.emojiFilter.length > 0);\n\nconst selectedTab = ref('1');\n\nconst { isScrolling } = toRefs(props);\n\nconst tabsetRef = ref([]);\n\nwatch(() => props.scrollIntoTab,\n () => {\n if (!isScrolling.value && !isSearching.value) {\n selectedTab.value = (props.scrollIntoTab + 1).toString();\n }\n });\n\nwatch(isSearching,\n () => {\n if (isSearching.value) {\n selectedTab.value = null;\n }\n });\n\n/**\n * We are using .capture.stop modifiers on the click event\n * because we don't want to trigger the click event of the\n * dt-tab component\n */\nfunction selectTabset (id) {\n if (!isScrolling.value) {\n selectedTab.value = id;\n }\n emits('selected-tabset', id);\n}\n\nfunction setTabsetRef (ref) {\n // We push the $el, because $el is the button inside the dt-tab component\n // and we need the button to focus it\n tabsetRef.value.push(ref.$el);\n}\n\nfunction focusTabset () {\n tabsetRef.value[0].focus();\n}\n\nfunction handleKeyDown (event, tabId) {\n if (event.key === 'Enter') {\n selectTabset(tabId);\n // We blur because seems like the tab component override the selected prop, and it removes the selected style\n tabsetRef.value[tabId - 1].blur();\n }\n\n if (event.key === 'Tab') {\n event.preventDefault();\n if (event.shiftKey) {\n emits('focus-skin-selector');\n } else {\n emits('focus-search-input');\n }\n }\n\n if (event.key === 'ArrowDown') {\n // Jump to search input\n emits('focus-search-input');\n }\n}\n\ndefineExpose({\n focusTabset,\n});\n</script>\n","export const ARROW_KEYS = {\n ARROW_UP: 'ArrowUp',\n ARROW_DOWN: 'ArrowDown',\n ARROW_LEFT: 'ArrowLeft',\n ARROW_RIGHT: 'ArrowRight',\n};\n\nexport const CDN_URL = 'https://static.dialpadcdn.com/joypixels/png/unicode/32/';\nexport const EMOJIS_PER_ROW = 9;\nexport const EMOJI_PICKER_SKIN_TONE_MODIFIERS = {\n DEFAULT: 'Default',\n LIGHT: 'Light',\n MEDIUM_LIGHT: 'MediumLight',\n MEDIUM: 'Medium',\n MEDIUM_DARK: 'MediumDark',\n DARK: 'Dark',\n};\n\nexport const EMOJI_PICKER_CATEGORIES = {\n MOST_RECENTLY_USED: 'Most recently used',\n SMILEYS_AND_PEOPLE: 'Smileys and people',\n NATURE: 'Nature',\n FOOD: 'Food',\n ACTIVITY: 'Activity',\n TRAVEL: 'Travel',\n OBJECTS: 'Objects',\n SYMBOLS: 'Symbols',\n FLAGS: 'Flags',\n};\n\nexport default {\n EMOJI_PICKER_SKIN_TONE_MODIFIERS,\n EMOJI_PICKER_CATEGORIES,\n};\n","import { ref } from 'vue';\nimport { EMOJIS_PER_ROW, ARROW_KEYS } from '@/components/emoji_picker/emoji_picker_constants';\n\nexport function useKeyboardNavigation () {\n const emojiRefs = ref([]);\n const emojiFilteredRefs = ref([]);\n const isFiltering = ref(false);\n const hoverFirstEmoji = ref(true);\n\n function _handleArrowLeft (indexTab, indexEmoji) {\n if (!focusEmoji(indexTab, indexEmoji - 1)) {\n if (emojiRefs.value[indexTab - 1]) {\n focusEmoji(indexTab - 1, emojiRefs.value[indexTab - 1].length - 1);\n } else {\n focusEmoji(emojiRefs.value.length - 1, emojiRefs.value[emojiRefs.value.length - 1].length - 1);\n }\n }\n }\n\n function _handleArrowRight (indexTab, indexEmoji) {\n if (!focusEmoji(indexTab, indexEmoji + 1)) {\n if (!focusEmoji(indexTab + 1, 0)) {\n focusEmoji(0, 0);\n }\n }\n }\n\n function _handleArrowLeftFiltered (indexTab, indexEmoji) {\n if (!focusEmoji(0, indexEmoji - 1)) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n }\n }\n\n function _handleArrowRightFiltered (indexTab, indexEmoji) {\n if (!focusEmoji(0, indexEmoji + 1)) {\n focusEmoji(0, 0);\n }\n }\n\n function _handleHorizontalNavigation (direction, indexTab, indexEmoji) {\n if (isFiltering.value) {\n if (direction === 'left') {\n _handleArrowLeftFiltered(indexTab, indexEmoji);\n } else if (direction === 'right') {\n _handleArrowRightFiltered(indexTab, indexEmoji);\n }\n } else {\n if (direction === 'left') {\n _handleArrowLeft(indexTab, indexEmoji);\n } else if (direction === 'right') {\n _handleArrowRight(indexTab, indexEmoji);\n }\n }\n }\n\n function focusEmoji (indexTab, indexEmoji) {\n const emojiRef = isFiltering.value\n ? emojiFilteredRefs.value?.[indexEmoji]\n : emojiRefs.value?.[indexTab]?.[indexEmoji];\n\n if (emojiRef) {\n emojiRef.focus();\n return true;\n }\n\n return false;\n }\n\n function setEmojiRef (el, indexTab, indexEmoji) {\n if (!emojiRefs.value[indexTab]) {\n emojiRefs.value[indexTab] = [];\n }\n emojiRefs.value[indexTab][indexEmoji] = el;\n }\n\n function setFilteredRef (el, index) {\n emojiFilteredRefs.value[index] = el;\n }\n\n function handleArrowNavigationFiltered (key, indexEmoji) {\n hoverFirstEmoji.value = false;\n\n if (key === ARROW_KEYS.ARROW_UP) {\n const position = indexEmoji % EMOJIS_PER_ROW;\n\n if (!focusEmoji(0, indexEmoji - EMOJIS_PER_ROW)) {\n const lastEmojiPosition =\n emojiFilteredRefs.value.length - (emojiFilteredRefs.value.length % EMOJIS_PER_ROW) + position;\n\n focusEmoji(0, lastEmojiPosition);\n\n if (!focusEmoji(0, lastEmojiPosition)) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n }\n }\n }\n\n if (key === ARROW_KEYS.ARROW_DOWN) {\n if (!focusEmoji(0, indexEmoji + EMOJIS_PER_ROW)) {\n const position = indexEmoji % EMOJIS_PER_ROW;\n\n if (emojiFilteredRefs.value?.[indexEmoji + (EMOJIS_PER_ROW - position)]) {\n focusEmoji(0, emojiFilteredRefs.value.length - 1);\n } else {\n focusEmoji(0, position);\n }\n }\n }\n\n if (key === ARROW_KEYS.ARROW_LEFT) {\n _handleHorizontalNavigation('left', 0, indexEmoji);\n }\n\n if (key === ARROW_KEYS.ARROW_RIGHT) {\n _handleHorizontalNavigation('right', 0, indexEmoji);\n }\n }\n\n function handleArrowNavigation (key, indexTab, indexEmoji) {\n if (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 - (emojiRefs.value[emojiRefs.value.length - 1].length % EMOJIS_PER_ROW);\n\n const emojiToJump =\n emojiRefs.value[emojiRefs.value.length - 1].length + numberOfMissingEmojis - (EMOJIS_PER_ROW - position);\n\n if (!focusEmoji(emojiRefs.value.length - 1, emojiToJump)) {\n // if there is no emoji in this position, jump to the last emoji of the row\n focusEmoji(emojiRefs.value.length - 1, emojiRefs.value[emojiRefs.value.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 (!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 = emojiRefs.value[previousTab].length;\n const lastEmojiPosition = emojisInPreviousTab - (emojisInPreviousTab % EMOJIS_PER_ROW) + position;\n\n if (!focusEmoji(previousTab, lastEmojiPosition)) {\n // if there is no emoji in this position, jump to the last emoji of the row\n focusEmoji(indexTab - 1, emojiRefs.value[indexTab - 1].length - 1);\n }\n }\n }\n\n if (key === 'ArrowDown') {\n if (!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 (emojiRefs.value?.[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 focusEmoji(indexTab, emojiRefs.value[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 (!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 (!focusEmoji(0, position)) {\n focusEmoji(0, emojiRefs.value[0].length - 1);\n }\n }\n }\n }\n }\n\n if (key === 'ArrowLeft') {\n _handleHorizontalNavigation('left', indexTab, indexEmoji);\n }\n\n if (key === 'ArrowRight') {\n _handleHorizontalNavigation('right', indexTab, indexEmoji);\n }\n }\n\n return {\n emojiFilteredRefs,\n isFiltering,\n hoverFirstEmoji,\n setEmojiRef,\n setFilteredRef,\n focusEmoji,\n handleArrowNavigationFiltered,\n handleArrowNavigation,\n };\n}\n","<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=\"selectEmoji(emoji)\"\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=\"selectEmoji(emoji)\"\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\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 scrollTo function starts scrolling and stops scrolling\n * @event is-scrolling\n * @param {Boolean} is-scrolling - Whether the user is scrolling with the scroll-to\n */\n 'is-scrolling',\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 - 20;\n\n /**\n * This variable is used to check if the user is scrolling inside the emoji picker\n * This is used to check if the user is scrolling using the scrollTo function\n * This is useful because this flag will prevent to update the fixed label when the user is scrolling\n * using the scrollTo function\n */\n let isScrolling = true;\n\n let prevScrollTop = container.scrollTop;\n emits('is-scrolling', true);\n\n /**\n * This event listener checks whether the user is scrolling up or down by comparing the current scrollTop\n * to prevScrollTop. If the scrollToTab function is scrolling from bottom to top and has reached the desired\n * position (scrollTop <= offsetTop),or if the scrollToTab function is scrolling from top to bottom and has\n * passed the desired position(scrollTop >= offsetTop), then isScrolling is set to false.\n */\n container.addEventListener('scroll', () => {\n if (isScrolling) {\n const scrollTop = container.scrollTop;\n if (\n (prevScrollTop < scrollTop && scrollTop >= offsetTop) ||\n (prevScrollTop > scrollTop && scrollTop <= offsetTop)\n ) {\n isScrolling = false;\n emits('is-scrolling', false);\n }\n prevScrollTop = scrollTop;\n }\n });\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(entries => {\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);\n break;\n default:\n break;\n }\n};\n\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);\n break;\n\n default:\n break;\n }\n};\n\nfunction selectEmoji (emoji) {\n emits('selected-emoji', emoji);\n}\n\nfunction highlightEmoji (emoji) {\n emits('highlighted-emoji', emoji);\n}\n\nfunction focusEmojiSelector () {\n focusEmoji(0, 0);\n}\n\nfunction focusLastEmoji () {\n focusEmoji(tabs.value.length - 1, 0);\n}\n\nonMounted(() => {\n setTabLabelObserver();\n});\n\nonUnmounted(() => {\n tabLabelObserver.value.disconnect();\n});\n\ndefineExpose({\n focusEmojiSelector,\n focusLastEmoji,\n});\n</script>\n","<template>\n <div data-qa=\"skin-selector\">\n <div\n v-show=\"isOpen\"\n class=\"d-emoji-picker__skin-list\"\n >\n <button\n v-for=\"(skin, index) in skinList\"\n :ref=\"el => { if (el) setSkinsRef(el) }\"\n :key=\"skin.name\"\n :class=\"{\n 'selected': skinSelected.skinCode === skin.skinCode,\n }\"\n @keydown=\"event => handleKeyDown(event, skin, index)\"\n @click=\"selectSkin(skin)\"\n >\n <img\n class=\"d-icon d-icon--size-500\"\n :alt=\"skin.name\"\n :aria-label=\"skin.name\"\n :title=\"skin.name\"\n :src=\"`${CDN_URL + skin.unicode_output}.png`\"\n >\n </button>\n </div>\n <div\n v-show=\"!isOpen\"\n class=\"d-emoji-picker__skin-selected\"\n >\n <dt-tooltip placement=\"top-end\">\n {{ skinSelectorButtonTooltipLabel }}\n <template #anchor>\n <button\n ref=\"skinSelectorRef\"\n :aria-label=\"skinSelectorButtonTooltipLabel\"\n tabindex=\"-1\"\n @click=\"toggleSkinList\"\n @keydown=\"event => handleKeyDown(event)\"\n >\n <img\n class=\"d-icon d-icon--size-500\"\n :alt=\"skinSelected.name\"\n :aria-label=\"skinSelected.name\"\n :title=\"skinSelected.name\"\n :src=\"`${CDN_URL + skinSelected.unicode_output}.png`\"\n >\n </button>\n </template>\n </dt-tooltip>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, nextTick, ref, watchEffect } from 'vue';\nimport { CDN_URL, EMOJI_PICKER_SKIN_TONE_MODIFIERS } from '@/components/emoji_picker';\nimport { DtTooltip } from '@/components/tooltip';\n\nconst props = defineProps({\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 isHovering: {\n type: Boolean,\n default: false,\n },\n\n skinSelectorButtonTooltipLabel: {\n type: String,\n required: true,\n },\n});\n\nconst emits = defineEmits([\n /**\n * The skin tone that was selected\n * @event skin-tone\n * @type {Number}\n */\n 'skin-tone',\n 'focus-tabset',\n 'focus-last-emoji',\n]);\n\nconst skinList = [\n {\n name: ':wave_tone1:',\n unicode_output: '1f44b-1f3fb',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.LIGHT,\n skinCode: '_tone1',\n },\n {\n name: ':wave_tone2:',\n unicode_output: '1f44b-1f3fc',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM_LIGHT,\n skinCode: '_tone2',\n },\n {\n name: ':wave_tone3:',\n unicode_output: '1f44b-1f3fd',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM,\n skinCode: '_tone3',\n },\n {\n name: ':wave_tone4:',\n unicode_output: '1f44b-1f3fe',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.MEDIUM_DARK,\n skinCode: '_tone4',\n },\n {\n name: ':wave_tone5:',\n unicode_output: '1f44b-1f3ff',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.DARK,\n skinCode: '_tone5',\n },\n {\n name: ':wave:',\n unicode_output: '1f44b',\n skinTone: EMOJI_PICKER_SKIN_TONE_MODIFIERS.DEFAULT,\n skinCode: '',\n },\n];\n\nconst isOpen = ref(false);\n\nconst skinSelectorRef = ref(null);\n\nconst skinsRef = ref([]);\n\n/**\n * It will close the skin selector if the user is hovering over the emoji list\n */\nwatchEffect(\n () => props.isHovering && (isOpen.value = false),\n);\n\n/**\n * It will initially display props.skinTone. If a new skin tone is selected,\n * it will display that until props.skinTone changes.\n */\nconst skinPassedIn = computed(() => skinList.find((skin) => skin.skinTone === props.skinTone));\nconst skinSelected = ref(skinPassedIn.value);\nwatchEffect(() => skinPassedIn.value && (skinSelected.value = skinPassedIn.value));\n\nfunction setSkinsRef (ref) {\n skinsRef.value.push(ref);\n}\nfunction focusSkinSelector () {\n skinSelectorRef.value.focus();\n}\n\nfunction selectSkin (skin) {\n skinSelected.value = skin;\n isOpen.value = false;\n emits('skin-tone', skin.skinTone);\n nextTick(() => focusSkinSelector());\n}\n\nconst handleKeyDown = (event, skin, index) => {\n event.preventDefault();\n\n if (event.key === 'ArrowLeft') {\n if (index === 0) skinsRef.value[skinsRef.value.length - 1]?.focus();\n skinsRef.value[index - 1]?.focus();\n }\n\n if (event.key === 'ArrowRight') {\n skinsRef.value[index + 1]?.focus();\n }\n\n if (event.key === 'Enter') {\n if (skin) { selectSkin(skin); } else {\n toggleSkinList();\n }\n }\n\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n emits('focus-last-emoji');\n } else {\n emits('focus-tabset');\n }\n }\n};\n\nfunction toggleSkinList () {\n isOpen.value = !isOpen.value;\n nextTick(() => skinsRef.value[0].focus());\n}\n\ndefineExpose({\n focusSkinSelector,\n});\n</script>\n","<template>\n <div\n class=\"d-emoji-picker\"\n >\n <div class=\"d-emoji-picker--header\">\n <emoji-tabset\n ref=\"tabsetRef\"\n :emoji-filter=\"internalSearchQuery\"\n :show-recently-used-tab=\"showRecentlyUsedTab\"\n :scroll-into-tab=\"scrollIntoTab\"\n :tabset-labels=\"tabSetLabels\"\n :is-scrolling=\"isScrolling\"\n @focus-skin-selector=\"$refs.skinSelectorRef.focusSkinSelector()\"\n @focus-search-input=\"showSearch ? $refs.searchInputRef.focusSearchInput() : $refs.emojiSelectorRef.focusEmojiSelector()\"\n @selected-tabset=\"scrollToSelectedTabset\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n <div class=\"d-emoji-picker--body\">\n <emoji-search\n v-if=\"showSearch\"\n ref=\"searchInputRef\"\n v-model=\"internalSearchQuery\"\n :search-placeholder-label=\"searchPlaceholderLabel\"\n @select-first-emoji=\"emits('selected-emoji', highlightedEmoji)\"\n @focus-tabset=\"$refs.tabsetRef.focusTabset()\"\n @focus-emoji-selector=\"$refs.emojiSelectorRef.focusEmojiSelector()\"\n @keydown.esc=\"emits('close')\"\n />\n <emoji-selector\n ref=\"emojiSelectorRef\"\n :emoji-filter=\"internalSearchQuery\"\n :skin-tone=\"skinTone\"\n :tabset-labels=\"tabSetLabels\"\n :search-results-label=\"searchResultsLabel\"\n :search-no-results-label=\"searchNoResultsLabel\"\n :recently-used-emojis=\"recentlyUsedEmojis\"\n :selected-tabset=\"selectedTabset\"\n @scroll-into-tab=\"updateScrollIntoTab\"\n @is-scrolling=\"updateIsScrolling\"\n @highlighted-emoji=\"updateHighlightedEmoji\"\n @selected-emoji=\"emits('selected-emoji', $event)\"\n @focus-skin-selector=\"$refs.skinSelectorRef.focusSkinSelector()\"\n @focus-search-input=\"showSearch ? $refs.searchInputRef.focusSearchInput() : $refs.tabsetRef.focusTabset()\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n <div class=\"d-emoji-picker--footer\">\n <emoji-description :emoji=\"highlightedEmoji\" />\n <emoji-skin-selector\n ref=\"skinSelectorRef\"\n :is-hovering=\"!!highlightedEmoji\"\n :skin-selector-button-tooltip-label=\"skinSelectorButtonTooltipLabel\"\n :skin-tone=\"skinTone\"\n @skin-tone=\"emits('skin-tone', $event)\"\n @focus-tabset=\"$refs.tabsetRef.focusTabset()\"\n @focus-last-emoji=\"$refs.emojiSelectorRef.focusLastEmoji()\"\n @keydown.esc=\"emits('close')\"\n />\n </div>\n </div>\n</template>\n\n<script setup>\nimport EmojiSearch from './modules/emoji_search.vue';\nimport EmojiTabset from './modules/emoji_tabset.vue';\nimport EmojiSelector from './modules/emoji_selector.vue';\nimport EmojiSkinSelector from './modules/emoji_skin_selector.vue';\nimport EmojiDescription from './modules/emoji_description.vue';\nimport { computed, ref, watch } from 'vue';\n\nconst props = defineProps({\n /**\n * The array with recently used emoji object\n * This list is necessary to fill the recently used tab\n * @type {Array}\n * @default []\n * @example\n * <dt-emoji-picker :recentlyUsedEmojis=\"[emojiObject, emojiObject]\" />\n */\n // TODO try to simplify this to achieve an array of unicode characters and not an entire emoji data object\n recentlyUsedEmojis: {\n type: Array,\n default: () => ([]),\n },\n\n /**\n * The placeholder text for the search input\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchPlaceholderLabel=\"'Search...'\" />\n */\n searchPlaceholderLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The label for the search results tab\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchResultsLabel=\"'Search results'\" />\n */\n searchResultsLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The label for the search no results\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :searchNoResultsLabel=\"'No results'\" />\n */\n searchNoResultsLabel: {\n type: String,\n required: true,\n },\n\n /**\n * The list of tabsets to show, it is necessary to be updated with the correct language\n * It must respect the provided order.\n * @type {Array}\n * @required\n * @example\n * <dt-emoji-picker\n * :tabSetLabels=\"['Most recently used', 'Smileys and people', 'Nature',\n * 'Food', 'Activity', 'Travel', 'Objects', 'Symbols', 'Flags']\" />\n */\n tabSetLabels: {\n type: Array,\n required: true,\n },\n\n /**\n * The skin tone to show the emojis\n * This prop gives the possibility to use the skin tone selected by the user previously\n * @type {String}\n * @default 'Default'\n * @values 'Default', 'Light', 'MediumLight', 'Medium', 'MediumDark', 'Dark'\n * @example\n * <dt-emoji-picker :skinTone=\"'Default'\" />\n */\n skinTone: {\n type: String,\n default: 'Default',\n },\n\n /**\n * Tooltip shown when skin selector button is hovered.\n * @type {String}\n * @required\n * @example\n * <dt-emoji-picker :skin-selector-button-tooltip-label=\"'Change default skin tone'\" />\n */\n skinSelectorButtonTooltipLabel: {\n type: String,\n required: true,\n },\n\n /**\n * Sets the search query that filters emojis.\n * @type {String}\n * @example\n * <dt-emoji-picker search-query=\"smile\" />\n */\n searchQuery: {\n type: String,\n default: '',\n },\n\n /**\n * Shows the search input\n * @type {Boolean}\n * @example\n * <dt-emoji-picker :show-search=\"false\" />\n */\n showSearch: {\n type: Boolean,\n default: true,\n },\n});\n\nconst emits = defineEmits(\n [\n /**\n * It will emit the selected emoji\n * @event selected-emoji\n * @param {Object} emoji - The selected emoji from the emoji selector\n */\n 'selected-emoji',\n\n /**\n * It will emit the selected skin tone\n * @event skin-tone\n * @param {String} skin - The selected skin tone from the skin selector\n */\n 'skin-tone',\n\n /**\n * Since the keyboard events are encapsulated, we emit this event to close the picker\n * @event close\n */\n 'close',\n ],\n);\n\nconst internalSearchQuery = ref(props.searchQuery.value);\nconst highlightedEmoji = ref(null);\nconst selectedTabset = ref({});\n\nconst scrollIntoTab = ref(0);\nconst isScrolling = ref(false);\n\nconst showRecentlyUsedTab = computed(() => props.recentlyUsedEmojis.length > 0);\n\nwatch(\n () => props.searchQuery,\n (newValue) => {\n internalSearchQuery.value = newValue;\n },\n);\n\n/**\n * Handle the selected tabset event\n * We're creating a new object with the same value as selectedTabset and assigning it back to selectedTabset.\n * Vue will see this as a new object and trigger the watcher in the child component.\n * Using this method, we are able to trigger the watcher in the child component even if the value being passed is the\n * same as the previous value.\n * @event selectedTabset\n * @param tabName {String} - The name of the tab that was selected\n */\nfunction scrollToSelectedTabset (tabId) {\n internalSearchQuery.value = '';\n selectedTabset.value = tabId;\n selectedTabset.value = { ...selectedTabset.value, tabId };\n}\n\nfunction updateScrollIntoTab (value) {\n scrollIntoTab.value = value;\n}\n\nfunction updateIsScrolling (value) {\n isScrolling.value = value;\n}\nfunction updateHighlightedEmoji (emoji) {\n highlightedEmoji.value = emoji;\n}\n</script>\n"],"names":["ref","emojis"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.cjs","sources":["../../components/tooltip/tooltip.vue"],"sourcesContent":["<template>\n <div data-qa=\"dt-tooltip-container\">\n <!-- disabling as the below events are for capturing events from interactive\n elements within the span rather than on the span itself -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <span\n v-if=\"!externalAnchor\"\n ref=\"anchor\"\n data-qa=\"dt-tooltip-anchor\"\n @focusin=\"onEnterAnchor\"\n @focusout=\"onLeaveAnchor\"\n @mouseenter=\"onEnterAnchor\"\n @mouseleave=\"onLeaveAnchor\"\n @keydown.esc=\"onLeaveAnchor\"\n >\n <!-- @slot Slot for the anchor element -->\n <slot\n name=\"anchor\"\n />\n </span>\n <div\n :id=\"id\"\n ref=\"content\"\n data-qa=\"dt-tooltip\"\n :class=\"[\n 'd-tooltip',\n {\n [ TOOLTIP_KIND_MODIFIERS.inverted ]: inverted,\n },\n contentClass,\n ]\"\n >\n <!-- In case when transitionend event doesn't work correct (for ex. tooltip component with custom trigger) -->\n <!-- after-leave event can be used instead of transitionend -->\n <!-- @slot Slot for the content, defaults to message prop -->\n <slot>\n {{ message }}\n </slot>\n </div>\n </div>\n</template>\n\n<script>\nimport {\n TOOLTIP_KIND_MODIFIERS,\n TOOLTIP_DIRECTIONS,\n TOOLTIP_STICKY_VALUES,\n TOOLTIP_DELAY_MS,\n} from './tooltip_constants.js';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '../popover/popover_constants';\nimport { getUniqueString, hasSlotContent } from '@/common/utils';\nimport {\n createTippy,\n getAnchor,\n getPopperOptions,\n} from '@/components/popover/tippy_utils';\n\n/**\n * A tooltip is a floating label that briefly explains an action, function, or an element.\n * Its content is exclusively text and shouldn't be vital information for users.\n * If richer media is desired, consider using a popover instead.\n * @see https://dialtone.dialpad.com/components/tooltip.html\n */\nexport default {\n name: 'DtTooltip',\n\n props: {\n /**\n * The id of the tooltip\n */\n id: {\n type: String,\n default () { return getUniqueString(); },\n },\n\n /**\n * If the popover does not fit in the direction described by \"placement\",\n * it will attempt to change its direction to the \"fallbackPlacements\"\n * if defined, otherwise it will automatically position to a new location\n * as it sees best fit. See\n * <a\n * class=\"d-link\"\n * href=\"https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements\"\n * target=\"_blank\"\n * >\n * Popper.js docs\n * </a>\n * */\n fallbackPlacements: {\n type: Array,\n default: () => ['auto'],\n },\n\n /**\n * If true, applies inverted styles to the tooltip\n * @values true, false\n */\n inverted: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Displaces the tooltip from its reference element\n * by the specified number of pixels. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#offset\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n */\n offset: {\n type: Array,\n default: () => [0, 12],\n },\n\n /**\n * The direction the popover displays relative to the anchor. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#placement\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values top, top-start, top-end,\n * right, right-start, right-end,\n * left, left-start, left-end,\n * bottom, bottom-start, bottom-end,\n * auto, auto-start, auto-end\n */\n placement: {\n type: String,\n default: 'top',\n validator (placement) {\n return TOOLTIP_DIRECTIONS.includes(placement);\n },\n },\n\n /**\n * If the tooltip sticks to the anchor. This is usually not needed, but can be needed\n * if the reference element's position is animating, or to automatically update the popover\n * position in those cases the DOM layout changes the reference element's position.\n * `true` enables it, `reference` only checks the \"reference\" rect for changes and `popper` only\n * checks the \"popper\" rect for changes. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#sticky\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values true, false, reference, popper\n */\n sticky: {\n type: [Boolean, String],\n default: true,\n validator: (sticky) => {\n return TOOLTIP_STICKY_VALUES.includes(sticky);\n },\n },\n\n /**\n * Sets the element to which the tooltip is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * This prop is not reactive, must be set on initial render.\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Additional css classes for the tooltip content element.\n * Can accept all of String, Object, and Array, i.e. has the\n * same api as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * A provided message for the tooltip content\n */\n message: {\n type: String,\n default: '',\n },\n\n /**\n * Controls whether hover/focus causes the tooltip to appear.\n * Cannot be combined with the show prop. show value will be ignored.\n * by default this is true, if you override with false, the tooltip will never show up.\n */\n enabled: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Controls whether the tooltip is shown. Leaving this null will have the tooltip trigger on mouseover by default.\n * If you set this value, the default mouseover behavior will be disabled and you can control it as you need.\n * Supports .sync modifier\n * @values null, true, false\n */\n show: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Whether the tooltip should have a transition effect (fade).\n */\n transition: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the tooltip will have a delay when being focused or moused over.\n * @values true, false\n */\n delay: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Set a custom theme on the tooltip. See https://atomiks.github.io/tippyjs/v6/themes/\n */\n theme: {\n type: String,\n default: undefined,\n },\n\n /**\n * External anchor id to use in those cases the anchor can't be provided via the slot.\n * For instance, using the combobox's input as the anchor for the popover.\n */\n externalAnchor: {\n type: String,\n default: null,\n },\n },\n\n emits: [\n /**\n * Emitted when tooltip is shown or hidden\n *\n * @event shown\n * @type {Boolean}\n */\n 'shown',\n\n /**\n * Sync show value\n *\n * @event update:show\n */\n 'update:show',\n ],\n\n data () {\n return {\n TOOLTIP_KIND_MODIFIERS,\n hasSlotContent,\n tip: null,\n\n inTimer: null,\n\n // Internal state for whether the tooltip is shown. Changing the prop\n // will update this.\n internalShow: false,\n\n // this is where the placement currently is, this can be different than\n // the placement prop when there is not enough available room for the tip\n // to display and it uses a fallback placement.\n currentPlacement: this.placement,\n };\n },\n\n computed: {\n // eslint-disable-next-line complexity\n tippyProps () {\n return {\n offset: this.offset,\n delay: this.delay ? TOOLTIP_DELAY_MS : false,\n placement: this.placement,\n sticky: this.sticky,\n theme: this.inverted ? 'inverted' : this.theme,\n animation: this.transition ? 'fade' : false,\n // onShown only triggers when transition is truthy\n onShown: (tooltipInstance) => this.onShow(tooltipInstance, 'onShown'),\n // onShown will always be called, but it will be called before the animation is complete\n onShow: (tooltipInstance) => this.onShow(tooltipInstance, 'onShow'),\n onHidden: this.onHide,\n\n popperOptions: getPopperOptions({\n fallbackPlacements: this.fallbackPlacements,\n hasHideModifierEnabled: true,\n onChangePlacement: this.onChangePlacement,\n }),\n };\n },\n\n anchor () {\n return this.externalAnchor ? document.body.querySelector(this.externalAnchor) : getAnchor(this.$refs.anchor);\n },\n },\n\n watch: {\n\n tippyProps: {\n handler: 'setProps',\n deep: true,\n },\n\n show: {\n handler: function (show) {\n if (show !== null) {\n this.internalShow = show;\n }\n },\n\n immediate: true,\n },\n\n internalShow (value) {\n if (value) {\n this.setProps();\n this.tip.show();\n } else {\n this.tip.hide();\n }\n },\n\n sticky (sticky) {\n this.tip.setProps({\n sticky,\n });\n },\n },\n\n mounted () {\n if (!this.enabled && this.show != null) {\n console.warn('Tooltip: You cannot use both the enabled and show props at the same time.');\n console.warn('The show prop will be ignored.');\n }\n\n this.externalAnchor && this.addExternalAnchorEventListeners();\n this.tip = createTippy(this.anchor, this.initOptions());\n },\n\n beforeUnmount () {\n this.externalAnchor && this.removeExternalAnchorEventListeners();\n\n if (this.tip) {\n this.tip?.destroy();\n }\n },\n\n methods: {\n calculateAnchorZindex () {\n // if a modal is currently active render at modal-element z-index, otherwise at tooltip z-index\n if (this.$el.getRootNode()\n .querySelector('.d-modal[aria-hidden=\"false\"], .d-modal--transparent[aria-hidden=\"false\"]') ||\n // Special case because we don't have any dialtone drawer component yet. Render at 651 when\n // anchor of popover is within a drawer.\n this.$el.closest('.d-zi-drawer')) {\n return 651;\n } else {\n return 400;\n }\n },\n\n hasVisibleFocus () {\n return this.anchor.matches(':focus-visible');\n },\n\n onEnterAnchor (e) {\n if (this.delay && this.inTimer === null) {\n this.inTimer = setTimeout(() => {\n this.triggerShow(e);\n }, TOOLTIP_DELAY_MS);\n } else {\n this.triggerShow(e);\n }\n },\n\n triggerShow (e) {\n if (e.type === 'focusin') {\n // only show tooltips on visible focus when triggered via focus.\n // when the user is using the mouse they only want tooltips to display\n // on mouseover.\n //\n // Example: anchor of a popover is a button with tooltip.\n // closing it with the mouse would trigger the tooltip to display as\n // the anchor is focused on close. Not what we want.\n if (this.show === null && this.hasVisibleFocus()) {\n this.internalShow = true;\n }\n } else {\n if (this.show === null) this.internalShow = true;\n }\n },\n\n onLeaveAnchor (e) {\n if (e.type === 'keydown' && e.code !== 'Escape') return;\n\n clearTimeout(this.inTimer);\n this.inTimer = null;\n this.triggerHide();\n },\n\n triggerHide () {\n if (this.show === null) this.internalShow = false;\n },\n\n onChangePlacement (placement) {\n this.currentPlacement = placement;\n },\n\n onHide () {\n this.tip?.unmount();\n this.$emit('shown', false);\n if (this.show !== null) {\n this.$emit('update:show', false);\n }\n },\n\n onShow (tooltipInstance, callingMethod) {\n if (!this.tooltipHasContent(tooltipInstance)) {\n return false;\n }\n if (this.transition && callingMethod === 'onShow') {\n return;\n }\n this.$emit('shown', true);\n if (this.show !== null) {\n this.$emit('update:show', true);\n }\n },\n\n setProps () {\n if (this.tip && this.tip.setProps) {\n this.tip.setProps({\n ...this.tippyProps,\n // these need to be set here rather than in tippyProps because they are non-reactive\n appendTo: this.appendTo === 'body' ? this.anchor?.getRootNode()?.querySelector('body') : this.appendTo,\n zIndex: this.calculateAnchorZindex(),\n });\n }\n },\n\n onMount () {\n this.setProps();\n },\n\n tooltipHasContent (tooltipInstance) {\n // don't show tooltip when no content\n if (tooltipInstance.props.content.textContent.trim().length === 0) {\n return false;\n }\n return true;\n },\n\n // set initial options here. If any of the options need to dynamically change, they should be put in\n // tippyProps instead.\n initOptions () {\n const template = this.$refs.content;\n return {\n content: template,\n arrow: '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"7\"><path d=\"M 14.5,7 8,0 1.5,7 Z\"/></svg>',\n // transition duration - same as our custom fade delay in dialtone-globals.less\n duration: 180,\n interactive: false,\n trigger: 'manual',\n hideOnClick: false,\n // disable tooltip from displaying on touch devices\n touch: false,\n onMount: this.onMount,\n showOnCreate: this.internalShow,\n popperOptions: getPopperOptions({\n hasHideModifierEnabled: true,\n }),\n };\n },\n\n addExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n\n removeExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n },\n};\n</script>\n\n<style lang=\"less\">\n@import 'tippy.js/dist/svg-arrow.css';\n\n.tippy-box[data-reference-hidden] {\n visibility: hidden;\n pointer-events: none;\n}\n\n.tippy-box > .tippy-svg-arrow {\n fill: var(--dt-color-surface-contrast);\n}\n\n.tippy-box[data-theme~='inverted'] > .tippy-svg-arrow {\n fill: var(--dt-color-surface-moderate);\n}\n\n.tippy-box[data-animation='fade'][data-state='hidden'] {\n opacity: 0;\n}\n</style>\n"],"names":["getUniqueString","TOOLTIP_DIRECTIONS","TOOLTIP_STICKY_VALUES","POPOVER_APPEND_TO_VALUES","TOOLTIP_KIND_MODIFIERS","hasSlotContent","TOOLTIP_DELAY_MS","getPopperOptions","getAnchor","createTippy","_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_normalizeClass"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tooltip.cjs","sources":["../../components/tooltip/tooltip.vue"],"sourcesContent":["<template>\n <div data-qa=\"dt-tooltip-container\">\n <!-- disabling as the below events are for capturing events from interactive\n elements within the span rather than on the span itself -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <span\n v-if=\"!externalAnchor\"\n ref=\"anchor\"\n data-qa=\"dt-tooltip-anchor\"\n @focusin=\"onEnterAnchor\"\n @focusout=\"onLeaveAnchor\"\n @mouseenter=\"onEnterAnchor\"\n @mouseleave=\"onLeaveAnchor\"\n @keydown.esc=\"onLeaveAnchor\"\n >\n <!-- @slot Slot for the anchor element -->\n <slot\n name=\"anchor\"\n />\n </span>\n <div\n :id=\"id\"\n ref=\"content\"\n data-qa=\"dt-tooltip\"\n :class=\"[\n 'd-tooltip',\n {\n [ TOOLTIP_KIND_MODIFIERS.inverted ]: inverted,\n },\n contentClass,\n ]\"\n >\n <!-- In case when transitionend event doesn't work correct (for ex. tooltip component with custom trigger) -->\n <!-- after-leave event can be used instead of transitionend -->\n <!-- @slot Slot for the content, defaults to message prop -->\n <slot>\n {{ message }}\n </slot>\n </div>\n </div>\n</template>\n\n<script>\nimport {\n TOOLTIP_KIND_MODIFIERS,\n TOOLTIP_DIRECTIONS,\n TOOLTIP_STICKY_VALUES,\n TOOLTIP_DELAY_MS,\n} from './tooltip_constants.js';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '../popover/popover_constants';\nimport { getUniqueString, hasSlotContent } from '@/common/utils';\nimport {\n createTippy,\n getAnchor,\n getPopperOptions,\n} from '@/components/popover/tippy_utils';\n\n/**\n * A tooltip is a floating label that briefly explains an action, function, or an element.\n * Its content is exclusively text and shouldn't be vital information for users.\n * If richer media is desired, consider using a popover instead.\n * @see https://dialtone.dialpad.com/components/tooltip.html\n */\nexport default {\n name: 'DtTooltip',\n\n props: {\n /**\n * The id of the tooltip\n */\n id: {\n type: String,\n default () { return getUniqueString(); },\n },\n\n /**\n * If the popover does not fit in the direction described by \"placement\",\n * it will attempt to change its direction to the \"fallbackPlacements\"\n * if defined, otherwise it will automatically position to a new location\n * as it sees best fit. See\n * <a\n * class=\"d-link\"\n * href=\"https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements\"\n * target=\"_blank\"\n * >\n * Popper.js docs\n * </a>\n * */\n fallbackPlacements: {\n type: Array,\n default: () => ['auto'],\n },\n\n /**\n * If true, applies inverted styles to the tooltip\n * @values true, false\n */\n inverted: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Displaces the tooltip from its reference element\n * by the specified number of pixels. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#offset\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n */\n offset: {\n type: Array,\n default: () => [0, 12],\n },\n\n /**\n * The direction the popover displays relative to the anchor. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#placement\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values top, top-start, top-end,\n * right, right-start, right-end,\n * left, left-start, left-end,\n * bottom, bottom-start, bottom-end,\n * auto, auto-start, auto-end\n */\n placement: {\n type: String,\n default: 'top',\n validator (placement) {\n return TOOLTIP_DIRECTIONS.includes(placement);\n },\n },\n\n /**\n * If the tooltip sticks to the anchor. This is usually not needed, but can be needed\n * if the reference element's position is animating, or to automatically update the popover\n * position in those cases the DOM layout changes the reference element's position.\n * `true` enables it, `reference` only checks the \"reference\" rect for changes and `popper` only\n * checks the \"popper\" rect for changes. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#sticky\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values true, false, reference, popper\n */\n sticky: {\n type: [Boolean, String],\n default: true,\n validator: (sticky) => {\n return TOOLTIP_STICKY_VALUES.includes(sticky);\n },\n },\n\n /**\n * Sets the element to which the tooltip is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * This prop is not reactive, must be set on initial render.\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Additional css classes for the tooltip content element.\n * Can accept all of String, Object, and Array, i.e. has the\n * same api as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * A provided message for the tooltip content\n */\n message: {\n type: String,\n default: '',\n },\n\n /**\n * Controls whether hover/focus causes the tooltip to appear.\n * Cannot be combined with the show prop. show value will be ignored.\n * by default this is true, if you override with false, the tooltip will never show up.\n */\n enabled: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Controls whether the tooltip is shown. Leaving this null will have the tooltip trigger on mouseover by default.\n * If you set this value, the default mouseover behavior will be disabled and you can control it as you need.\n * Supports .sync modifier\n * @values null, true, false\n */\n show: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Whether the tooltip should have a transition effect (fade).\n */\n transition: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the tooltip will have a delay when being focused or moused over.\n * @values true, false\n */\n delay: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Set a custom theme on the tooltip. See https://atomiks.github.io/tippyjs/v6/themes/\n */\n theme: {\n type: String,\n default: null,\n },\n\n /**\n * External anchor id to use in those cases the anchor can't be provided via the slot.\n * For instance, using the combobox's input as the anchor for the popover.\n */\n externalAnchor: {\n type: String,\n default: null,\n },\n },\n\n emits: [\n /**\n * Emitted when tooltip is shown or hidden\n *\n * @event shown\n * @type {Boolean}\n */\n 'shown',\n\n /**\n * Sync show value\n *\n * @event update:show\n */\n 'update:show',\n ],\n\n data () {\n return {\n TOOLTIP_KIND_MODIFIERS,\n hasSlotContent,\n tip: null,\n\n inTimer: null,\n\n // Internal state for whether the tooltip is shown. Changing the prop\n // will update this.\n internalShow: false,\n\n // this is where the placement currently is, this can be different than\n // the placement prop when there is not enough available room for the tip\n // to display and it uses a fallback placement.\n currentPlacement: this.placement,\n };\n },\n\n computed: {\n // eslint-disable-next-line complexity\n tippyProps () {\n return {\n offset: this.offset,\n delay: this.delay ? TOOLTIP_DELAY_MS : false,\n placement: this.placement,\n sticky: this.sticky,\n theme: this.inverted ? 'inverted' : this.theme,\n animation: this.transition ? 'fade' : false,\n // onShown only triggers when transition is truthy\n onShown: (tooltipInstance) => this.onShow(tooltipInstance, 'onShown'),\n // onShown will always be called, but it will be called before the animation is complete\n onShow: (tooltipInstance) => this.onShow(tooltipInstance, 'onShow'),\n onHidden: this.onHide,\n\n popperOptions: getPopperOptions({\n fallbackPlacements: this.fallbackPlacements,\n hasHideModifierEnabled: true,\n onChangePlacement: this.onChangePlacement,\n }),\n };\n },\n\n anchor () {\n return this.externalAnchor ? document.body.querySelector(this.externalAnchor) : getAnchor(this.$refs.anchor);\n },\n },\n\n watch: {\n\n tippyProps: {\n handler: 'setProps',\n deep: true,\n },\n\n show: {\n handler: function (show) {\n if (show !== null) {\n this.internalShow = show;\n }\n },\n\n immediate: true,\n },\n\n internalShow (value) {\n if (value) {\n this.setProps();\n this.tip.show();\n } else {\n this.tip.hide();\n }\n },\n\n sticky (sticky) {\n this.tip.setProps({\n sticky,\n });\n },\n },\n\n mounted () {\n if (!this.enabled && this.show != null) {\n console.warn('Tooltip: You cannot use both the enabled and show props at the same time.');\n console.warn('The show prop will be ignored.');\n }\n\n this.externalAnchor && this.addExternalAnchorEventListeners();\n this.tip = createTippy(this.anchor, this.initOptions());\n },\n\n beforeUnmount () {\n this.externalAnchor && this.removeExternalAnchorEventListeners();\n\n if (this.tip) {\n this.tip?.destroy();\n }\n },\n\n methods: {\n calculateAnchorZindex () {\n // if a modal is currently active render at modal-element z-index, otherwise at tooltip z-index\n if (this.$el.getRootNode()\n .querySelector('.d-modal[aria-hidden=\"false\"], .d-modal--transparent[aria-hidden=\"false\"]') ||\n // Special case because we don't have any dialtone drawer component yet. Render at 651 when\n // anchor of popover is within a drawer.\n this.$el.closest('.d-zi-drawer')) {\n return 651;\n } else {\n return 400;\n }\n },\n\n hasVisibleFocus () {\n return this.anchor.matches(':focus-visible');\n },\n\n onEnterAnchor (e) {\n if (this.delay && this.inTimer === null) {\n this.inTimer = setTimeout(() => {\n this.triggerShow(e);\n }, TOOLTIP_DELAY_MS);\n } else {\n this.triggerShow(e);\n }\n },\n\n triggerShow (e) {\n if (e.type === 'focusin') {\n // only show tooltips on visible focus when triggered via focus.\n // when the user is using the mouse they only want tooltips to display\n // on mouseover.\n //\n // Example: anchor of a popover is a button with tooltip.\n // closing it with the mouse would trigger the tooltip to display as\n // the anchor is focused on close. Not what we want.\n if (this.show === null && this.hasVisibleFocus()) {\n this.internalShow = true;\n }\n } else {\n if (this.show === null) this.internalShow = true;\n }\n },\n\n onLeaveAnchor (e) {\n if (e.type === 'keydown' && e.code !== 'Escape') return;\n\n clearTimeout(this.inTimer);\n this.inTimer = null;\n this.triggerHide();\n },\n\n triggerHide () {\n if (this.show === null) this.internalShow = false;\n },\n\n onChangePlacement (placement) {\n this.currentPlacement = placement;\n },\n\n onHide () {\n this.tip?.unmount();\n this.$emit('shown', false);\n if (this.show !== null) {\n this.$emit('update:show', false);\n }\n },\n\n onShow (tooltipInstance, callingMethod) {\n if (!this.tooltipHasContent(tooltipInstance)) {\n return false;\n }\n if (this.transition && callingMethod === 'onShow') {\n return;\n }\n this.$emit('shown', true);\n if (this.show !== null) {\n this.$emit('update:show', true);\n }\n },\n\n setProps () {\n if (this.tip && this.tip.setProps) {\n this.tip.setProps({\n ...this.tippyProps,\n // these need to be set here rather than in tippyProps because they are non-reactive\n appendTo: this.appendTo === 'body' ? this.anchor?.getRootNode()?.querySelector('body') : this.appendTo,\n zIndex: this.calculateAnchorZindex(),\n });\n }\n },\n\n onMount () {\n this.setProps();\n },\n\n tooltipHasContent (tooltipInstance) {\n // don't show tooltip when no content\n if (tooltipInstance.props.content.textContent.trim().length === 0) {\n return false;\n }\n return true;\n },\n\n // set initial options here. If any of the options need to dynamically change, they should be put in\n // tippyProps instead.\n initOptions () {\n const template = this.$refs.content;\n return {\n content: template,\n arrow: '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"7\"><path d=\"M 14.5,7 8,0 1.5,7 Z\"/></svg>',\n // transition duration - same as our custom fade delay in dialtone-globals.less\n duration: 180,\n interactive: false,\n trigger: 'manual',\n hideOnClick: false,\n // disable tooltip from displaying on touch devices\n touch: false,\n onMount: this.onMount,\n showOnCreate: this.internalShow,\n popperOptions: getPopperOptions({\n hasHideModifierEnabled: true,\n }),\n };\n },\n\n addExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n\n removeExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n },\n};\n</script>\n\n<style lang=\"less\">\n@import 'tippy.js/dist/svg-arrow.css';\n\n.tippy-box[data-reference-hidden] {\n visibility: hidden;\n pointer-events: none;\n}\n\n.tippy-box > .tippy-svg-arrow {\n fill: var(--dt-color-surface-contrast);\n}\n\n.tippy-box[data-theme~='inverted'] > .tippy-svg-arrow {\n fill: var(--dt-color-surface-moderate);\n}\n\n.tippy-box[data-animation='fade'][data-state='hidden'] {\n opacity: 0;\n}\n</style>\n"],"names":["getUniqueString","TOOLTIP_DIRECTIONS","TOOLTIP_STICKY_VALUES","POPOVER_APPEND_TO_VALUES","TOOLTIP_KIND_MODIFIERS","hasSlotContent","TOOLTIP_DELAY_MS","getPopperOptions","getAnchor","createTippy","_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_normalizeClass"],"mappings":"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"}
|
package/dist/vue3/lib/tooltip.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","sources":["../../components/tooltip/tooltip.vue"],"sourcesContent":["<template>\n <div data-qa=\"dt-tooltip-container\">\n <!-- disabling as the below events are for capturing events from interactive\n elements within the span rather than on the span itself -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <span\n v-if=\"!externalAnchor\"\n ref=\"anchor\"\n data-qa=\"dt-tooltip-anchor\"\n @focusin=\"onEnterAnchor\"\n @focusout=\"onLeaveAnchor\"\n @mouseenter=\"onEnterAnchor\"\n @mouseleave=\"onLeaveAnchor\"\n @keydown.esc=\"onLeaveAnchor\"\n >\n <!-- @slot Slot for the anchor element -->\n <slot\n name=\"anchor\"\n />\n </span>\n <div\n :id=\"id\"\n ref=\"content\"\n data-qa=\"dt-tooltip\"\n :class=\"[\n 'd-tooltip',\n {\n [ TOOLTIP_KIND_MODIFIERS.inverted ]: inverted,\n },\n contentClass,\n ]\"\n >\n <!-- In case when transitionend event doesn't work correct (for ex. tooltip component with custom trigger) -->\n <!-- after-leave event can be used instead of transitionend -->\n <!-- @slot Slot for the content, defaults to message prop -->\n <slot>\n {{ message }}\n </slot>\n </div>\n </div>\n</template>\n\n<script>\nimport {\n TOOLTIP_KIND_MODIFIERS,\n TOOLTIP_DIRECTIONS,\n TOOLTIP_STICKY_VALUES,\n TOOLTIP_DELAY_MS,\n} from './tooltip_constants.js';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '../popover/popover_constants';\nimport { getUniqueString, hasSlotContent } from '@/common/utils';\nimport {\n createTippy,\n getAnchor,\n getPopperOptions,\n} from '@/components/popover/tippy_utils';\n\n/**\n * A tooltip is a floating label that briefly explains an action, function, or an element.\n * Its content is exclusively text and shouldn't be vital information for users.\n * If richer media is desired, consider using a popover instead.\n * @see https://dialtone.dialpad.com/components/tooltip.html\n */\nexport default {\n name: 'DtTooltip',\n\n props: {\n /**\n * The id of the tooltip\n */\n id: {\n type: String,\n default () { return getUniqueString(); },\n },\n\n /**\n * If the popover does not fit in the direction described by \"placement\",\n * it will attempt to change its direction to the \"fallbackPlacements\"\n * if defined, otherwise it will automatically position to a new location\n * as it sees best fit. See\n * <a\n * class=\"d-link\"\n * href=\"https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements\"\n * target=\"_blank\"\n * >\n * Popper.js docs\n * </a>\n * */\n fallbackPlacements: {\n type: Array,\n default: () => ['auto'],\n },\n\n /**\n * If true, applies inverted styles to the tooltip\n * @values true, false\n */\n inverted: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Displaces the tooltip from its reference element\n * by the specified number of pixels. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#offset\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n */\n offset: {\n type: Array,\n default: () => [0, 12],\n },\n\n /**\n * The direction the popover displays relative to the anchor. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#placement\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values top, top-start, top-end,\n * right, right-start, right-end,\n * left, left-start, left-end,\n * bottom, bottom-start, bottom-end,\n * auto, auto-start, auto-end\n */\n placement: {\n type: String,\n default: 'top',\n validator (placement) {\n return TOOLTIP_DIRECTIONS.includes(placement);\n },\n },\n\n /**\n * If the tooltip sticks to the anchor. This is usually not needed, but can be needed\n * if the reference element's position is animating, or to automatically update the popover\n * position in those cases the DOM layout changes the reference element's position.\n * `true` enables it, `reference` only checks the \"reference\" rect for changes and `popper` only\n * checks the \"popper\" rect for changes. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#sticky\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values true, false, reference, popper\n */\n sticky: {\n type: [Boolean, String],\n default: true,\n validator: (sticky) => {\n return TOOLTIP_STICKY_VALUES.includes(sticky);\n },\n },\n\n /**\n * Sets the element to which the tooltip is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * This prop is not reactive, must be set on initial render.\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Additional css classes for the tooltip content element.\n * Can accept all of String, Object, and Array, i.e. has the\n * same api as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * A provided message for the tooltip content\n */\n message: {\n type: String,\n default: '',\n },\n\n /**\n * Controls whether hover/focus causes the tooltip to appear.\n * Cannot be combined with the show prop. show value will be ignored.\n * by default this is true, if you override with false, the tooltip will never show up.\n */\n enabled: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Controls whether the tooltip is shown. Leaving this null will have the tooltip trigger on mouseover by default.\n * If you set this value, the default mouseover behavior will be disabled and you can control it as you need.\n * Supports .sync modifier\n * @values null, true, false\n */\n show: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Whether the tooltip should have a transition effect (fade).\n */\n transition: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the tooltip will have a delay when being focused or moused over.\n * @values true, false\n */\n delay: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Set a custom theme on the tooltip. See https://atomiks.github.io/tippyjs/v6/themes/\n */\n theme: {\n type: String,\n default: undefined,\n },\n\n /**\n * External anchor id to use in those cases the anchor can't be provided via the slot.\n * For instance, using the combobox's input as the anchor for the popover.\n */\n externalAnchor: {\n type: String,\n default: null,\n },\n },\n\n emits: [\n /**\n * Emitted when tooltip is shown or hidden\n *\n * @event shown\n * @type {Boolean}\n */\n 'shown',\n\n /**\n * Sync show value\n *\n * @event update:show\n */\n 'update:show',\n ],\n\n data () {\n return {\n TOOLTIP_KIND_MODIFIERS,\n hasSlotContent,\n tip: null,\n\n inTimer: null,\n\n // Internal state for whether the tooltip is shown. Changing the prop\n // will update this.\n internalShow: false,\n\n // this is where the placement currently is, this can be different than\n // the placement prop when there is not enough available room for the tip\n // to display and it uses a fallback placement.\n currentPlacement: this.placement,\n };\n },\n\n computed: {\n // eslint-disable-next-line complexity\n tippyProps () {\n return {\n offset: this.offset,\n delay: this.delay ? TOOLTIP_DELAY_MS : false,\n placement: this.placement,\n sticky: this.sticky,\n theme: this.inverted ? 'inverted' : this.theme,\n animation: this.transition ? 'fade' : false,\n // onShown only triggers when transition is truthy\n onShown: (tooltipInstance) => this.onShow(tooltipInstance, 'onShown'),\n // onShown will always be called, but it will be called before the animation is complete\n onShow: (tooltipInstance) => this.onShow(tooltipInstance, 'onShow'),\n onHidden: this.onHide,\n\n popperOptions: getPopperOptions({\n fallbackPlacements: this.fallbackPlacements,\n hasHideModifierEnabled: true,\n onChangePlacement: this.onChangePlacement,\n }),\n };\n },\n\n anchor () {\n return this.externalAnchor ? document.body.querySelector(this.externalAnchor) : getAnchor(this.$refs.anchor);\n },\n },\n\n watch: {\n\n tippyProps: {\n handler: 'setProps',\n deep: true,\n },\n\n show: {\n handler: function (show) {\n if (show !== null) {\n this.internalShow = show;\n }\n },\n\n immediate: true,\n },\n\n internalShow (value) {\n if (value) {\n this.setProps();\n this.tip.show();\n } else {\n this.tip.hide();\n }\n },\n\n sticky (sticky) {\n this.tip.setProps({\n sticky,\n });\n },\n },\n\n mounted () {\n if (!this.enabled && this.show != null) {\n console.warn('Tooltip: You cannot use both the enabled and show props at the same time.');\n console.warn('The show prop will be ignored.');\n }\n\n this.externalAnchor && this.addExternalAnchorEventListeners();\n this.tip = createTippy(this.anchor, this.initOptions());\n },\n\n beforeUnmount () {\n this.externalAnchor && this.removeExternalAnchorEventListeners();\n\n if (this.tip) {\n this.tip?.destroy();\n }\n },\n\n methods: {\n calculateAnchorZindex () {\n // if a modal is currently active render at modal-element z-index, otherwise at tooltip z-index\n if (this.$el.getRootNode()\n .querySelector('.d-modal[aria-hidden=\"false\"], .d-modal--transparent[aria-hidden=\"false\"]') ||\n // Special case because we don't have any dialtone drawer component yet. Render at 651 when\n // anchor of popover is within a drawer.\n this.$el.closest('.d-zi-drawer')) {\n return 651;\n } else {\n return 400;\n }\n },\n\n hasVisibleFocus () {\n return this.anchor.matches(':focus-visible');\n },\n\n onEnterAnchor (e) {\n if (this.delay && this.inTimer === null) {\n this.inTimer = setTimeout(() => {\n this.triggerShow(e);\n }, TOOLTIP_DELAY_MS);\n } else {\n this.triggerShow(e);\n }\n },\n\n triggerShow (e) {\n if (e.type === 'focusin') {\n // only show tooltips on visible focus when triggered via focus.\n // when the user is using the mouse they only want tooltips to display\n // on mouseover.\n //\n // Example: anchor of a popover is a button with tooltip.\n // closing it with the mouse would trigger the tooltip to display as\n // the anchor is focused on close. Not what we want.\n if (this.show === null && this.hasVisibleFocus()) {\n this.internalShow = true;\n }\n } else {\n if (this.show === null) this.internalShow = true;\n }\n },\n\n onLeaveAnchor (e) {\n if (e.type === 'keydown' && e.code !== 'Escape') return;\n\n clearTimeout(this.inTimer);\n this.inTimer = null;\n this.triggerHide();\n },\n\n triggerHide () {\n if (this.show === null) this.internalShow = false;\n },\n\n onChangePlacement (placement) {\n this.currentPlacement = placement;\n },\n\n onHide () {\n this.tip?.unmount();\n this.$emit('shown', false);\n if (this.show !== null) {\n this.$emit('update:show', false);\n }\n },\n\n onShow (tooltipInstance, callingMethod) {\n if (!this.tooltipHasContent(tooltipInstance)) {\n return false;\n }\n if (this.transition && callingMethod === 'onShow') {\n return;\n }\n this.$emit('shown', true);\n if (this.show !== null) {\n this.$emit('update:show', true);\n }\n },\n\n setProps () {\n if (this.tip && this.tip.setProps) {\n this.tip.setProps({\n ...this.tippyProps,\n // these need to be set here rather than in tippyProps because they are non-reactive\n appendTo: this.appendTo === 'body' ? this.anchor?.getRootNode()?.querySelector('body') : this.appendTo,\n zIndex: this.calculateAnchorZindex(),\n });\n }\n },\n\n onMount () {\n this.setProps();\n },\n\n tooltipHasContent (tooltipInstance) {\n // don't show tooltip when no content\n if (tooltipInstance.props.content.textContent.trim().length === 0) {\n return false;\n }\n return true;\n },\n\n // set initial options here. If any of the options need to dynamically change, they should be put in\n // tippyProps instead.\n initOptions () {\n const template = this.$refs.content;\n return {\n content: template,\n arrow: '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"7\"><path d=\"M 14.5,7 8,0 1.5,7 Z\"/></svg>',\n // transition duration - same as our custom fade delay in dialtone-globals.less\n duration: 180,\n interactive: false,\n trigger: 'manual',\n hideOnClick: false,\n // disable tooltip from displaying on touch devices\n touch: false,\n onMount: this.onMount,\n showOnCreate: this.internalShow,\n popperOptions: getPopperOptions({\n hasHideModifierEnabled: true,\n }),\n };\n },\n\n addExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n\n removeExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n },\n};\n</script>\n\n<style lang=\"less\">\n@import 'tippy.js/dist/svg-arrow.css';\n\n.tippy-box[data-reference-hidden] {\n visibility: hidden;\n pointer-events: none;\n}\n\n.tippy-box > .tippy-svg-arrow {\n fill: var(--dt-color-surface-contrast);\n}\n\n.tippy-box[data-theme~='inverted'] > .tippy-svg-arrow {\n fill: var(--dt-color-surface-moderate);\n}\n\n.tippy-box[data-animation='fade'][data-state='hidden'] {\n opacity: 0;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_normalizeClass"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tooltip.js","sources":["../../components/tooltip/tooltip.vue"],"sourcesContent":["<template>\n <div data-qa=\"dt-tooltip-container\">\n <!-- disabling as the below events are for capturing events from interactive\n elements within the span rather than on the span itself -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <span\n v-if=\"!externalAnchor\"\n ref=\"anchor\"\n data-qa=\"dt-tooltip-anchor\"\n @focusin=\"onEnterAnchor\"\n @focusout=\"onLeaveAnchor\"\n @mouseenter=\"onEnterAnchor\"\n @mouseleave=\"onLeaveAnchor\"\n @keydown.esc=\"onLeaveAnchor\"\n >\n <!-- @slot Slot for the anchor element -->\n <slot\n name=\"anchor\"\n />\n </span>\n <div\n :id=\"id\"\n ref=\"content\"\n data-qa=\"dt-tooltip\"\n :class=\"[\n 'd-tooltip',\n {\n [ TOOLTIP_KIND_MODIFIERS.inverted ]: inverted,\n },\n contentClass,\n ]\"\n >\n <!-- In case when transitionend event doesn't work correct (for ex. tooltip component with custom trigger) -->\n <!-- after-leave event can be used instead of transitionend -->\n <!-- @slot Slot for the content, defaults to message prop -->\n <slot>\n {{ message }}\n </slot>\n </div>\n </div>\n</template>\n\n<script>\nimport {\n TOOLTIP_KIND_MODIFIERS,\n TOOLTIP_DIRECTIONS,\n TOOLTIP_STICKY_VALUES,\n TOOLTIP_DELAY_MS,\n} from './tooltip_constants.js';\nimport {\n POPOVER_APPEND_TO_VALUES,\n} from '../popover/popover_constants';\nimport { getUniqueString, hasSlotContent } from '@/common/utils';\nimport {\n createTippy,\n getAnchor,\n getPopperOptions,\n} from '@/components/popover/tippy_utils';\n\n/**\n * A tooltip is a floating label that briefly explains an action, function, or an element.\n * Its content is exclusively text and shouldn't be vital information for users.\n * If richer media is desired, consider using a popover instead.\n * @see https://dialtone.dialpad.com/components/tooltip.html\n */\nexport default {\n name: 'DtTooltip',\n\n props: {\n /**\n * The id of the tooltip\n */\n id: {\n type: String,\n default () { return getUniqueString(); },\n },\n\n /**\n * If the popover does not fit in the direction described by \"placement\",\n * it will attempt to change its direction to the \"fallbackPlacements\"\n * if defined, otherwise it will automatically position to a new location\n * as it sees best fit. See\n * <a\n * class=\"d-link\"\n * href=\"https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements\"\n * target=\"_blank\"\n * >\n * Popper.js docs\n * </a>\n * */\n fallbackPlacements: {\n type: Array,\n default: () => ['auto'],\n },\n\n /**\n * If true, applies inverted styles to the tooltip\n * @values true, false\n */\n inverted: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Displaces the tooltip from its reference element\n * by the specified number of pixels. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#offset\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n */\n offset: {\n type: Array,\n default: () => [0, 12],\n },\n\n /**\n * The direction the popover displays relative to the anchor. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#placement\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values top, top-start, top-end,\n * right, right-start, right-end,\n * left, left-start, left-end,\n * bottom, bottom-start, bottom-end,\n * auto, auto-start, auto-end\n */\n placement: {\n type: String,\n default: 'top',\n validator (placement) {\n return TOOLTIP_DIRECTIONS.includes(placement);\n },\n },\n\n /**\n * If the tooltip sticks to the anchor. This is usually not needed, but can be needed\n * if the reference element's position is animating, or to automatically update the popover\n * position in those cases the DOM layout changes the reference element's position.\n * `true` enables it, `reference` only checks the \"reference\" rect for changes and `popper` only\n * checks the \"popper\" rect for changes. See\n * <a\n * class=\"d-link\"\n * href=\"https://atomiks.github.io/tippyjs/v6/all-props/#sticky\"\n * target=\"_blank\"\n * >\n * Tippy.js docs\n * </a>\n * @values true, false, reference, popper\n */\n sticky: {\n type: [Boolean, String],\n default: true,\n validator: (sticky) => {\n return TOOLTIP_STICKY_VALUES.includes(sticky);\n },\n },\n\n /**\n * Sets the element to which the tooltip is going to append to.\n * 'body' will append to the nearest body (supports shadow DOM).\n * This prop is not reactive, must be set on initial render.\n * @values 'body', 'parent', HTMLElement,\n */\n appendTo: {\n type: [HTMLElement, String],\n default: 'body',\n validator: appendTo => {\n return POPOVER_APPEND_TO_VALUES.includes(appendTo) ||\n (appendTo instanceof HTMLElement);\n },\n },\n\n /**\n * Additional css classes for the tooltip content element.\n * Can accept all of String, Object, and Array, i.e. has the\n * same api as Vue's built-in handling of the class attribute.\n */\n contentClass: {\n type: [String, Object, Array],\n default: '',\n },\n\n /**\n * A provided message for the tooltip content\n */\n message: {\n type: String,\n default: '',\n },\n\n /**\n * Controls whether hover/focus causes the tooltip to appear.\n * Cannot be combined with the show prop. show value will be ignored.\n * by default this is true, if you override with false, the tooltip will never show up.\n */\n enabled: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Controls whether the tooltip is shown. Leaving this null will have the tooltip trigger on mouseover by default.\n * If you set this value, the default mouseover behavior will be disabled and you can control it as you need.\n * Supports .sync modifier\n * @values null, true, false\n */\n show: {\n type: Boolean,\n default: null,\n },\n\n /**\n * Whether the tooltip should have a transition effect (fade).\n */\n transition: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Whether the tooltip will have a delay when being focused or moused over.\n * @values true, false\n */\n delay: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Set a custom theme on the tooltip. See https://atomiks.github.io/tippyjs/v6/themes/\n */\n theme: {\n type: String,\n default: null,\n },\n\n /**\n * External anchor id to use in those cases the anchor can't be provided via the slot.\n * For instance, using the combobox's input as the anchor for the popover.\n */\n externalAnchor: {\n type: String,\n default: null,\n },\n },\n\n emits: [\n /**\n * Emitted when tooltip is shown or hidden\n *\n * @event shown\n * @type {Boolean}\n */\n 'shown',\n\n /**\n * Sync show value\n *\n * @event update:show\n */\n 'update:show',\n ],\n\n data () {\n return {\n TOOLTIP_KIND_MODIFIERS,\n hasSlotContent,\n tip: null,\n\n inTimer: null,\n\n // Internal state for whether the tooltip is shown. Changing the prop\n // will update this.\n internalShow: false,\n\n // this is where the placement currently is, this can be different than\n // the placement prop when there is not enough available room for the tip\n // to display and it uses a fallback placement.\n currentPlacement: this.placement,\n };\n },\n\n computed: {\n // eslint-disable-next-line complexity\n tippyProps () {\n return {\n offset: this.offset,\n delay: this.delay ? TOOLTIP_DELAY_MS : false,\n placement: this.placement,\n sticky: this.sticky,\n theme: this.inverted ? 'inverted' : this.theme,\n animation: this.transition ? 'fade' : false,\n // onShown only triggers when transition is truthy\n onShown: (tooltipInstance) => this.onShow(tooltipInstance, 'onShown'),\n // onShown will always be called, but it will be called before the animation is complete\n onShow: (tooltipInstance) => this.onShow(tooltipInstance, 'onShow'),\n onHidden: this.onHide,\n\n popperOptions: getPopperOptions({\n fallbackPlacements: this.fallbackPlacements,\n hasHideModifierEnabled: true,\n onChangePlacement: this.onChangePlacement,\n }),\n };\n },\n\n anchor () {\n return this.externalAnchor ? document.body.querySelector(this.externalAnchor) : getAnchor(this.$refs.anchor);\n },\n },\n\n watch: {\n\n tippyProps: {\n handler: 'setProps',\n deep: true,\n },\n\n show: {\n handler: function (show) {\n if (show !== null) {\n this.internalShow = show;\n }\n },\n\n immediate: true,\n },\n\n internalShow (value) {\n if (value) {\n this.setProps();\n this.tip.show();\n } else {\n this.tip.hide();\n }\n },\n\n sticky (sticky) {\n this.tip.setProps({\n sticky,\n });\n },\n },\n\n mounted () {\n if (!this.enabled && this.show != null) {\n console.warn('Tooltip: You cannot use both the enabled and show props at the same time.');\n console.warn('The show prop will be ignored.');\n }\n\n this.externalAnchor && this.addExternalAnchorEventListeners();\n this.tip = createTippy(this.anchor, this.initOptions());\n },\n\n beforeUnmount () {\n this.externalAnchor && this.removeExternalAnchorEventListeners();\n\n if (this.tip) {\n this.tip?.destroy();\n }\n },\n\n methods: {\n calculateAnchorZindex () {\n // if a modal is currently active render at modal-element z-index, otherwise at tooltip z-index\n if (this.$el.getRootNode()\n .querySelector('.d-modal[aria-hidden=\"false\"], .d-modal--transparent[aria-hidden=\"false\"]') ||\n // Special case because we don't have any dialtone drawer component yet. Render at 651 when\n // anchor of popover is within a drawer.\n this.$el.closest('.d-zi-drawer')) {\n return 651;\n } else {\n return 400;\n }\n },\n\n hasVisibleFocus () {\n return this.anchor.matches(':focus-visible');\n },\n\n onEnterAnchor (e) {\n if (this.delay && this.inTimer === null) {\n this.inTimer = setTimeout(() => {\n this.triggerShow(e);\n }, TOOLTIP_DELAY_MS);\n } else {\n this.triggerShow(e);\n }\n },\n\n triggerShow (e) {\n if (e.type === 'focusin') {\n // only show tooltips on visible focus when triggered via focus.\n // when the user is using the mouse they only want tooltips to display\n // on mouseover.\n //\n // Example: anchor of a popover is a button with tooltip.\n // closing it with the mouse would trigger the tooltip to display as\n // the anchor is focused on close. Not what we want.\n if (this.show === null && this.hasVisibleFocus()) {\n this.internalShow = true;\n }\n } else {\n if (this.show === null) this.internalShow = true;\n }\n },\n\n onLeaveAnchor (e) {\n if (e.type === 'keydown' && e.code !== 'Escape') return;\n\n clearTimeout(this.inTimer);\n this.inTimer = null;\n this.triggerHide();\n },\n\n triggerHide () {\n if (this.show === null) this.internalShow = false;\n },\n\n onChangePlacement (placement) {\n this.currentPlacement = placement;\n },\n\n onHide () {\n this.tip?.unmount();\n this.$emit('shown', false);\n if (this.show !== null) {\n this.$emit('update:show', false);\n }\n },\n\n onShow (tooltipInstance, callingMethod) {\n if (!this.tooltipHasContent(tooltipInstance)) {\n return false;\n }\n if (this.transition && callingMethod === 'onShow') {\n return;\n }\n this.$emit('shown', true);\n if (this.show !== null) {\n this.$emit('update:show', true);\n }\n },\n\n setProps () {\n if (this.tip && this.tip.setProps) {\n this.tip.setProps({\n ...this.tippyProps,\n // these need to be set here rather than in tippyProps because they are non-reactive\n appendTo: this.appendTo === 'body' ? this.anchor?.getRootNode()?.querySelector('body') : this.appendTo,\n zIndex: this.calculateAnchorZindex(),\n });\n }\n },\n\n onMount () {\n this.setProps();\n },\n\n tooltipHasContent (tooltipInstance) {\n // don't show tooltip when no content\n if (tooltipInstance.props.content.textContent.trim().length === 0) {\n return false;\n }\n return true;\n },\n\n // set initial options here. If any of the options need to dynamically change, they should be put in\n // tippyProps instead.\n initOptions () {\n const template = this.$refs.content;\n return {\n content: template,\n arrow: '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"7\"><path d=\"M 14.5,7 8,0 1.5,7 Z\"/></svg>',\n // transition duration - same as our custom fade delay in dialtone-globals.less\n duration: 180,\n interactive: false,\n trigger: 'manual',\n hideOnClick: false,\n // disable tooltip from displaying on touch devices\n touch: false,\n onMount: this.onMount,\n showOnCreate: this.internalShow,\n popperOptions: getPopperOptions({\n hasHideModifierEnabled: true,\n }),\n };\n },\n\n addExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.addEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n\n removeExternalAnchorEventListeners () {\n ['focusin', 'mouseenter'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onEnterAnchor(event));\n });\n ['focusout', 'mouseleave', 'keydown'].forEach(listener => {\n this.anchor.removeEventListener(listener, (event) => this.onLeaveAnchor(event));\n });\n },\n },\n};\n</script>\n\n<style lang=\"less\">\n@import 'tippy.js/dist/svg-arrow.css';\n\n.tippy-box[data-reference-hidden] {\n visibility: hidden;\n pointer-events: none;\n}\n\n.tippy-box > .tippy-svg-arrow {\n fill: var(--dt-color-surface-contrast);\n}\n\n.tippy-box[data-theme~='inverted'] > .tippy-svg-arrow {\n fill: var(--dt-color-surface-moderate);\n}\n\n.tippy-box[data-animation='fade'][data-state='hidden'] {\n opacity: 0;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_renderSlot","_createElementVNode","_normalizeClass"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
2
|
focusEmojiSelector: typeof focusEmojiSelector;
|
|
3
3
|
focusLastEmoji: typeof focusLastEmoji;
|
|
4
|
-
$emit: (event: "
|
|
4
|
+
$emit: (event: "focus-search-input" | "focus-skin-selector" | "highlighted-emoji" | "selected-emoji" | "scroll-into-tab" | "is-scrolling", ...args: any[]) => void;
|
|
5
5
|
$props: {
|
|
6
6
|
readonly [x: string]: any;
|
|
7
7
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
declare const _default: import("vue").DefineComponent<{}, {
|
|
2
2
|
focusTabset: typeof focusTabset;
|
|
3
|
-
$emit: (event: "selected-tabset" | "
|
|
3
|
+
$emit: (event: "selected-tabset" | "focus-search-input" | "focus-skin-selector", ...args: any[]) => void;
|
|
4
4
|
$props: {
|
|
5
5
|
readonly [x: string]: any;
|
|
6
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji_tabset.vue.d.ts","sourceRoot":"","sources":["../../../../../components/emoji_picker/modules/emoji_tabset.vue.js"],"names":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"emoji_tabset.vue.d.ts","sourceRoot":"","sources":["../../../../../components/emoji_picker/modules/emoji_tabset.vue.js"],"names":[],"mappings":";;;;;;;;AAyHA,qCAEC"}
|
|
@@ -155,7 +155,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
155
155
|
*/
|
|
156
156
|
theme: {
|
|
157
157
|
type: StringConstructor;
|
|
158
|
-
default:
|
|
158
|
+
default: null;
|
|
159
159
|
};
|
|
160
160
|
/**
|
|
161
161
|
* External anchor id to use in those cases the anchor can't be provided via the slot.
|
|
@@ -183,7 +183,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
183
183
|
delay: number | boolean;
|
|
184
184
|
placement: string;
|
|
185
185
|
sticky: string | boolean;
|
|
186
|
-
theme: string
|
|
186
|
+
theme: string;
|
|
187
187
|
animation: string | boolean;
|
|
188
188
|
onShown: (tooltipInstance: any) => false | undefined;
|
|
189
189
|
onShow: (tooltipInstance: any) => false | undefined;
|
|
@@ -429,7 +429,7 @@ declare const _default: import("vue").DefineComponent<{
|
|
|
429
429
|
*/
|
|
430
430
|
theme: {
|
|
431
431
|
type: StringConstructor;
|
|
432
|
-
default:
|
|
432
|
+
default: null;
|
|
433
433
|
};
|
|
434
434
|
/**
|
|
435
435
|
* External anchor id to use in those cases the anchor can't be provided via the slot.
|