/**
 * RelatedContentSection
 *
 * Renders content references grouped by type using the canonical card
 * components. MOVED from the hub (`components/shared/related-content-card.tsx`)
 * so any consuming app can embed it; the hub keeps a thin wrapper that
 * pre-binds its host-specific injections (nav hook, URL recomposition,
 * program configs, admin campaign card).
 *
 * THREE data modes (precedence top-down):
 *   1. CONTROLLED — `contentRefs` provided (even `[]`): render exactly those
 *      refs, no suggestion fetch (the original investor-update behavior).
 *   2. SUGGESTION — `entityType` + `entityId` provided: self-fetch
 *      `GET {apiBaseUrl}/api/related-content?entityType&entityId[&count][&excludeTypes]`
 *      (the generic 5-tier engine's second web service). `minResults` maps to
 *      `count`; absent → param not sent (server default applies). Each ref
 *      carries a `reason` (data-only — never rendered, matching the
 *      FaqSection/FaqWithReason precedent).
 *   3. SSR-HYDRATED suggestion — also pass `initialItems` (the server page
 *      called the engine directly); the first client fetch is skipped per the
 *      `useSelfFetch` initialData contract.
 *
 * Group layout (list vs grid) + card size (lg vs default) come from
 * `CONTENT_REF_GROUPS` in `../../utils/content-ref-groups` — single source of
 * truth, no per-type logic in this file. Skeletons come from
 * `renderSkeletonForType` so the placeholder height matches the loaded card
 * exactly (zero layout shift on resolve).
 *
 * One API call per content type via the shared list-URL builder
 * (`buildListUrl` — injectable; defaults to the lib's byte-parity-tested
 * builder prefixed with `apiBaseUrl`). Fetching uses `useSelfFetch` (plain
 * fetch, NO react-query) so third-party embedders need no QueryClientProvider;
 * cards are imported via DEEP module paths (not the chat barrel) so this
 * chunk never reaches `@tanstack/react-query`.
 *
 * LOCKSTEP NOTE: this file's per-type card/skeleton dispatch is the SIZED
 * sibling of the chat-side `CHAT_CARD_REGISTRY` (`../chat/entity-cards/
 * dispatch.tsx`), which renders compact `size='sm'` cards wired to the chat
 * runtime. Two dispatchers by design — when registering a new fetch-mode
 * content type, add it BOTH there and here (cards + skeleton + list URL).
 */
import React from 'react';
import type { ContentRef, ContentRefWithReason } from '../../types/content-ref';
import type { ChatCardDispatchExtras } from '../chat/entity-cards/dispatch';
/** Anchor prop bundle the per-card link surface receives — same shape the
 *  hub's `useNavLink` returns and the chat dispatcher's anchor builders
 *  produce. `null` = non-anchor mode (no URL). */
export interface CardLinkAnchorProps {
    href: string;
    target?: '_blank';
    rel?: 'noopener noreferrer';
    onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
}
/** Render-prop component injection for the navigation decision — keeps hook
 *  calls legal (hooks live INSIDE the injected component; `CardForType`
 *  itself calls zero hooks). The hub injects a `useNavLink`-backed provider;
 *  the default is hook-free (pure `decideNewTab`). MUST be defined at module
 *  scope by hosts — an inline arrow would remount every card each render. */
export interface CardLinkProviderProps {
    href: string | null;
    targetPlatform: string | null;
    children: (linkProps: CardLinkAnchorProps | null) => React.ReactElement | null;
}
export type CardLinkProvider = React.ComponentType<CardLinkProviderProps>;
/** Host-injected renderer pair for the admin-only `marketing_campaign` type.
 *  Absent (every non-hub embed) → the type renders nothing (its list URL
 *  hits `/api/admin`, unreachable outside the hub anyway). */
export interface AdminCampaignCardSlot {
    Card: React.ComponentType<{
        campaign: any;
    }>;
    Skeleton: React.ComponentType<{
        size?: 'default' | 'sm';
    }>;
}
/** Items per page within one type group. Groups larger than this paginate
 *  with the standard Pagination control (NO nested scrolling — a bounded
 *  scrollbox inside the page traps wheel events and hides the sections
 *  below it). MUST stay at or above the largest suggestion fill
 *  (RELATED_SAME_TYPE_COUNT in the hub's lib/constants/suggestions.ts) so
 *  current rails never paginate — only genuinely big groups (author pages)
 *  do. Exported through the subpath barrel for the hub's module-load
 *  assertion of that relation (entity-suggestion-sections.tsx). */
