import { type ElementType, type ReactElement, type ReactNode } from "react"; /** * One page listed inside a {@link DocsTopic}. */ export interface DocsTopicPage { /** The link text. */ title: string; /** Where it goes. */ href: string; /** One-sentence summary. Shown in filter results, and searched by the filter. */ description?: string | undefined; } /** * One topic card: a heading, a blurb, an icon, and the pages filed under it. */ export interface DocsTopic { /** Stable key, and the value the grid dedupes on. */ id: string; /** The card heading. */ title: string; /** Where the heading and the footer count link go. */ href: string; /** One line on what this topic covers. Omitted when unset. */ description?: string | undefined; /** The card's glyph, already rendered. A node rather than a name, so the grid needs no icon map. */ icon?: ReactNode; /** * Any CSS colour. Drives the icon tile, the corner wash, the bullets and the footer link via * the `--scribekit-topic-accent` custom property; the softer fills are derived from it with * `color-mix`, so ONE value themes the whole card. Defaults to this topic's entry in `accents`. */ accent?: string | undefined; /** * Every page in the topic - not just the visible ones. The card shows the first * `pagesPerTopic`, but the filter searches all of them, so a page hidden by the cap is still * findable. */ pages: DocsTopicPage[]; /** * The footer link's text, e.g. `"6 pages"`. Already localized and already pluralized - the * count is known before render, so it is resolved by the caller (who has the language and the * plural rules) rather than templated here. Defaults to `" pages"`. */ countLabel?: string | undefined; } /** * Copy overrides for {@link DocsTopicGrid}. Every entry is optional; anything omitted falls back to * the packaged English default (or, via {@link DocsIndex}, to the packaged translation). * * EVERY ENTRY IS A PLAIN STRING, and that is a hard constraint rather than a style choice: this is * a client component, so a label built as a `(count) => string` callback cannot reach it from a * server page at all - React refuses to serialize a function across the boundary and the render * throws. The two labels that need runtime values therefore use `{count}` / `{query}` placeholders, * substituted here. */ export interface DocsTopicGridLabels { /** The section heading. */ heading?: string | undefined; /** Placeholder and accessible name for the filter input. */ filterPlaceholder?: string | undefined; /** Label for the button that empties the filter. */ clearFilter?: string | undefined; /** Results heading; `{count}` and `{query}` are substituted. Used when the count is not 1. */ resultCount?: string | undefined; /** Results heading for exactly one match. Falls back to {@link DocsTopicGridLabels.resultCount}. */ resultCountOne?: string | undefined; /** Empty-results heading; `{query}` is substituted. */ noMatches?: string | undefined; /** * A line under the empty-results heading suggesting what to try instead. Deliberately has NO * packaged default: a useful hint names terms from YOUR corpus, and a generic one is noise. */ noMatchesHint?: string | undefined; } /** * Props for {@link DocsTopicGrid}. */ export interface DocsTopicGridProps { /** The topics to render, in display order. */ topics: DocsTopic[]; /** Copy overrides. Anything unset uses the packaged translation. */ labels?: DocsTopicGridLabels | undefined; /** How many pages each card lists before its footer count. Defaults to `3`. */ pagesPerTopic?: number | undefined; /** Set `false` to drop the filter box, leaving a plain grid. Defaults to `true`. */ filter?: boolean | undefined; /** Accent cycle for topics that declare no `accent` of their own. */ accents?: string[] | undefined; /** Element used for the links. Defaults to `"a"`; pass `next/link` for client-side nav. */ linkComponent?: ElementType; /** Id put on the heading and pointed at by the section's `aria-labelledby`. */ headingId?: string | undefined; /** Appended to the section's class list. */ className?: string | undefined; } /** * "Browse by topic": a grid of topic cards, each listing the first few pages filed under it, with * an optional filter box that replaces the grid with a flat, ranked result list while a query is * typed. * * A CLIENT component, because the filter is local state - which is also why every prop is plain * data and icons arrive as already-rendered nodes rather than a `renderIcon` callback: a function * cannot cross the server/client boundary, an element can. Pass `linkComponent` only from a client * module (re-export `next/link` behind `"use client"`); handing a server component's own function * across the boundary throws. * * The filter searches each page's title and description plus its topic's title, so "billing" finds * a page whose own words never say it. It searches EVERY page, including ones the `pagesPerTopic` * cap hides from the card - a page you cannot see is exactly the one you need the filter for. * * @param props - see {@link DocsTopicGridProps}. * @returns the topic section. */ export declare function DocsTopicGrid({ topics, labels, pagesPerTopic, filter, accents, linkComponent: Link, headingId, className, }: DocsTopicGridProps): ReactElement;