UNPKG

@empathyco/x-components

Version:
229 lines (226 loc) • 8.11 kB
import { defineComponent, ref, onMounted } from 'vue'; import { use$x } from '../../../composables/use-_x.js'; import { useState } from '../../../composables/use-state.js'; import { debounce } from '../../../utils/debounce.js'; import { searchBoxXModule } from '../x-module.js'; /** * This component renders an input field that allows the user to type a query. It also reacts to * query changes through event listening. * * @public */ var _sfc_main = defineComponent({ name: 'SearchInput', xModule: searchBoxXModule.name, props: { /** * Maximum characters allowed in the input search. */ maxLength: { type: Number, default: 64, }, /** * Allows input autofocus when the search field is rendered. */ autofocus: { type: Boolean, default: true, }, /** * Enables the auto-accept query after debounce. */ instant: { type: Boolean, default: true, }, /** * Debounce time for the instant. */ instantDebounceInMs: { type: Number, default: 500, }, }, setup(props) { const $x = use$x(); const { query } = useState('searchBox'); const inputElement = ref(); let debouncedUserAcceptedAQuery; /** * Generates the {@link WireMetadata} object omitting the moduleName. * * @returns The {@link WireMetadata} object omitting the moduleName. * @internal */ const createEventMetadata = () => { return { target: inputElement.value, feature: 'search_box', }; }; /** * Emits {@link XEventsTypes.UserAcceptedAQuery} event. * * @remarks It is necessary in a separated method to use it as the parameter of debounce in * emitDebouncedUserAcceptedAQuery method. * @internal * @param query - The query that will be emitted. */ const emitUserAcceptedAQuery = (query) => { $x.emit('UserAcceptedAQuery', query, createEventMetadata()); }; /** * Emits {@link XEventsTypes.UserAcceptedAQuery} event with a debounce configured in * `instantDebounceInMs` prop. * * @internal * @param query - The query that will be emitted. */ const emitDebouncedUserAcceptedAQuery = (query) => { if (props.instant) { if (!debouncedUserAcceptedAQuery) { debouncedUserAcceptedAQuery = debounce(emitUserAcceptedAQuery, props.instantDebounceInMs); } debouncedUserAcceptedAQuery(query); } }; /** * Emits event {@link SearchBoxXEvents.UserHoveredInSearchBox} when search box is hovered in. * * @internal */ const emitUserHoveredInSearchBox = () => { $x.emit('UserHoveredInSearchBox', undefined, { target: inputElement.value }); }; /** * Emits event {@link SearchBoxXEvents.UserHoveredOutSearchBox} when search box is hovered out. * * @internal */ const emitUserHoveredOutSearchBox = () => { $x.emit('UserHoveredOutSearchBox', undefined, { target: inputElement.value }); }; /** * Emits event {@link SearchBoxXEvents.UserBlurredSearchBox} when search box loses focus. * * @internal */ const emitUserBlurredSearchBox = () => { $x.emit('UserBlurredSearchBox', undefined, { target: inputElement.value }); }; /** * Emits event {@link SearchBoxXEvents.UserClickedSearchBox} when user clicks the search input. * * @internal */ const emitUserClickedSearchBox = () => { $x.emit('UserClickedSearchBox', undefined, { target: inputElement.value }); }; /** * Emits event {@link SearchBoxXEvents.UserFocusedSearchBox} when search box gains focus. * * @internal */ const emitUserFocusedSearchBox = () => { $x.emit('UserFocusedSearchBox', undefined, { target: inputElement.value }); }; /** * Emits event {@link SearchBoxXEvents.UserIsTypingAQuery} when the user typed/pasted something * into the search-box. Also emits event {@link SearchBoxXEvents.UserClearedQuery} when the user * removes all characters in the search-box. * * @internal */ const emitUserIsTypingAQueryEvents = () => { const query = inputElement.value?.value ?? ''; $x.emit('UserIsTypingAQuery', query, { target: inputElement.value }); if (query.trim()) { emitDebouncedUserAcceptedAQuery(query); } else { cancelDebouncedUserAcceptedAQuery(); } }; /** * Emits event {@link XEventsTypes.UserPressedArrowKey} when the user pressed an arrow key. * * @param event - The keyboard event with the arrow key pressed. * @internal */ const emitUserPressedArrowKey = (event) => { $x.emit('UserPressedArrowKey', event.key, createEventMetadata()); }; /** * Emits multiple events when the user pressed the enter key. * * @remarks * Emitted events are: * {@link SearchBoxXEvents.UserPressedEnterKey} * {@link XEventsTypes.UserAcceptedAQuery} * * @internal */ const emitUserPressedEnterKey = () => { const query = inputElement.value?.value.trim(); if (!!query && query.length > 0) { $x.emit('UserPressedEnterKey', query, createEventMetadata()); emitUserAcceptedAQuery(query); } inputElement.value?.blur(); }; /** * Prevents the user from either typing or pasting special characters in the input field. * * @internal * @param event - The event that will be checked for special characters. */ const preventSpecialKey = (event) => { if (/[<>]/.test(event.data ?? '')) { event.preventDefault(); } }; /** * When event {@link XEventsTypes.UserReachedEmpathizeTop} or * {@link SearchBoxXEvents.UserPressedClearSearchBoxButton} * are emitted the search input is focused. * * @internal */ function focusInput() { inputElement.value?.focus(); } ['UserReachedEmpathizeTop', 'UserPressedClearSearchBoxButton'].forEach(event => $x.on(event, false).subscribe(focusInput)); /** * When event {@link XEventsTypes.UserAcceptedAQuery} or * {@link SearchBoxXEvents.UserClearedQuery} are emitted the pending debounced emit * {@link XEvent} `UserAcceptedAQuery` is canceled. * * @internal */ function cancelDebouncedUserAcceptedAQuery() { debouncedUserAcceptedAQuery?.cancel(); } ['UserAcceptedAQuery', 'UserClearedQuery'].forEach(event => $x.on(event, false).subscribe(cancelDebouncedUserAcceptedAQuery)); onMounted(() => { if (props.autofocus) { focusInput(); } }); return { query, inputElement, emitUserHoveredInSearchBox, emitUserHoveredOutSearchBox, emitUserBlurredSearchBox, emitUserClickedSearchBox, emitUserFocusedSearchBox, emitUserIsTypingAQueryEvents, emitUserPressedEnterKey, emitUserPressedArrowKey, preventSpecialKey, }; }, }); export { _sfc_main as default }; //# sourceMappingURL=search-input.vue2.js.map