import React from 'react' import { DocViewer, type DocViewerProps } from './doc-viewer' import { MarkdownSkeleton, EmbedSkeleton } from './skeletons' import { PdfViewer } from '../embeds/pdf-viewer' import { GoogleSheetsViewer } from '../embeds/google-sheets-viewer' import { FigmaEmbed } from '../embeds/figma-embed' import { FileDownloadCard } from '../embeds/file-download-card' import type { DocContent, DocRenderHandlers, DocumentType, } from '../../types/doc-source' type DocRenderer = (content: DocContent, handlers: DocRenderHandlers) => React.ReactNode /** * Per-document-type renderer map. `markdown` is required (the lib does NOT * ship a default markdown renderer — embedders pick their own library + * sanitization to avoid an XSS surface in the lib). * * `pdf` / `google_sheet` / `figma` / `file` are optional — the lib provides * defaults from `components/embeds`. Override only when you want different * props than the default (e.g. a custom PDF toolbar, embedded credentials). */ export type DocumentTypeRenderers = { markdown: DocRenderer } & Partial< Record > export interface DocsHubPageProps extends Omit { /** Per-document-type renderer map. `markdown` is REQUIRED. */ documentTypeRenderers: DocumentTypeRenderers /** Renderer for unknown / future document types. Defaults to a lib-styled * "Unsupported document type" message. */ fallbackRenderer?: DocRenderer /** Loading skeleton picker. Defaults: `markdown` / `undefined` → * ``, everything else → ``. */ renderSkeleton?: (documentType: DocumentType | undefined) => React.ReactNode /** Defaults to `true` (the embeddable wrapper favors the chat-enabled * experience). Only mounts the in-source RAG search bar * (``) — does NOT require `ChatRuntimeContext`. */ showAIChat?: boolean } const DEFAULT_TITLE = 'Documents' const defaultFallbackRenderer: DocRenderer = () => (

Unsupported document type

) // When the DAL hasn't populated the URL field for a rich-content type, the // embed-viewer components render a broken iframe (empty src). Fall back to // the same lib-styled "Unsupported document type" panel the explicit // fallback uses — the surface is honest about the missing data instead of // pretending to load. `FileDownloadCard` handles its own missing-URL state // (hides the Download button), so it doesn't need this guard. const defaultPdfRenderer: DocRenderer = (content, handlers) => content.fileUrl ? ( ) : ( defaultFallbackRenderer(content, handlers) ) const defaultGoogleSheetRenderer: DocRenderer = (content, handlers) => content.externalUrl ? ( ) : ( defaultFallbackRenderer(content, handlers) ) const defaultFigmaRenderer: DocRenderer = (content, handlers) => content.externalUrl ? ( ) : ( defaultFallbackRenderer(content, handlers) ) const defaultFileRenderer: DocRenderer = (content) => ( ) const defaultRenderSkeleton = (documentType: DocumentType | undefined) => !documentType || documentType === 'markdown' ? ( ) : ( // Forward the documentType so the embed skeleton renders the right // shape (PDF=2 buttons, sheets/figma=1 button, file=centered card). ) /** * Embeddable docs-hub page. Bundles `` with safe defaults so the * minimum embed is a one-line mount (consumer only has to supply * `documentTypeRenderers.markdown`). * * Used by the hub at `/knowledge-base` and `/data-room`, and by third-party * React apps that embed the docs experience behind their own proxy. See * `docs/EMBEDDING_DOCS_HUB.md` for the embedder setup. * * SEO note: this component is `'use client'` (via the docs barrel) — server- * side SEO is the host's responsibility. The hub's `` is the * canonical implementation embedders can reference. */ export function DocsHubPage({ title = DEFAULT_TITLE, documentTypeRenderers, fallbackRenderer = defaultFallbackRenderer, renderSkeleton = defaultRenderSkeleton, showAIChat = true, className = 'min-h-screen', sidebarLabel = 'DOCUMENTATION', ...docViewerProps }: DocsHubPageProps) { const resolvedRenderers: DocumentTypeRenderers = { markdown: documentTypeRenderers.markdown, pdf: documentTypeRenderers.pdf ?? defaultPdfRenderer, google_sheet: documentTypeRenderers.google_sheet ?? defaultGoogleSheetRenderer, figma: documentTypeRenderers.figma ?? defaultFigmaRenderer, file: documentTypeRenderers.file ?? defaultFileRenderer, } const renderContent: DocViewerProps['renderContent'] = (content, handlers) => { const type = (content.documentType ?? 'markdown') as DocumentType const renderer = resolvedRenderers[type] ?? fallbackRenderer return renderer(content, handlers) } return ( ) }