import { useSearchState, DirectAnswerType, DirectAnswer as DirectAnswerData, UnknownFieldValueDirectAnswer, } from '@yext/search-headless-react'; import { ThumbsFeedbackCssClasses, ThumbsFeedback, builtInCssClasses as thumbsFeedbackCssClasses } from './ThumbsFeedback'; import { twMerge, useComposedCssClasses } from '../hooks/useComposedCssClasses'; import { useCardAnalyticsCallback } from '../hooks'; import { useCardFeedbackCallback } from '../hooks'; import { FieldValueDirectAnswer } from './FieldValueDirectAnswer'; import { FeaturedSnippetDirectAnswer } from './FeaturedSnippetDirectAnswer'; import React from 'react'; /** * Props for {@link UnknownFieldTypeDisplayComponent}. * * @public */ export interface UnknownFieldTypeDisplayProps { result: UnknownFieldValueDirectAnswer } /** * A React component interface to render results with "unknown" field type in field value direct answer. * * @public */ export type UnknownFieldTypeDisplayComponent = ( props: UnknownFieldTypeDisplayProps ) => React.JSX.Element; /** * Props for {@link DirectAnswer}. * * @public */ export interface DirectAnswerProps { /** A component to handle rendering results with "unknown" field type in field value direct answer. */ UnknownFieldTypeDisplay?: UnknownFieldTypeDisplayComponent, /** CSS classes for customizing the component styling. */ customCssClasses?: DirectAnswerCssClasses } /** * The CSS class interface for {@link DirectAnswer}. * * @public */ export interface DirectAnswerCssClasses extends ThumbsFeedbackCssClasses { directAnswerContainer?: string, directAnswerLoading?: string, answer?: string, description?: string, content?: string, highlighted?: string, answerContainer?: string } const builtInCssClasses: Readonly = { directAnswerContainer: '', directAnswerLoading: 'opacity-50', answer: 'font-bold text-xl text-neutral-dark', description: 'text-neutral', content: 'mt-4', highlighted: 'bg-primary-light', answerContainer: 'p-4 border border-gray-200 rounded-lg shadow-sm', thumbsFeedbackContainer: thumbsFeedbackCssClasses.thumbsFeedbackContainer, thumbsUpIcon: thumbsFeedbackCssClasses.thumbsUpIcon, thumbsDownIcon: thumbsFeedbackCssClasses.thumbsDownIcon }; /** * Renders Direct Answers provided by the Search API. * * @public * * @param props - {@link DirectAnswerProps} * @returns A react element for DirectAnswer */ export function DirectAnswer({ customCssClasses, UnknownFieldTypeDisplay }: DirectAnswerProps): React.JSX.Element | null { const directAnswerResult = useSearchState(state => state.directAnswer.result); const isLoading = useSearchState(state => state.searchStatus.isLoading || false); const composedCssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses); const handleClickViewDetails = useCardAnalyticsCallback(directAnswerResult as DirectAnswerData, 'CTA_CLICK'); const handleClickFeedbackButton = useCardFeedbackCallback(directAnswerResult as DirectAnswerData); if (!directAnswerResult) { return null; } const cssClasses = getCssClassesForAnswerType(composedCssClasses, directAnswerResult.type); const containerCssClasses = twMerge( cssClasses.directAnswerContainer, isLoading && cssClasses.directAnswerLoading ); return (
{directAnswerResult.type === DirectAnswerType.FieldValue ? : }
); } function getCssClassesForAnswerType(cssClasses: DirectAnswerCssClasses, type: DirectAnswerType) { const isSnippet = type === DirectAnswerType.FeaturedSnippet; return { ...cssClasses, header: isSnippet ? cssClasses.answer : cssClasses.description, body: isSnippet ? cssClasses.description : cssClasses.answer }; }