export declare const GROUP_PAGE_SIZE = 12;
export interface RelatedContentSectionProps {
    /** CONTROLLED mode (the original behavior). When defined — even `[]` — no
     *  suggestion fetch runs and exactly these refs render. */
    contentRefs?: ContentRef[];
    /** SUGGESTION mode (with `entityId`): self-fetch suggestions for this host
     *  entity from `{apiBaseUrl}/api/related-content`. Ignored when
     *  `contentRefs` is provided. */
    entityType?: string;
    entityId?: number | string;
    /** AUTHOR mode: self-fetch ALL published content authored by this profile
     *  from `{apiBaseUrl}/api/related-content?authorId=…` (grouped per type,
     *  endless within each group). Ignored when `contentRefs` is provided;
     *  takes precedence over the entityType/entityId suggestion scope.
     *  SSR-hydrate via `initialItems`, same as suggestion mode. */
    authorId?: string;
    /** Maps to the suggestion API's `count` param — the PER-TYPE fill target
     *  for every candidate type EXCEPT the host's own. Absent → param not sent
     *  (server default applies). */
    minResults?: number;
    /** Maps to the suggestion API's `sameTypeCount` param — the budget for the
     *  candidate type MATCHING the host's own `entityType` (same-type boost:
     *  a blog post's rail leads with more blog posts). Absent → param not
     *  sent (host's type uses the server's `count`). */
    sameTypeMinResults?: number;
    /** SSR hydrate for suggestion mode — the server page ran the engine and
     *  drills the refs here; the first client fetch is skipped (useSelfFetch
     *  initialData contract). */
    initialItems?: ContentRefWithReason[];
    /** Section title (default: "Related Content") */
    title?: string;
    /**
     * Grid columns at desktop. 2 = denser cards / wider summary (original
     * investor-update layout); 3 = more cards per row for dashboards.
     * Only consulted for grid-layout groups. Default: 2.
     */
    columns?: 2 | 3;
    /**
     * ContentRef.type values to exclude. Honored in ALL modes — controlled
     * mode post-filters (original behavior); suggestion mode ALSO forwards the
     * list verbatim as the API's `excludeTypes=` param so excluded types never
     * consume engine fill slots (`minResults` stays honored). The subtraction
     * happens SERVER-side — this component never mirrors the hub's candidate
     * list.
     */
    excludeTypes?: string[];
    /**
     * SUGGESTION-mode allow-list (rail vocabulary): which content types
     * participate in this rail. Sent verbatim as the API's `types=` param —
     * the SERVER intersects it with its own allowed candidate set, and
     * platform policy gates (e.g. internal-only types) ALWAYS win: the client
     * cannot request its way past them. Absent → all server-side candidates.
     */
    includeTypes?: string[];
    /** Fetch-URL prefix for third-party embeds / reverse proxies
     *  ('' = same-origin). Applied to BOTH the suggestion fetch and the
     *  default per-group list fetches. */
    apiBaseUrl?: string;
    /** Host injection bundle — REUSES the chat dispatcher's
     *  `ChatCardDispatchExtras` (programConfigs, buildOgPlaceholderUrl,
     *  buildProductReleaseCardProps override). Program groups render nothing
     *  when their config is absent. */
    extras?: ChatCardDispatchExtras;
    /** Hub injects its `buildContentURL` recomposition; default uses the
     *  ref's stored `url`/`targetPlatform` as the API composed them. */
    resolveHref?: (ref: ContentRef) => {
        href: string | null;
        targetPlatform: string | null;
    };
    /** Hub injects its registry-driven entity-list-api builder; default = the
     *  lib's `buildListUrl(type, ids, apiBaseUrl)`. */
    buildListUrl?: (type: string, ids: string[]) => string | null;
    /** Hub injects a `useNavLink`-backed render-prop provider; default = pure
     *  anchor via `decideNewTab`. MUST be a module-scope component. */
    LinkProvider?: CardLinkProvider;
    /** Renderer pair for the admin-only `marketing_campaign` type. Absent →
     *  the type renders nothing. */
    adminCampaignCard?: AdminCampaignCardSlot;
}
export declare function RelatedContentSection({ contentRefs, entityType, entityId, authorId, minResults, sameTypeMinResults, includeTypes, initialItems, title, columns, excludeTypes, apiBaseUrl, extras, resolveHref, buildListUrl, LinkProvider, adminCampaignCard, }: RelatedContentSectionProps): React.JSX.Element | null;
//# sourceMappingURL=related-content-section.d.ts.map