@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
179 lines • 5.7 kB
text/typescript
import { type ElapsedTime, type Orama, type Result, type SearchParams } from '@orama/orama';
import type { Sitemap, SitemapPage, SitemapSection, SitemapPart, SitemapExport, SitemapSectionData } from "../createSitemap/types.mjs";
/**
* Base search result structure that can be extended by consumers
*/
export interface BaseSearchResult {
id?: string;
title?: string;
description?: string;
slug: string;
path: string;
sectionTitle: string;
prefix: string;
keywords?: string;
score?: number;
group?: string;
}
/**
* Page search result (top-level documentation page)
*/
export interface PageSearchResult extends BaseSearchResult {
type: 'page';
page?: string;
pageKeywords?: string;
types?: string;
sections?: string;
subsections?: string;
}
/**
* Part search result (component part with API documentation)
*/
export interface PartSearchResult extends BaseSearchResult {
type: 'part';
part: string;
export: string;
props?: string;
dataAttributes?: string;
cssVariables?: string;
}
/**
* Export search result (exported function/component with API documentation)
*/
export interface ExportSearchResult extends BaseSearchResult {
type: 'export';
export: string;
props?: string;
dataAttributes?: string;
cssVariables?: string;
}
/**
* Section search result (top-level heading within a page)
*/
export interface SectionSearchResult extends BaseSearchResult {
type: 'section';
section: string;
}
/**
* Subsection search result (nested heading within a page)
*/
export interface SubsectionSearchResult extends BaseSearchResult {
type: 'subsection';
subsection: string;
}
/**
* Union type of all common search result variants
*/
export type SearchResult = PageSearchResult | PartSearchResult | ExportSearchResult | SectionSearchResult | SubsectionSearchResult;
export type { SitemapPage, SitemapSection, SitemapPart, SitemapExport, SitemapSectionData, Sitemap };
export type SearchResults = {
group: string;
items: SearchResult[];
}[];
/**
* Options for configuring search behavior
*/
export interface UseSearchOptions {
/** Function that returns a promise resolving to sitemap data */
sitemap: () => Promise<{
sitemap?: Sitemap;
}>;
/** Maximum number of default results to show */
maxDefaultResults?: number;
/** Search tolerance for fuzzy matching */
tolerance?: number;
/** Maximum number of search results */
limit?: number;
/** Enable stemming and stopwords (uses English by default) */
enableStemming?: boolean;
/** Boost values for different result types and fields */
boost?: Partial<Record<string, number>>;
/** Include page categories in groups: "Overview Pages" vs "Pages" */
includeCategoryInGroup?: boolean;
/**
* When true, pages with `audience: 'private'` are included in the search index
* and default results. Use this for internal deployments where private pages
* should be discoverable.
*
* Typically driven by an environment variable:
* ```ts
* showPrivatePages: process.env.SHOW_PRIVATE_PAGES === 'true'
* ```
*
* @default false
*/
showPrivatePages?: boolean;
/**
* When true, excludes `sections` and `subsections` fields from page-type results.
* The individual section and subsection entries are still created.
* @default false
*/
excludeSections?: boolean;
/**
* Custom function to convert heading text to URL-friendly slugs.
* Use this to match your site's slug generation (e.g., rehype-slug).
* Only applied to section/subsection slugs from the sitemap.
*
* If not provided, the original slugs from the sitemap are used as-is.
*
* The second parameter `parentTitles` contains the original text of parent headings,
* useful for pages that concatenate parent context into child heading IDs
* (e.g., Releases pages: `v1.0.0-rc.0-autocomplete` where the version is prepended).
*
* @example
* ```ts
* // Simple generateSlug (ignores parent context)
* generateSlug: (text) => text.toLowerCase().replace(/[^a-z0-9]+/g, '-')
*
* // generateSlug with parent concatenation for subsections (e.g., Releases page)
* generateSlug: (text, parentTitles) => {
* const slug = stringToUrl(text);
* // If parent is a semver version, prepend it to match rehypeConcatHeadings
* if (parentTitles?.[0]?.match(/^v\d+\.\d+\.\d+/)) {
* return `${parentTitles[0]}-${slug}`;
* }
* return slug;
* }
* ```
*/
generateSlug?: (text: string, parentTitles?: string[]) => string;
/** Custom function to flatten sitemap pages into search results */
flattenPage?: (page: SitemapPage, sectionData: SitemapSectionData) => SearchResult[];
/** Custom function to format Orama search hits into typed results */
formatResult?: <TDocument = unknown>(hit: Result<TDocument>) => SearchResult;
}
export type SearchBy<T> = Pick<SearchParams<Orama<T>>, 'facets' | 'groupBy' | 'limit' | 'offset' | 'where'>;
/**
* Return value from useSearch hook
*/
export interface UseSearchResult<T> {
/**
* Current search results
*/
results: {
results: SearchResults;
count: number;
elapsed: ElapsedTime;
};
/**
* Whether the search index is ready
*/
isReady: boolean;
/**
* Function to update search value and get new results
*/
search: (value: string, by?: SearchBy<T>) => Promise<void>;
/**
* Default results shown when search is empty
*/
defaultResults: {
results: SearchResults;
count: number;
elapsed: ElapsedTime;
};
/**
* Build a URL from a search result
* Handles path normalization and hash fragments for different result types
*/
buildResultUrl: (result: SearchResult) => string;
}