@empathyco/x-components
Version:
Empathy X Components
229 lines (226 loc) • 8.11 kB
JavaScript
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