import React, { useEffect, useRef } from 'react'; import styled from 'styled-components'; import type { JSX } from 'react'; import type { SearchItemData } from '@redocly/theme/core/types'; import { HttpTag } from '@redocly/theme/components/Tags/HttpTag'; import { Link } from '@redocly/theme/components/Link/Link'; import { Image } from '@redocly/theme/components/Image/Image'; import { searchHighlight } from '@redocly/theme/components/Search/SearchHighlight'; import { Badge } from '@redocly/theme/components/Badge/Badge'; import { trimText, getOperationColor } from '@redocly/theme/core/utils'; import { ReturnKeyIcon } from '@redocly/theme/icons/ReturnKeyIcon/ReturnKeyIcon'; import { useThemeHooks } from '@redocly/theme/core/hooks'; type ActiveItem = T & { active?: boolean }; export type SearchItemProps = { item: ActiveItem; onClick?: VoidFunction; product?: { name: string; icon?: string; }; className?: string; innerRef?: React.ForwardedRef; }; export function SearchItem({ onClick, item, className, product, innerRef, }: SearchItemProps): JSX.Element { const ref = useRef(null); const { useTranslate } = useThemeHooks(); const { translate } = useTranslate(); useEffect(() => { if (item.active) { ref.current?.focus(); } }, [item.active]); const { document, highlight } = item; const parameter = highlight.parameters && highlight.parameters.length ? highlight.parameters[0] : null; const shouldShowPath = document.path && document.path?.length > 1; const httpColor = getOperationColor({ isAdditionalOperation: document.isAdditionalOperation, httpVerb: document.httpMethod || '', }); return ( { ref.current = el; if (!innerRef) return; if (typeof innerRef === 'function') { innerRef(el); } else { innerRef.current = el; } }} data-component-name="Search/SearchItem" > {product && ( {product.name} )} {document.httpMethod ? ( {document.httpMethod.toUpperCase()} {highlight.httpPath ? searchHighlight(highlight.httpPath) : document.httpPath} ) : null} {highlight.title ? searchHighlight(highlight.title) : document.title} {document.deprecated ? ( {translate('search.searchItem.deprecated', 'Deprecated')} ) : null} {document.badges ? document.badges.map(({ name, color }) => ( {name} )) : null} {highlight.text ? searchHighlight(highlight.text) : trimText(document.text)} {parameter ? (
{searchHighlight(parameter.place)} {` → `} {parameter.path?.length ? searchHighlight(parameter.path?.join(' → ')) + ' → ' : ''} {searchHighlight(parameter.name)}
{searchHighlight(parameter.description)}
) : ( shouldShowPath && ( {highlight.path && highlight.path.length ? searchHighlight(highlight.path.join(' → ')) : document.path?.join(' → ')} ) )}
); } const SearchItemWrapper = styled(Link)` display: flex; padding: var(--search-item-padding); color: var(--search-item-text-color); background-color: var(--search-item-bg-color); transition: background-color 0.3s ease; text-decoration: none; white-space: normal; outline: none; border-top: 1px solid var(--search-item-border-color); border-bottom: 1px solid var(--search-item-border-color); ${ReturnKeyIcon} { align-self: center; opacity: 0; } &:hover, &:focus { color: var(--search-item-text-color-hover); background-color: var(--search-item-bg-color-hover); ${ReturnKeyIcon} { opacity: 1; } } &:focus { border-top: 1px solid var(--search-item-border-color-focused); border-bottom: 1px solid var(--search-item-border-color-focused); } `; const SearchItemContent = styled.section` flex: 1 1 auto; `; const SearchItemHeader = styled.div` position: relative; `; const SearchItemTitleWrapper = styled.div` display: flex; align-items: center; `; const SearchItemTitle = styled.div` overflow: hidden; text-overflow: ellipsis; color: var(--search-item-title-text-color); padding: var(--search-item-title-padding); font-size: var(--search-item-title-font-size); font-weight: var(--search-item-title-font-weight); line-height: var(--search-item-title-line-height); `; const SearchItemBadge = styled(Badge)` font-size: var(--font-size-sm); line-height: var(--line-height-sm); font-weight: var(--font-weight-regular); `; const SearchItemOperation = styled.div` display: inline-flex; align-items: baseline; overflow: hidden; text-overflow: ellipsis; font-size: var(--font-size-sm); line-height: var(--line-height-sm); font-weight: var(--font-weight-regular); color: var(--search-item-path-text-color); gap: var(--search-item-gap); `; const SearchItemDescription = styled.div` overflow: hidden; text-overflow: ellipsis; font-size: var(--font-size-base); line-height: var(--line-height-base); font-weight: var(--font-weight-regular); `; const SearchItemPath = styled.div` overflow: hidden; text-overflow: ellipsis; font-size: var(--font-size-sm); line-height: var(--line-height-sm); font-weight: var(--font-weight-regular); margin-top: var(--spacing-sm); `; const SearchItemPlace = styled.div` display: flex; flex-direction: column; overflow: hidden; text-overflow: ellipsis; font-size: var(--font-size-sm); line-height: var(--line-height-sm); font-weight: var(--font-weight-regular); margin-top: var(--spacing-sm); &:first-child { padding-top: 0; } `; const SearchItemProductTag = styled.div` position: absolute; display: flex; align-items: center; right: 0; font-size: var(--font-size-base); line-height: var(--line-height-base); font-weight: var(--font-weight-regular); padding: var(--search-item-title-padding); gap: var(--spacing-xs); img { width: var(--search-item-product-icon-size); height: var(--search-item-product-icon-size); } `; const SearchItemOperationTag = styled(HttpTag)` --http-tag-width: auto; --http-tag-font-weight: var(--font-weight-semibold); `;