import { useFrontmatter } from "@rspress/core/runtime" import { SectionBand } from "./sections/SectionBand" import { FeatureGrid } from "./sections/FeatureGrid" import { Capabilities } from "./sections/Capabilities" import { Cases } from "./sections/Cases" import { CallToAction } from "./sections/CallToAction" import { hasContent, isHoisted, type Section } from "./sections/types" /** Type guard for a single entry of `frontmatter.sections`. */ function isSection(value: unknown): value is Section { if (typeof value !== "object" || value === null) return false const type = (value as { type?: unknown }).type return ( type === "advantages" || type === "contentGrid" || type === "capabilities" || type === "cases" || type === "cta" ) } function renderBody(section: Section) { switch (section.type) { case "advantages": case "contentGrid": return case "capabilities": return case "cases": return case "cta": return } } interface HomeSectionsProps { /** * Which bands this instance renders. Omit it to render all of them in * declaration order, which is what the home page wants — it has no article * for a band to sit on either side of. */ placement?: "top" | "bottom" } /** * Renders `frontmatter.sections` in declaration order. * * Attached to the `Layout` `afterFeatures` (home) and `afterDoc` (products, * services) slots, and to the `DocContent` override for hoisted bands. Returns * `null` for any page without a `sections` array, so it is inert on every doc * page that does not opt in — the legal pages included. */ export function HomeSections({ placement }: HomeSectionsProps = {}) { const { frontmatter } = useFrontmatter() const raw = frontmatter?.sections if (!Array.isArray(raw)) return null const sections = raw.filter(isSection) // The stripe alternates over the page's whole `sections` list rather than // over whatever this instance happens to render: hoisting a band must not // flip the background of every band below it. const visible = sections .map((section, index) => ({ section, index })) .filter(({ section }) => { if (placement === undefined) return true return placement === "top" ? isHoisted(section) : !isHoisted(section) }) if (visible.length === 0) return null return (
{visible.map(({ section, index }) => ( {renderBody(section)} ))}
) }