import { type HTMLAttributes, type ReactElement, type Ref } from "react"; import type { SafeHtml } from "./safe-html.js"; export { EMPTY_HTML, sanitizedHtml, type SafeHtml } from "./safe-html.js"; /** The elements a rendered block is ever mounted into. A closed set — see the note below. */ export type SafeHtmlTag = "div" | "span" | "p" | "pre" | "code"; export type SafeHtmlViewProps = Omit, "dangerouslySetInnerHTML" | "children"> & { /** Escaped markup from an approved renderer. A plain `string` will not typecheck. */ html: SafeHtml; /** Element to mount into. Defaults to `div`. */ as?: SafeHtmlTag; ref?: Ref; }; /** * THE ONLY `dangerouslySetInnerHTML` in the product. Everything else renders through here. * * There is nothing clever in the body — the value is entirely in the two constraints around it: * * 1. `html` is `SafeHtml`, so a caller cannot reach this sink with an unescaped string. The * compiler enforces that, on every build, for every call site that exists or will exist. * 2. `safe-html-guard.test.ts` asserts that no OTHER file in the console, the admin, the agent * UIs or this package writes to `dangerouslySetInnerHTML` / `innerHTML` / `outerHTML` / * `insertAdjacentHTML`. Adding a tenth ad-hoc sink is a failing test, not a review miss. * * `as` is a closed union rather than `keyof JSX.IntrinsicElements` on purpose: the point of a * boundary is that you can enumerate what passes through it, and "any tag the caller names" puts * `