UNPKG

@empathyco/x-components

Version:
186 lines (183 loc) 6.12 kB
import { defineComponent, ref, computed, watch, onBeforeUnmount } from 'vue'; import { animateTranslate } from '../../../components/animations/animate-translate/animate-translate.factory.js'; import { use$x } from '../../../composables/use-_x.js'; import { useState } from '../../../composables/use-state.js'; import { AnimationProp } from '../../../types/animation-prop.js'; import { searchBoxXModule } from '../x-module.js'; /**. * This component renders an animated placeholder for the search input in the shape of a list of * iterating messages that can be configured to happen always or only when hovering the input * * @public */ var _sfc_main = defineComponent({ name: 'SearchInputPlaceholder', xModule: searchBoxXModule.name, props: { /** * List of messages to animate. * * @public */ messages: { type: Array, required: true, }, /** * Animation component used for the messages. * * @public */ animation: { type: AnimationProp, default: () => animateTranslate('bottom-to-top'), }, /** * Time in milliseconds during which each message is visible. * * @public */ animationIntervalMs: { type: Number, default: 1500, }, /** * Whether the messages animation is active only when hovering the search input or always. * * @public */ animateOnlyOnHover: Boolean, }, setup(props) { const $x = use$x(); /**. * The search box written query * * @internal */ const { query } = useState('searchBox'); /**. * The search box hover status * * @internal */ const isSearchBoxHovered = ref(false); /**. * The search box focus status * * @internal */ const isSearchBoxFocused = ref(false); /** * The index used to point to the current animation message in the list. * * @internal */ const animationMessageIndex = ref(0); /** * The interval used for the animation. * * @internal */ const animationInterval = ref(undefined); /** * The visibility state of the component. * * @returns The visibility state based on the search input state (query & focus). * * @internal */ const isVisible = computed(() => !query.value && !isSearchBoxFocused.value); /** * The animation state of the component. * * @returns Whether the animation is active or not. * * @internal */ const isBeingAnimated = computed(() => isVisible.value && (!props.animateOnlyOnHover || isSearchBoxHovered.value)); /** * The current placeholder message. * * @returns The message to display as placeholder at any moment. * * @internal */ const message = computed(() => isBeingAnimated.value ? props.messages[animationMessageIndex.value] : props.messages[0]); /** * Clears the interval used for the animation. * * @internal */ const stopAnimationInterval = () => { if (animationInterval.value) { clearInterval(animationInterval.value); animationInterval.value = undefined; } }; /** * Increments animation message index; if the new index exceeds the messages list length, it is * reset to 0. * * @internal */ const incrementAnimationMessageIndex = () => { animationMessageIndex.value = (animationMessageIndex.value + 1) % props.messages.length; }; $x.on('UserHoveredInSearchBox', false).subscribe(() => (isSearchBoxHovered.value = true)); $x.on('UserHoveredOutSearchBox', false).subscribe(() => (isSearchBoxHovered.value = false)); $x.on('UserFocusedSearchBox', false).subscribe(() => (isSearchBoxFocused.value = true)); $x.on('UserBlurredSearchBox', false).subscribe(() => (isSearchBoxFocused.value = false)); /** * Starts or stops the animation depending on the current animation state. * * @internal */ const resetAnimation = () => { stopAnimationInterval(); if (isBeingAnimated.value) { animationInterval.value = window.setInterval(() => { incrementAnimationMessageIndex(); }, props.animationIntervalMs); } }; watch(() => 'animationIntervalMs', resetAnimation); /** * Resets the animation message index to zero. * * @internal */ const resetAnimationMessageIndex = () => { animationMessageIndex.value = 0; }; watch(() => props.messages, () => { resetAnimationMessageIndex(); resetAnimation(); }, { deep: true }); /** * Sets the animation message index with the right value for the next future iteration when the * current one stops,assuring the user will see always a new message on each animation state * change. * * @internal */ watch(isBeingAnimated, () => { if (!isBeingAnimated.value) { if (props.animateOnlyOnHover) { resetAnimationMessageIndex(); } incrementAnimationMessageIndex(); } resetAnimation(); }, { immediate: true }); onBeforeUnmount(() => { stopAnimationInterval(); }); return { isVisible, message, }; }, }); export { _sfc_main as default }; //# sourceMappingURL=search-input-placeholder.vue2.js.map