@ai-matrx/media 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/files/engine/cache/register-service-worker.js +1 -1
- package/dist/files/engine/cache/register-service-worker.js.map +1 -1
- package/dist/files/engine/redux/thunks.js +1 -1
- package/dist/files/engine/redux/thunks.js.map +1 -1
- package/dist/files/engine/support/logger.js +1 -1
- package/dist/files/engine/support/logger.js.map +1 -1
- package/dist/files/engine/upload/tusUpload.js +1 -1
- package/dist/files/engine/upload/tusUpload.js.map +1 -1
- package/dist/files/engine/upload/uploadGuardOpeners.js +1 -1
- package/dist/files/engine/upload/uploadGuardOpeners.js.map +1 -1
- package/dist/react.cjs +3 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +3 -2
- package/dist/react.js.map +1 -1
- package/dist/share.cjs +3 -8
- package/dist/share.cjs.map +1 -1
- package/dist/share.js +3 -8
- package/dist/share.js.map +1 -1
- package/dist/viewers.cjs +3 -2
- package/dist/viewers.cjs.map +1 -1
- package/dist/viewers.js +3 -2
- package/dist/viewers.js.map +1 -1
- package/package.json +4 -4
package/dist/viewers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/viewers/media-file-viewer.tsx","../src/viewers/registry.ts","../src/viewers/code-viewer.tsx","../src/react/cn.ts","../src/viewers/chrome.tsx","../src/react/icons.tsx","../src/viewers/use-viewer-bytes.ts","../src/core/use-media-blob.ts","../src/core/context.ts","../src/core/diagnostics.ts","../src/core/ref-key.ts","../src/core/use-media-resolution.ts","../src/core/file-kind.ts","../src/react/file-icon.tsx","../src/viewers/generic-viewer.tsx","../src/viewers/html-viewer.tsx","../src/viewers/markup-chrome.tsx","../src/viewers/svg-viewer.tsx","../src/viewers/transparency-grid.ts","../src/viewers/text-viewer.tsx","../src/viewers/unavailable-viewer.tsx","../src/viewers/preview-kind.ts"],"sourcesContent":["/**\n * src/viewers/media-file-viewer.tsx — THE dispatcher.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/PreviewerSwitch.tsx`, which was\n * already the app's single kind→viewer switch across three surfaces (the\n * preview pane, the inline markdown file block, and the code editor's\n * binary-file fallback). The dispatch table, the kind vocabulary and the\n * degradation arms now belong to the package; the app keeps only the\n * registration of its own heavy engines.\n *\n * RESOLUTION ORDER (deliberate):\n * 1. a host registration for the kind — a real engine, or a feature's own\n * domain viewer overriding a built-in;\n * 2. the package's built-in body — text / code / svg / html / generic;\n * 3. the ANNOUNCING default — never a dead pane.\n *\n * FRAGMENTATION LAW: this module contains ZERO dynamic imports. Every body it\n * can render is statically part of the `./viewers` graph, which is already\n * behind whatever edge the consuming surface sits on. Heavy engines are lazy\n * on the HOST side of the registry seam — one boundary, at the edge, owned by\n * the app that knows its own chunking.\n */\n\n\"use client\";\n\nimport { createElement, type ComponentType } from \"react\";\nimport { getMediaViewer } from \"./registry\";\nimport { CodeViewer } from \"./code-viewer\";\nimport { GenericViewer } from \"./generic-viewer\";\nimport { HtmlViewer } from \"./html-viewer\";\nimport { SvgViewer } from \"./svg-viewer\";\nimport { TextViewer } from \"./text-viewer\";\nimport { MediaViewerUnavailable } from \"./unavailable-viewer\";\nimport { getPreviewKind } from \"./preview-kind\";\nimport type {\n MediaViewerComponent,\n MediaViewerKind,\n MediaViewerProps,\n} from \"./types\";\n\n/** The kinds the package renders itself, with no host registration. */\nconst BUILT_IN: Partial<Record<MediaViewerKind, MediaViewerComponent>> = {\n text: TextViewer as MediaViewerComponent,\n code: CodeViewer as MediaViewerComponent,\n svg: SvgViewer as MediaViewerComponent,\n html: HtmlViewer as MediaViewerComponent,\n generic: GenericViewer as MediaViewerComponent,\n};\n\nexport interface MediaFileViewerProps extends MediaViewerProps {\n /**\n * The kind to render. Omit to let the package derive it from the file name\n * and MIME type (`getPreviewKind`).\n */\n previewKind?: MediaViewerKind | undefined;\n}\n\nexport function MediaFileViewer({\n previewKind,\n ...props\n}: MediaFileViewerProps) {\n const kind =\n previewKind ?? getPreviewKind(props.fileName, props.mimeType ?? null);\n\n // MOUNTED AS AN ELEMENT, NEVER CALLED AS A FUNCTION. `viewer(props)` would\n // run the viewer's hooks inside THIS component's hook list, so a registered\n // viewer that uses hooks (every real engine adapter does — it resolves a\n // URL, reads a theme, joins a playback session) would blow up the moment\n // the kind changed between renders. `createElement` gives each body its own\n // component instance and its own hook list.\n const viewer = (getMediaViewer(kind) ?? BUILT_IN[kind]) as\n | ComponentType<MediaViewerProps>\n | undefined;\n if (viewer) return createElement(viewer, props);\n\n return <MediaViewerUnavailable {...props} kind={kind} />;\n}\n","/**\n * src/viewers/registry.ts — the heavy-engine seam.\n *\n * The package ships working bodies for every viewer kind it can render with\n * DOM primitives alone (text, code chrome, svg, html, generic). The kinds\n * whose rendering IS a multi-megabyte browser-only engine — PDF.js, a\n * Markdown/KaTeX stack, SheetJS, a server-side Office extractor — ride this\n * seam instead (C8 + the diff-package Monaco precedent): a host registers the\n * engine once, and until it does, the dispatcher renders an ANNOUNCING\n * default that names the missing engine and still offers download/open. A\n * dead pane is never an outcome.\n *\n * MODULE-LEVEL MUTABLE STATE IS BANNED (the dual ESM/CJS bundle rule): with\n * `splitting: false` and two formats, each loader graph instantiates its own\n * copy of this module, so a plain module-scope Map would silently split the\n * registry — a host registering through the CJS graph would be invisible to a\n * component rendered from the ESM graph. The maps therefore live on\n * `globalThis` under `Symbol.for` slots, and the tarball canary proves a\n * registration made in one graph is visible from the other.\n */\n\nimport type {\n MediaCodeHighlighter,\n MediaViewerComponent,\n MediaViewerKind,\n} from \"./types\";\n\nconst VIEWER_SLOT = Symbol.for(\"ai-matrx.media.viewer-registry\");\nconst HIGHLIGHTER_SLOT = Symbol.for(\"ai-matrx.media.code-highlighter\");\n\ninterface RegistrySlots {\n [VIEWER_SLOT]?: Map<MediaViewerKind, MediaViewerComponent>;\n [HIGHLIGHTER_SLOT]?: MediaCodeHighlighter | null;\n}\n\nfunction slots(): RegistrySlots {\n return globalThis as unknown as RegistrySlots;\n}\n\nfunction viewerMap(): Map<MediaViewerKind, MediaViewerComponent> {\n const host = slots();\n const existing = host[VIEWER_SLOT];\n if (existing) return existing;\n const created = new Map<MediaViewerKind, MediaViewerComponent>();\n host[VIEWER_SLOT] = created;\n return created;\n}\n\n/**\n * Register the viewer body for a kind. Registering a kind the package already\n * renders REPLACES the built-in — that is the sanctioned host override (a\n * feature-specific domain viewer implementing the same contract).\n *\n * Returns an unregister function so a test or a hot-reloading host can undo it.\n */\nexport function registerMediaViewer(\n kind: MediaViewerKind,\n viewer: MediaViewerComponent,\n): () => void {\n const map = viewerMap();\n const previous = map.get(kind);\n map.set(kind, viewer);\n return () => {\n if (previous) map.set(kind, previous);\n else map.delete(kind);\n };\n}\n\n/** The registered viewer for a kind, or `null` when nothing is registered. */\nexport function getMediaViewer(\n kind: MediaViewerKind,\n): MediaViewerComponent | null {\n return viewerMap().get(kind) ?? null;\n}\n\n/** Every kind a host has registered — for diagnostics and tests. */\nexport function registeredMediaViewerKinds(): MediaViewerKind[] {\n return [...viewerMap().keys()];\n}\n\n/**\n * Register the syntax-highlighting engine for the built-in code viewer.\n * Without one the code viewer still renders — monospace, line-numbered,\n * copyable, truncation-honest — it simply is not colored.\n */\nexport function registerMediaCodeHighlighter(\n highlighter: MediaCodeHighlighter,\n): () => void {\n const host = slots();\n const previous = host[HIGHLIGHTER_SLOT] ?? null;\n host[HIGHLIGHTER_SLOT] = highlighter;\n return () => {\n host[HIGHLIGHTER_SLOT] = previous;\n };\n}\n\nexport function getMediaCodeHighlighter(): MediaCodeHighlighter | null {\n return slots()[HIGHLIGHTER_SLOT] ?? null;\n}\n","/**\n * src/viewers/code-viewer.tsx — source-code viewer.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/CodePreview.tsx`.\n *\n * THE ONE DELIBERATE DIVERGENCE (C8 + the diff-package Monaco precedent):\n * the original imported `react-syntax-highlighter` (Prism, ~150KB min) at the\n * top of the module. A syntax highlighter is a browser-only engine that a\n * headless consumer of this package must never be forced to carry, so the\n * ENGINE rides `registerMediaCodeHighlighter` and the package ships the\n * chrome plus a capable default: monospace, line-numbered, wrap-toggling,\n * copyable, truncation-honest — everything except color. The default is not\n * a stub and never announces a failure, because nothing failed; a host that\n * wants color registers an engine in one line.\n */\n\n\"use client\";\n\nimport { createElement, useMemo, useState, type ComponentType } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { ViewerCopyButton, ViewerError, ViewerSkeleton, truncationNote } from \"./chrome\";\nimport { getMediaCodeHighlighter } from \"./registry\";\nimport type { MediaCodeHighlighterProps, MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\n/**\n * Extension → Prism-style language id. Ported verbatim from the original;\n * unknown ids are handed through unchanged (every engine we target degrades\n * to no-highlight rather than throwing).\n */\nconst EXT_TO_LANGUAGE: Record<string, string> = {\n js: \"javascript\",\n jsx: \"jsx\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n ts: \"typescript\",\n tsx: \"tsx\",\n py: \"python\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n java: \"java\",\n kt: \"kotlin\",\n swift: \"swift\",\n c: \"c\",\n h: \"c\",\n cpp: \"cpp\",\n cc: \"cpp\",\n cxx: \"cpp\",\n hpp: \"cpp\",\n cs: \"csharp\",\n php: \"php\",\n scala: \"scala\",\n html: \"markup\",\n htm: \"markup\",\n xml: \"markup\",\n svg: \"markup\",\n css: \"css\",\n scss: \"scss\",\n less: \"less\",\n json: \"json\",\n yaml: \"yaml\",\n yml: \"yaml\",\n toml: \"toml\",\n ini: \"ini\",\n sh: \"bash\",\n bash: \"bash\",\n zsh: \"bash\",\n fish: \"bash\",\n ps1: \"powershell\",\n sql: \"sql\",\n graphql: \"graphql\",\n gql: \"graphql\",\n proto: \"protobuf\",\n dockerfile: \"docker\",\n makefile: \"makefile\",\n lua: \"lua\",\n r: \"r\",\n};\n\nfunction extensionOf(fileName: string): string {\n const base = fileName.split(/[\\\\/]/).pop() ?? fileName;\n const dot = base.lastIndexOf(\".\");\n if (dot <= 0) return \"\";\n return base.slice(dot + 1).toLowerCase();\n}\n\n/** Filename → language id. Exported: hosts registering an engine reuse it. */\nexport function detectCodeLanguage(fileName: string): string {\n const ext = extensionOf(fileName);\n if (ext) return EXT_TO_LANGUAGE[ext] ?? \"text\";\n const lower = fileName.toLowerCase();\n if (lower === \"dockerfile\") return \"docker\";\n if (lower === \"makefile\") return \"makefile\";\n return \"text\";\n}\n\nexport function CodeViewer({\n source,\n fileName,\n className,\n maxBytes = 1024 * 1024,\n}: MediaViewerProps) {\n const { text, error, loading, truncated } = useViewerText(source, maxBytes);\n const [wrap, setWrap] = useState(false);\n const language = useMemo(() => detectCodeLanguage(fileName), [fileName]);\n const highlighter = getMediaCodeHighlighter();\n\n if (error) return <ViewerError message={error} className={className} />;\n if (loading || text === null) return <ViewerSkeleton className={className} />;\n\n const lines = text.split(\"\\n\");\n\n return (\n <div\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden bg-card\",\n className,\n )}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-border bg-muted/30 px-3 py-1.5\">\n <div className=\"flex min-w-0 items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-mono tracking-wide uppercase\">{language}</span>\n {truncated ? (\n <span className=\"text-warning\">· {truncationNote(maxBytes)}</span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n {highlighter ? null : (\n <button\n type=\"button\"\n onClick={() => setWrap((value) => !value)}\n aria-pressed={wrap}\n className={cn(\n \"rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground\",\n wrap && \"bg-accent text-accent-foreground\",\n )}\n >\n Wrap\n </button>\n )}\n <ViewerCopyButton text={text} />\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {highlighter ? (\n // Mounted as an element, never called — a real highlighter reads the\n // host's theme with a hook, and calling it would put that hook in\n // THIS component's list (see the note in media-file-viewer.tsx).\n createElement(\n highlighter as ComponentType<MediaCodeHighlighterProps>,\n { code: text, language },\n )\n ) : (\n <pre className=\"m-0 flex p-3 font-mono text-xs leading-5\">\n <code\n aria-hidden\n className=\"mr-3 shrink-0 border-r border-border/60 pr-3 text-right text-muted-foreground/60 select-none\"\n >\n {lines.map((_, index) => `${index + 1}\\n`).join(\"\")}\n </code>\n <code\n className={cn(\n \"min-w-0 flex-1 text-foreground\",\n wrap ? \"break-words whitespace-pre-wrap\" : \"whitespace-pre\",\n )}\n >\n {text}\n </code>\n </pre>\n )}\n </div>\n </div>\n );\n}\n","/**\n * src/react/cn.ts — conditional class join with last-wins Tailwind conflict\n * merging. The originals used the app's `cn` (clsx + tailwind-merge); public\n * `className` overrides depend on last-wins class-conflict merging, so a\n * naive join would be a behavior divergence (the kit `./confirm` precedent —\n * this is why `tailwind-merge` is a sanctioned runtime dep of `/react`).\n */\n\nimport { twMerge } from \"tailwind-merge\";\n\nexport type ClassValue = string | false | null | undefined | 0;\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(inputs.filter(Boolean).join(\" \"));\n}\n","/**\n * src/viewers/chrome.tsx — the shared viewer chrome.\n *\n * The five absorbed matrx-frontend previewers each hand-rolled the same\n * error card, the same skeleton, and the same copy button. One copy here;\n * one place to make them good.\n */\n\n\"use client\";\n\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport { useCallback, useState } from \"react\";\nimport { ErrorBox } from \"@ai-matrx/design-system\";\nimport { cn } from \"../react/cn\";\nimport { AlertCircleIcon, CheckIcon, CopyIcon } from \"../react/icons\";\n\n/** The uniform loading bar every viewer shows while bytes are in flight. */\nexport function ViewerSkeleton({\n className,\n tone = \"muted\",\n}: {\n className?: string | undefined;\n tone?: \"muted\" | \"plain\" | undefined;\n}) {\n return (\n <div\n className={cn(\n \"flex h-full w-full items-center justify-center\",\n tone === \"muted\" && \"bg-muted/20\",\n className,\n )}\n >\n <div className=\"h-6 w-40 animate-pulse rounded bg-muted\" />\n </div>\n );\n}\n\n/**\n * The honest failure card. It shows the REAL underlying message (HTTP\n * 401/403/404/network) rather than a generic \"Preview failed\" — the original\n * previewers' deliberate choice, kept: a user who can see the status can act\n * on it, and a support thread starts with a fact instead of a shrug.\n */\nexport function ViewerError({\n title = \"Couldn't load this file\",\n message,\n hint,\n className,\n}: {\n title?: string | undefined;\n message?: string | null | undefined;\n hint?: string | undefined;\n className?: string | undefined;\n}) {\n return (\n <ErrorBox\n as=\"div\"\n className={cn(\n \"flex h-full w-full flex-col items-center justify-center gap-3 p-6 text-center\",\n className,\n )}\n title={title}\n message={message ?? title}\n operation=\"Show this file\"\n origin=\"media/ViewerError\"\n >\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10\">\n <AlertCircleIcon className=\"h-6 w-6 text-destructive\" />\n </div>\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold\">{title}</h3>\n {message ? (\n <p className=\"max-w-md text-xs break-words text-muted-foreground\">\n {message}\n </p>\n ) : null}\n {hint ? (\n <p className=\"max-w-md text-[11px] text-muted-foreground/80\">{hint}</p>\n ) : null}\n </div>\n </ErrorBox>\n );\n}\n\n/**\n * Copy-to-clipboard button with the settled-state flip. Swallows the\n * clipboard rejection that non-secure contexts always throw — a failed copy\n * is not an error worth a card, and the un-flipped button IS the signal.\n */\nexport function ViewerCopyButton({\n text,\n className,\n}: {\n text: string | null;\n className?: string | undefined;\n}) {\n const [copied, setCopied] = useState(false);\n const onCopy = useCallback(() => {\n if (text == null) return;\n void navigator.clipboard\n .writeText(text)\n .then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1600);\n })\n .catch(() => {\n /* non-secure context — the un-flipped button is the honest signal */\n });\n }, [text]);\n\n return (\n <button\n type=\"button\"\n onClick={onCopy}\n aria-label=\"Copy text to clipboard\"\n title=\"Copy text to clipboard\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground\",\n copied && \"text-emerald-600 dark:text-emerald-400\",\n className,\n )}\n >\n {copied ? (\n <CheckIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <CopyIcon className=\"h-3.5 w-3.5\" />\n )}\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n );\n}\n\n/** The strip above a text-shaped viewer: status on the left, copy on the right. */\nexport function ViewerToolbar({\n children,\n className,\n}: {\n children?: React.ReactNode;\n className?: string | undefined;\n}) {\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center justify-between gap-2 border-b border-border/60 bg-muted/20 px-3 py-1 text-xs\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\n/**\n * \"truncated to the first 1.0 MB\" — one phrasing across every text-shaped\n * viewer.\n *\n * THE SIZE IS `formatFileSize`'s, NOT OURS (2026-09-12). This body used to do\n * its own `maxBytes / 1024 / 1024` and print `${mb.toFixed(0)}MB` above a\n * megabyte and `${(maxBytes / 1024).toFixed(0)}KB` below it — a byte-size\n * formatter living in a PACKAGE, which is the worst place for one: every\n * consumer of `@ai-matrx/media` inherited its rounding. And it rounded badly in\n * both directions. A 1.5 MiB ceiling printed \"2MB\" (`toFixed(0)` rounds half\n * up, so the note over-stated the limit by half a megabyte), and anything under\n * ~512 bytes printed \"0KB\" — the confident zero `formatFileSize` exists to\n * refuse. `@ai-matrx/media` already depends on `@ai-matrx/kit` and already\n * imports this exact function two files away in `generic-viewer.tsx`.\n */\nexport function truncationNote(maxBytes: number): string {\n return `truncated to the first ${formatFileSize(maxBytes)}`;\n}\n","/**\n * src/react/icons.tsx — the package's OWN inlined SVG icons.\n *\n * Per campaign ruling C19 (2026-08-29): no icon-library dependency, ever.\n * Every glyph below is copied from lucide-react v1.22.0 (ISC license) exactly,\n * following the @ai-matrx/tap-target precedent. Add a new icon by copying the\n * lucide __iconNode data — never by adding a lucide peer.\n *\n * Internal module: icons are exported for the package's own components and for\n * hosts that want visual parity in slots, but they are not the product.\n */\n\nimport type { SVGProps } from \"react\";\n\nexport type MediaIconProps = SVGProps<SVGSVGElement>;\n\nfunction svgProps(props: MediaIconProps): MediaIconProps {\n return {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n width: 24,\n height: 24,\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n// lucide: archive\nexport function ArchiveIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\" />\n <path d=\"M10 12h4\" />\n </svg>\n );\n}\n\n// lucide: braces\nexport function BracesIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n// lucide: check\nexport function CheckIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n// lucide: code\nexport function CodeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m16 18 6-6-6-6\" />\n <path d=\"m8 6-6 6 6 6\" />\n </svg>\n );\n}\n\n// lucide: copy\nexport function CopyIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n// lucide: database\nexport function DatabaseIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n );\n}\n\n// lucide: download\nexport function DownloadIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </svg>\n );\n}\n\n// lucide: externalLink\nexport function ExternalLinkIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n );\n}\n\n// lucide: file\nexport function FileIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n </svg>\n );\n}\n\n// lucide: fileAudio\nexport function FileAudioIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M4 6.835V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-.343\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M2 19a2 2 0 0 1 4 0v1a2 2 0 0 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 4 0\" />\n </svg>\n );\n}\n\n// lucide: fileCode\nexport function FileCodeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12.5 8 15l2 2.5\" />\n <path d=\"m14 12.5 2 2.5-2 2.5\" />\n </svg>\n );\n}\n\n// lucide: fileJson\nexport function FileJsonIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1\" />\n <path d=\"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\" />\n </svg>\n );\n}\n\n// lucide: fileSpreadsheet\nexport function FileSpreadsheetIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M8 13h2\" />\n <path d=\"M14 13h2\" />\n <path d=\"M8 17h2\" />\n <path d=\"M14 17h2\" />\n </svg>\n );\n}\n\n// lucide: fileText\nexport function FileTextIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n}\n\n// lucide: fileType\nexport function FileTypeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M11 18h2\" />\n <path d=\"M12 12v6\" />\n <path d=\"M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5\" />\n </svg>\n );\n}\n\n// lucide: fileVideo\nexport function FileVideoIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z\" />\n </svg>\n );\n}\n\n// lucide: folder\nexport function FolderIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n}\n\n// lucide: folderOpen\nexport function FolderOpenIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n// lucide: image\nexport function ImageIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </svg>\n );\n}\n\n// lucide: imageOff\nexport function ImageOffIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M10.41 10.41a2 2 0 1 1-2.83-2.83\" />\n <line x1=\"13.5\" x2=\"6\" y1=\"13.5\" y2=\"21\" />\n <line x1=\"18\" x2=\"21\" y1=\"12\" y2=\"15\" />\n <path d=\"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59\" />\n <path d=\"M21 15V5a2 2 0 0 0-2-2H9\" />\n </svg>\n );\n}\n\n// lucide: music\nexport function MusicIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M9 18V5l12-2v13\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\n </svg>\n );\n}\n\n// lucide: packageBox\nexport function PackageBoxIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\" />\n <path d=\"M12 22V12\" />\n <polyline points=\"3.29 7 12 12 20.71 7\" />\n <path d=\"m7.5 4.27 9 5.15\" />\n </svg>\n );\n}\n\n// lucide: penTool\nexport function PenToolIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\" />\n <path d=\"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\" />\n <path d=\"m2.3 2.3 7.286 7.286\" />\n <circle cx=\"11\" cy=\"11\" r=\"2\" />\n </svg>\n );\n}\n\n// lucide: share2\nexport function Share2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </svg>\n );\n}\n\n// lucide: subtitles\nexport function SubtitlesIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 15h4M15 15h2M7 11h2M13 11h4\" />\n </svg>\n );\n}\n\n// lucide: upload\nexport function UploadIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </svg>\n );\n}\n\n// lucide: video\nexport function VideoIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\n// lucide: videoOff\nexport function VideoOffIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n// lucide: volumeX\nexport function VolumeXIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <line x1=\"22\" x2=\"16\" y1=\"9\" y2=\"15\" />\n <line x1=\"16\" x2=\"22\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n// lucide: x\nexport function XIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n// lucide: alertCircle\nexport function AlertCircleIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n// lucide: checkCircle2\nexport function CheckCircle2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M21.801 10A10 10 0 1 1 17 3.335\" />\n <path d=\"m9 11 3 3L22 4\" />\n </svg>\n );\n}\n\n// lucide: globe\nexport function GlobeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n// lucide: link-2\nexport function Link2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n// lucide: settings-2\nexport function Settings2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 7h-9\" />\n <path d=\"M14 17H5\" />\n <circle cx=\"17\" cy=\"17\" r=\"3\" />\n <circle cx=\"7\" cy=\"7\" r=\"3\" />\n </svg>\n );\n}\n\n// lucide: loader-circle (a.k.a. Loader2)\nexport function SpinnerIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// lucide: plus\nexport function PlusIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n );\n}\n\n// lucide: search\nexport function SearchIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n );\n}\n\n// lucide: pause (lucide-react v1.48.0)\nexport function PauseIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </svg>\n );\n}\n\n// lucide: play (lucide-react v1.48.0)\nexport function PlayIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </svg>\n );\n}\n","/**\n * src/viewers/use-viewer-bytes.ts — the ONE byte/text/URL machinery every\n * viewer body shares.\n *\n * Four separate matrx-frontend previewers (Text, Code, the SVG source view,\n * the HTML source view) each carried their own copy of \"read the blob, cap it\n * at N bytes, mark it truncated, surface the REAL backend error verbatim,\n * cancel on unmount\". Four copies is four places to drift; C22 says that\n * machinery lives in the package exactly once.\n */\n\nimport { useEffect, useState } from \"react\";\nimport { useMediaBlob } from \"../core/use-media-blob\";\nimport { useMediaResolution } from \"../core/use-media-resolution\";\nimport type { MediaViewerSource } from \"./types\";\n\nexport interface ViewerBytesState {\n blob: Blob | null;\n loading: boolean;\n /** The real underlying message (HTTP 401/403/404/network) — never generic. */\n error: string | null;\n}\n\n/**\n * Bytes for a viewer source. A `blob` source is already resolved; a `ref`\n * source goes through `MediaClient.getBlob` (which is also what emits the\n * terminal-failure diagnostics — see `useMediaBlob`).\n *\n * `useMediaBlob` is called UNCONDITIONALLY (with `null` for blob sources) so\n * the hook order never changes with the source shape.\n */\nexport function useViewerBytes(source: MediaViewerSource): ViewerBytesState {\n const fromClient = useMediaBlob(source.kind === \"ref\" ? source.ref : null);\n if (source.kind === \"blob\") {\n return { blob: source.blob, loading: false, error: null };\n }\n return {\n blob: fromClient.blob,\n loading: fromClient.loading,\n error: fromClient.error,\n };\n}\n\n/**\n * Blob → string, across every runtime we ship into.\n *\n * `Blob.prototype.text()` is the modern one-liner and is what the\n * matrx-frontend originals used — but it does not exist in Safari < 14, in\n * older WebViews (the Tauri shell's floor), or in jsdom, and the failure mode\n * is a raw \"blob.text is not a function\" TypeError rendered to the user as if\n * the FILE were broken. Per C22 this quirk branch belongs in the package, once.\n */\nasync function readBlobText(blob: Blob): Promise<string> {\n const maybeText = (blob as { text?: () => Promise<string> }).text;\n if (typeof maybeText === \"function\") return await maybeText.call(blob);\n\n const maybeArrayBuffer = (blob as { arrayBuffer?: () => Promise<ArrayBuffer> })\n .arrayBuffer;\n if (typeof maybeArrayBuffer === \"function\") {\n return new TextDecoder().decode(await maybeArrayBuffer.call(blob));\n }\n\n return await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result ?? \"\"));\n reader.onerror = () =>\n reject(reader.error ?? new Error(\"could not read the file's bytes\"));\n reader.readAsText(blob);\n });\n}\n\nexport interface ViewerTextState {\n text: string | null;\n loading: boolean;\n error: string | null;\n /** True when the file exceeded `maxBytes` and only the head was read. */\n truncated: boolean;\n}\n\n/**\n * Bytes → text, capped. The cap is not a nicety: a 500MB log file decoded in\n * full takes the tab down, which is how the original previewers were written\n * and why the cap must travel with the package rather than be re-derived.\n */\nexport function useViewerText(\n source: MediaViewerSource,\n maxBytes = 1024 * 1024,\n): ViewerTextState {\n const { blob, loading, error: bytesError } = useViewerBytes(source);\n const [text, setText] = useState<string | null>(null);\n const [readError, setReadError] = useState<string | null>(null);\n const [truncated, setTruncated] = useState(false);\n\n useEffect(() => {\n if (!blob) {\n setText(null);\n return undefined;\n }\n let cancelled = false;\n setReadError(null);\n setText(null);\n setTruncated(false);\n void (async () => {\n try {\n const oversized = blob.size > maxBytes;\n const value = await readBlobText(\n oversized ? blob.slice(0, maxBytes) : blob,\n );\n if (cancelled) return;\n setTruncated(oversized);\n setText(value);\n } catch (err) {\n if (cancelled) return;\n setReadError(err instanceof Error ? err.message : String(err));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [blob, maxBytes]);\n\n const error = readError ?? bytesError;\n return {\n text,\n error,\n truncated,\n loading: (loading || text === null) && error === null,\n };\n}\n\nexport interface ViewerDisplayUrlState {\n /**\n * The URL a media element may bind. Durable by construction: it is either\n * a `MediaClient.resolve()` result or the host's own object URL.\n */\n url: string | null;\n /**\n * Whether the client's ONE retry policy can rescue a load failure. False\n * for object URLs and for resolutions the client marked unrecoverable\n * (foreign links) — a session refresh cannot resurrect someone else's URL.\n */\n recoverable: boolean;\n /** `resolve()` refused the ref — render the honest unavailable state. */\n unavailable: boolean;\n loading: boolean;\n}\n\n/**\n * The display URL for a viewer source. Law 2: even for a `ref` carrying a\n * caller-supplied URL, resolution goes through the client — the package never\n * trusts a string it was handed.\n */\nexport function useViewerDisplayUrl(\n source: MediaViewerSource,\n): ViewerDisplayUrlState {\n const resolved = useMediaResolution(\n source.kind === \"ref\" ? source.ref : null,\n );\n if (source.kind === \"blob\") {\n return {\n url: source.url,\n recoverable: false,\n unavailable: false,\n loading: false,\n };\n }\n return {\n url: resolved.resolution?.src ?? null,\n recoverable: resolved.resolution?.recoverable !== false,\n unavailable: resolved.status === \"unavailable\",\n loading: resolved.status === \"empty\",\n };\n}\n","/**\n * src/core/use-media-blob.ts — bytes for canvas/crossOrigin/private-pixel\n * consumers, as state.\n *\n * The behavior contract is ported from matrx-frontend `hooks/useFileBlob.ts`;\n * the byte machinery (auth, caching, in-flight dedup, IDB tiers, progress) is\n * the CLIENT's (C10 persistence-injected — the package owns no cache). The\n * hook owns only the React lifecycle: load on mount/ref change, release the\n * handle on unmount, expose a retry.\n */\n\nimport { useEffect, useState } from \"react\";\nimport type { MediaRefLike } from \"../types\";\nimport { useMediaClient } from \"./context\";\nimport { failureMediaIdentity, useMediaFailureCapture } from \"./diagnostics\";\nimport { stableRefKey } from \"./ref-key\";\n\n/** Structural HTTP status probe for client errors (never a validation). */\nfunction statusOf(err: unknown): number | undefined {\n if (err && typeof err === \"object\") {\n const candidate =\n (err as { status?: unknown }).status ??\n (err as { statusCode?: unknown }).statusCode;\n if (typeof candidate === \"number\") return candidate;\n }\n return undefined;\n}\n\nexport interface MediaBlobState {\n /** `blob:` object URL safe to feed into any browser API. `null` until ready. */\n url: string | null;\n blob: Blob | null;\n loading: boolean;\n error: string | null;\n /** Force a fresh byte read (the client decides whether to drop its cache). */\n retry: () => void;\n}\n\nexport function useMediaBlob(\n ref: MediaRefLike | null | undefined,\n): MediaBlobState {\n const client = useMediaClient();\n const capture = useMediaFailureCapture();\n const refKey = stableRefKey(ref);\n const [state, setState] = useState<{\n url: string | null;\n blob: Blob | null;\n loading: boolean;\n error: string | null;\n }>({ url: null, blob: null, loading: !!ref, error: null });\n const [retryToken, setRetryToken] = useState(0);\n\n useEffect(() => {\n if (!ref) {\n setState({ url: null, blob: null, loading: false, error: null });\n return undefined;\n }\n let cancelled = false;\n let release: (() => void) | null = null;\n setState({ url: null, blob: null, loading: true, error: null });\n client.getBlob(ref).then(\n (handle) => {\n if (cancelled) {\n handle.release();\n return;\n }\n release = handle.release;\n setState({ url: handle.url, blob: handle.blob, loading: false, error: null });\n },\n (err: unknown) => {\n if (cancelled) return;\n const message =\n err instanceof Error ? err.message : String(err ?? \"Failed to load file\");\n setState({ url: null, blob: null, loading: false, error: message });\n // Terminal-failure capture (phase \"blob\"): the private-pixels bytes\n // never arrived. Latched per media identity by the machinery.\n const status = statusOf(err);\n capture({\n phase: \"blob\",\n mediaRef: failureMediaIdentity(ref),\n terminal: true,\n message: `getBlob() failed: ${message}`,\n ...(status !== undefined ? { status } : {}),\n });\n },\n );\n return () => {\n cancelled = true;\n release?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, refKey, retryToken]);\n\n return {\n ...state,\n retry: () => setRetryToken((t) => t + 1),\n };\n}\n","/**\n * src/core/context.ts — the MediaClient / host-ports React contexts.\n *\n * The context OBJECTS live on `globalThis` under `Symbol.for` slots — NOT at\n * module level. With `splitting: false` this module is duplicated into the\n * `/core` and `/react` bundles, and CJS/ESM each instantiate their own module\n * graph; a module-level `createContext` would silently produce two different\n * contexts (a Provider from one graph invisible to a consumer from the\n * other) — the kit tap-target/link-registry lesson. Never \"clean this up\".\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n type Context,\n type ReactNode,\n} from \"react\";\nimport type { MediaClient, MediaHostPorts } from \"../types\";\n\nconst CLIENT_SLOT = Symbol.for(\"ai-matrx.media.client-context\");\nconst PORTS_SLOT = Symbol.for(\"ai-matrx.media.host-ports-context\");\n\ntype SlotHost = typeof globalThis & {\n [CLIENT_SLOT]?: Context<MediaClient | null>;\n [PORTS_SLOT]?: Context<MediaHostPorts>;\n};\n\nfunction clientContext(): Context<MediaClient | null> {\n const host = globalThis as SlotHost;\n host[CLIENT_SLOT] ??= createContext<MediaClient | null>(null);\n return host[CLIENT_SLOT];\n}\n\nconst INERT_PORTS: MediaHostPorts = {};\n\nfunction portsContext(): Context<MediaHostPorts> {\n const host = globalThis as SlotHost;\n host[PORTS_SLOT] ??= createContext<MediaHostPorts>(INERT_PORTS);\n return host[PORTS_SLOT];\n}\n\nexport interface MediaProviderProps {\n client: MediaClient;\n /**\n * Optional host ports (playback session, actions, ImageComponent). Must be\n * referentially stable — the playback port members are hooks.\n */\n ports?: MediaHostPorts | undefined;\n children?: ReactNode;\n}\n\n/** Wire the injected MediaClient (and optional host ports) into the tree. */\nexport function MediaProvider({ client, ports, children }: MediaProviderProps) {\n const ClientCtx = clientContext();\n const PortsCtx = portsContext();\n return createElement(\n ClientCtx.Provider,\n { value: client },\n createElement(PortsCtx.Provider, { value: ports ?? INERT_PORTS }, children),\n );\n}\n\n/** The injected MediaClient. Throws when no MediaProvider is mounted. */\nexport function useMediaClient(): MediaClient {\n const client = useContext(clientContext());\n if (!client) {\n throw new Error(\n \"@ai-matrx/media: no MediaClient. Mount <MediaProvider client={...}> \" +\n \"above every media surface (canonically wired to @ai-matrx/data/files).\",\n );\n }\n return client;\n}\n\n/** The injected host ports; inert defaults when none were provided. */\nexport function useMediaHostPorts(): MediaHostPorts {\n return useContext(portsContext());\n}\n","/**\n * src/core/diagnostics.ts — the terminal-failure capture machinery.\n *\n * Born from the 2026-08-30 prod outage: server-side cookie-secret drift\n * killed every private image, the package rendered its honest \"unavailable\"\n * panel — and nothing reached the host's Error Inspector or error DB,\n * because the package had no diagnostics port and the host cannot capture\n * what it never learns about. Per ruling C22 the capture logic lives HERE,\n * so every consuming repo inherits it.\n *\n * The contract:\n *\n * - every terminal failure path emits exactly ONE {@link MediaFailureInfo}\n * per media identity (latched — re-renders, remounts and the unavailable\n * panel backstop never spam);\n * - a bound `MediaHostPorts.diagnostics.capture` receives the payload;\n * WITHOUT one (or if it throws) the package `console.error`s the same\n * structured payload — the loud default. A media failure is NEVER silent;\n * - the payload never carries a signed URL: identity is the file id or a\n * query-stripped URL key ({@link failureMediaIdentity}).\n *\n * The latch lives on `globalThis` under a `Symbol.for` slot (same reason as\n * context.ts: with `splitting: false` + dual formats, module-level state\n * silently duplicates across bundle/loader graphs).\n */\n\nimport { useCallback, useRef } from \"react\";\nimport type { MediaFailureInfo, MediaRefLike } from \"../types\";\nimport { useMediaHostPorts } from \"./context\";\n\nconst LATCH_SLOT = Symbol.for(\"ai-matrx.media.failure-latch\");\n\ntype SlotHost = typeof globalThis & {\n [LATCH_SLOT]?: Set<string>;\n};\n\nfunction latch(): Set<string> {\n const host = globalThis as SlotHost;\n host[LATCH_SLOT] ??= new Set<string>();\n return host[LATCH_SLOT];\n}\n\n/**\n * Clear the once-per-failure latch. For tests, and for hosts at auth\n * boundaries (a sign-in can genuinely fix a previously-terminal failure, and\n * a recurrence after it deserves a fresh capture).\n */\nexport function resetMediaFailureLatch(): void {\n latch().clear();\n}\n\n/**\n * Durable diagnostics identity for a media reference. NEVER a signed URL:\n * file ids win, and any URL is stripped to origin + path (signatures ride\n * query strings).\n */\nexport function failureMediaIdentity(\n ref: MediaRefLike | null | undefined,\n src?: string | null,\n): string {\n if (ref && typeof ref === \"object\" && ref.file_id) return `file:${ref.file_id}`;\n let raw: string | null | undefined;\n if (typeof ref === \"string\") raw = ref;\n else if (ref && typeof ref === \"object\" && ref.url) raw = ref.url;\n else raw = src;\n if (!raw) return \"<unknown-media>\";\n if (raw.startsWith(\"blob:\")) return \"blob:object-url\";\n try {\n const u = new URL(raw);\n return `url:${u.origin}${u.pathname}`;\n } catch {\n // A bare fileId string, or an unparseable fragment — still strip any query.\n const clean = raw.split(/[?#]/, 1)[0] ?? raw;\n return `ref:${clean}`;\n }\n}\n\n/**\n * Emit one media-failure capture through the host sink, or the loud\n * console.error default when no sink is bound (or the sink throws).\n * Latched per (terminal|warning, mediaRef) — one capture per failure,\n * however many renders, hooks, or backstops observe it.\n */\nexport function emitMediaFailure(\n capture: ((info: MediaFailureInfo) => void) | undefined,\n info: MediaFailureInfo,\n): void {\n const key = `${info.terminal ? \"terminal\" : \"warning\"}|${info.mediaRef}`;\n const seen = latch();\n if (seen.has(key)) return;\n seen.add(key);\n if (capture) {\n try {\n capture(info);\n return;\n } catch {\n // A broken sink must not re-silence the failure — fall through.\n }\n }\n console.error(\n \"[@ai-matrx/media] media failure (no diagnostics sink captured it — \" +\n \"bind MediaHostPorts.diagnostics.capture to your error system)\",\n info,\n );\n}\n\n/**\n * Hook form: a stable capture function wired to the host ports. Every core\n * hook and the unavailable-panel backstop route through this — the phase\n * vocabulary and the latch stay in ONE place.\n */\nexport function useMediaFailureCapture(): (\n info: Omit<MediaFailureInfo, \"source\">,\n) => void {\n const ports = useMediaHostPorts();\n const capture = ports.diagnostics?.capture;\n // The latest sink without invalidating effect deps in the calling hooks —\n // the port object is referentially stable by contract, but a fresh binding\n // (e.g. tests swapping providers) must not capture stale.\n const captureRef = useRef(capture);\n captureRef.current = capture;\n return useCallback((info: Omit<MediaFailureInfo, \"source\">) => {\n emitMediaFailure(captureRef.current, { source: \"media\", ...info });\n }, []);\n}\n","/**\n * src/core/ref-key.ts — stable identity key for a MediaRefLike.\n *\n * Callers routinely pass fresh object literals every render; hooks key their\n * effects/memos on this string instead of object identity. Ported from the\n * original `stableSourceKey` (matrx-frontend `handler/hooks/useFileAs.ts`).\n */\n\nimport type { MediaRefLike } from \"../types\";\n\nexport function stableRefKey(ref: MediaRefLike | null | undefined): string {\n if (!ref) return \"<none>\";\n if (typeof ref === \"string\") return `s:${ref}`;\n if (ref.file_id) return `id:${ref.file_id}:${ref.mime_type ?? \"\"}`;\n if (ref.url) return `url:${ref.url}:${ref.mime_type ?? \"\"}`;\n return \"<empty-ref>\";\n}\n","/**\n * src/core/use-media-resolution.ts — ref → durable resolution, as state.\n *\n * Law 2: every consumer resolves media through the client, unconditionally —\n * even a caller-supplied URL string is classified, never trusted. Law 15 of\n * the handler (unavailable is a rendered state): a throwing `resolve()` is\n * classified via `classifyError` and returned as typed state — never\n * re-thrown. It IS however a terminal failure, so it also emits exactly one\n * `MediaFailureInfo` (phase \"resolve\") through the diagnostics machinery —\n * the 2026-08-30 outage rule: an unavailable render is honest to the USER but\n * must never be silent to the SYSTEM.\n */\n\nimport { useEffect, useMemo } from \"react\";\nimport type {\n MediaRefLike,\n MediaResolution,\n MediaUnavailableReason,\n} from \"../types\";\nimport { useMediaClient } from \"./context\";\nimport { failureMediaIdentity, useMediaFailureCapture } from \"./diagnostics\";\nimport { stableRefKey } from \"./ref-key\";\n\nexport interface MediaResolutionState {\n resolution: MediaResolution | null;\n /**\n * \"empty\" — no ref, or a ref with no usable identity (render fallback)\n * \"ready\" — resolution available\n * \"unavailable\" — resolve() refused (signed URL, access denied…); render\n * the typed unavailable state, never an incident\n */\n status: \"empty\" | \"ready\" | \"unavailable\";\n reason: MediaUnavailableReason | null;\n}\n\nexport function useMediaResolution(\n ref: MediaRefLike | null | undefined,\n): MediaResolutionState {\n const client = useMediaClient();\n const capture = useMediaFailureCapture();\n const refKey = stableRefKey(ref);\n const { state, failureMessage } = useMemo<{\n state: MediaResolutionState;\n failureMessage: string | null;\n }>(() => {\n if (!ref) {\n return {\n state: { resolution: null, status: \"empty\", reason: null },\n failureMessage: null,\n };\n }\n try {\n const resolution = client.resolve(ref);\n if (!resolution) {\n return {\n state: { resolution: null, status: \"empty\", reason: null },\n failureMessage: null,\n };\n }\n return {\n state: { resolution, status: \"ready\", reason: null },\n failureMessage: null,\n };\n } catch (err) {\n return {\n state: {\n resolution: null,\n status: \"unavailable\",\n reason: client.classifyError(err),\n },\n failureMessage:\n err instanceof Error ? err.message : String(err ?? \"resolve() failed\"),\n };\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, refKey]);\n\n // Terminal-failure capture (phase \"resolve\") — an effect, never a render\n // side effect; latched per media identity by the diagnostics machinery.\n useEffect(() => {\n if (state.status !== \"unavailable\") return;\n capture({\n phase: \"resolve\",\n mediaRef: failureMediaIdentity(ref ?? null),\n terminal: true,\n message: `resolve() refused (${state.reason ?? \"unknown\"}): ${\n failureMessage ?? \"no error message\"\n }`,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refKey, state.status]);\n\n return state;\n}\n","/**\n * src/core/file-kind.ts — filename/MIME → category, icon name, color.\n *\n * Condensed port of the icon-relevant slice of matrx-frontend\n * `features/files/utils/file-types.ts` (the FILE_TYPES registry): every\n * extension→{category,icon,color,displayName} row is preserved; the\n * preview/thumbnail/size-cap columns stay in the app (C8 — they belong to\n * the previewer world, not the media kit). MIME-prefix fallback, the\n * dotfile-looks-like-text heuristic, folder details and the unknown default\n * are ported verbatim in behavior.\n *\n * Platform-free: icon NAMES only — `/react` maps names to its inlined SVGs;\n * a future `/react-native` binding maps the same names to its own glyphs.\n */\n\nexport type FileCategory =\n | \"CODE\"\n | \"DOCUMENT\"\n | \"AUDIO\"\n | \"IMAGE\"\n | \"VIDEO\"\n | \"ARCHIVE\"\n | \"DATA\"\n | \"NOTEBOOK\"\n | \"SUBTITLES\"\n | \"EMAIL\"\n | \"EBOOK\"\n | \"MODEL_3D\"\n | \"UNKNOWN\"\n | \"FOLDER\";\n\nexport type FileIconName =\n | \"image\"\n | \"pen-tool\"\n | \"video\"\n | \"music\"\n | \"file-type\"\n | \"file-text\"\n | \"code\"\n | \"braces\"\n | \"subtitles\"\n | \"file-code\"\n | \"file-json\"\n | \"file-spreadsheet\"\n | \"database\"\n | \"package\"\n | \"archive\"\n | \"folder\"\n | \"folder-open\"\n | \"file\"\n | \"file-audio\"\n | \"file-video\";\n\nexport interface FileKindDetails {\n category: FileCategory;\n displayName: string;\n /** Tailwind text color token, matching the original registry exactly. */\n colorClass: string;\n icon: FileIconName;\n}\n\ntype Row = [\n extensions: string[],\n category: FileCategory,\n colorClass: string,\n icon: FileIconName,\n displayName: string,\n];\n\n// Rows ported from the FILE_TYPES registry (icon-relevant columns), grouped\n// exactly as the original's icon/color assignments group them.\nconst ROWS: Row[] = [\n [[\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"avif\", \"heic\", \"heif\", \"bmp\", \"tif\", \"tiff\", \"ico\"], \"IMAGE\", \"text-emerald-500\", \"image\", \"Image\"],\n [[\"svg\"], \"IMAGE\", \"text-amber-500\", \"pen-tool\", \"SVG image\"],\n [[\"mp4\", \"mov\", \"webm\", \"mkv\", \"avi\", \"m4v\"], \"VIDEO\", \"text-purple-500\", \"video\", \"Video\"],\n [[\"mp3\", \"wav\", \"ogg\", \"m4a\", \"aac\", \"flac\", \"opus\"], \"AUDIO\", \"text-pink-500\", \"music\", \"Audio\"],\n [[\"pdf\"], \"DOCUMENT\", \"text-red-500\", \"file-type\", \"PDF Document\"],\n [[\"md\", \"markdown\", \"mdx\", \"rst\", \"adoc\", \"asciidoc\", \"org\"], \"DOCUMENT\", \"text-slate-400\", \"file-text\", \"Markdown\"],\n [[\"txt\", \"text\", \"asc\", \"me\", \"log\", \"out\", \"err\"], \"DOCUMENT\", \"text-muted-foreground\", \"file-text\", \"Text\"],\n [[\"dockerfile\", \"containerfile\", \"lua\"], \"CODE\", \"text-blue-500\", \"code\", \"Code\"],\n [[\"mk\", \"make\", \"swift\", \"ml\", \"mli\", \"fs\", \"fsi\", \"fsx\", \"svelte\"], \"CODE\", \"text-orange-500\", \"code\", \"Code\"],\n [[\"diff\", \"patch\", \"pem\", \"csr\", \"crt\", \"cer\", \"der\", \"key\", \"pub\", \"p7b\", \"p7c\", \"pfx\", \"p12\"], \"CODE\", \"text-amber-500\", \"file-text\", \"Text\"],\n [[\"ini\", \"cfg\", \"conf\", \"config\", \"properties\", \"prefs\"], \"CODE\", \"text-amber-400\", \"braces\", \"Config\"],\n [[\"tex\", \"latex\", \"ltx\", \"sty\", \"cls\", \"bib\"], \"CODE\", \"text-emerald-500\", \"file-text\", \"LaTeX\"],\n [[\"srt\", \"vtt\"], \"SUBTITLES\", \"text-cyan-500\", \"subtitles\", \"Subtitles\"],\n [[\"js\", \"mjs\", \"cjs\", \"jsx\"], \"CODE\", \"text-yellow-500\", \"file-code\", \"JavaScript\"],\n [[\"ts\", \"tsx\"], \"CODE\", \"text-blue-500\", \"file-code\", \"TypeScript\"],\n [[\"py\", \"clj\", \"cljs\", \"cljc\", \"edn\", \"vue\", \"styl\", \"stylus\"], \"CODE\", \"text-emerald-500\", \"code\", \"Code\"],\n [[\"rb\", \"rbw\", \"rake\", \"ru\", \"gemspec\", \"scala\", \"sbt\"], \"CODE\", \"text-red-500\", \"code\", \"Code\"],\n [[\"go\", \"dart\"], \"CODE\", \"text-cyan-500\", \"code\", \"Code\"],\n [[\"rs\"], \"CODE\", \"text-orange-600\", \"code\", \"Rust\"],\n [[\"java\"], \"CODE\", \"text-red-600\", \"code\", \"Java\"],\n [[\"c\", \"h\"], \"CODE\", \"text-blue-600\", \"code\", \"C\"],\n [[\"cpp\", \"cc\", \"cxx\", \"hpp\"], \"CODE\", \"text-blue-700\", \"code\", \"C++\"],\n [[\"cs\"], \"CODE\", \"text-purple-600\", \"code\", \"C#\"],\n [[\"html\", \"htm\", \"kt\", \"kts\"], \"CODE\", \"text-orange-400\", \"code\", \"Code\"],\n [[\"css\"], \"CODE\", \"text-sky-400\", \"code\", \"CSS\"],\n [[\"scss\"], \"CODE\", \"text-pink-400\", \"code\", \"SCSS\"],\n [[\"sh\", \"bash\", \"zsh\", \"fish\", \"ksh\", \"ash\", \"bat\", \"cmd\", \"twig\", \"jinja\", \"j2\", \"njk\"], \"CODE\", \"text-emerald-400\", \"code\", \"Script\"],\n [[\"sql\"], \"CODE\", \"text-amber-400\", \"code\", \"SQL\"],\n [[\"pl\", \"pm\"], \"CODE\", \"text-indigo-400\", \"code\", \"Perl\"],\n [[\"r\", \"rmd\", \"proto\", \"ps1\", \"psm1\", \"psd1\", \"less\"], \"CODE\", \"text-blue-400\", \"code\", \"Code\"],\n [[\"ex\", \"exs\"], \"CODE\", \"text-purple-400\", \"code\", \"Elixir\"],\n [[\"erl\", \"hrl\"], \"CODE\", \"text-rose-500\", \"code\", \"Erlang\"],\n [[\"hs\", \"lhs\"], \"CODE\", \"text-violet-500\", \"code\", \"Haskell\"],\n [[\"zig\"], \"CODE\", \"text-yellow-500\", \"code\", \"Zig\"],\n [[\"nim\", \"nims\"], \"CODE\", \"text-yellow-400\", \"code\", \"Nim\"],\n [[\"jl\"], \"CODE\", \"text-purple-500\", \"code\", \"Julia\"],\n [[\"astro\"], \"CODE\", \"text-fuchsia-500\", \"code\", \"Astro\"],\n [[\"graphql\", \"gql\", \"graphqls\"], \"CODE\", \"text-pink-500\", \"code\", \"GraphQL\"],\n [[\"sol\"], \"CODE\", \"text-slate-400\", \"code\", \"Solidity\"],\n [[\"php\", \"phtml\", \"phps\"], \"CODE\", \"text-indigo-500\", \"code\", \"PHP\"],\n [[\"hbs\", \"handlebars\", \"mustache\", \"ejs\", \"liquid\"], \"CODE\", \"text-amber-500\", \"code\", \"Template\"],\n [[\"json\", \"jsonc\", \"json5\", \"har\", \"geojson\", \"topojson\"], \"DATA\", \"text-amber-500\", \"file-json\", \"JSON\"],\n [[\"yaml\", \"yml\", \"toml\"], \"CODE\", \"text-amber-500\", \"braces\", \"Config\"],\n [[\"xml\"], \"DATA\", \"text-amber-500\", \"braces\", \"XML\"],\n [[\"csv\", \"tsv\"], \"DATA\", \"text-orange-500\", \"file-spreadsheet\", \"Spreadsheet data\"],\n [[\"sqlite\", \"sqlite3\", \"db\"], \"DATA\", \"text-blue-400\", \"database\", \"Database\"],\n [[\"ttl\", \"n3\", \"nt\", \"nq\", \"trig\"], \"DATA\", \"text-fuchsia-400\", \"braces\", \"RDF data\"],\n [[\"xlsx\", \"xls\"], \"DOCUMENT\", \"text-emerald-600\", \"file-spreadsheet\", \"Excel workbook\"],\n [[\"doc\", \"docx\"], \"DOCUMENT\", \"text-blue-500\", \"file-text\", \"Word document\"],\n [[\"ppt\", \"pptx\"], \"DOCUMENT\", \"text-orange-600\", \"file-type\", \"Presentation\"],\n [[\"ipynb\"], \"NOTEBOOK\", \"text-orange-400\", \"file-json\", \"Notebook\"],\n [[\"epub\"], \"EBOOK\", \"text-indigo-500\", \"file-text\", \"eBook\"],\n [[\"eml\"], \"EMAIL\", \"text-blue-400\", \"file-text\", \"Email\"],\n [[\"glb\", \"gltf\", \"stl\", \"obj\", \"fbx\"], \"MODEL_3D\", \"text-violet-400\", \"package\", \"3D model\"],\n [[\"zip\", \"rar\", \"7z\"], \"ARCHIVE\", \"text-amber-600\", \"archive\", \"Archive\"],\n [[\"tar\", \"gz\", \"tgz\"], \"ARCHIVE\", \"text-amber-600\", \"package\", \"Archive\"],\n];\n\nconst BY_EXTENSION = new Map<string, FileKindDetails>();\nfor (const [extensions, category, colorClass, icon, displayName] of ROWS) {\n for (const ext of extensions) {\n BY_EXTENSION.set(ext, { category, colorClass, icon, displayName });\n }\n}\n\nconst UNKNOWN_DETAILS: FileKindDetails = {\n category: \"UNKNOWN\",\n displayName: \"File\",\n colorClass: \"text-muted-foreground\",\n icon: \"file\",\n};\n\nconst ASSUMED_TEXT_DETAILS: FileKindDetails = {\n category: \"DOCUMENT\",\n displayName: \"Text\",\n colorClass: \"text-muted-foreground\",\n icon: \"file-text\",\n};\n\nconst FOLDER_DETAILS: FileKindDetails = {\n category: \"FOLDER\",\n displayName: \"Folder\",\n colorClass: \"text-sky-500\",\n icon: \"folder\",\n};\n\nconst IMAGE_DETAILS = BY_EXTENSION.get(\"png\") as FileKindDetails;\nconst VIDEO_DETAILS = BY_EXTENSION.get(\"mp4\") as FileKindDetails;\nconst AUDIO_DETAILS = BY_EXTENSION.get(\"mp3\") as FileKindDetails;\nconst PDF_DETAILS = BY_EXTENSION.get(\"pdf\") as FileKindDetails;\nconst SVG_DETAILS = BY_EXTENSION.get(\"svg\") as FileKindDetails;\n\nfunction basenameOf(path: string): string {\n const idx = Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\"));\n return idx >= 0 ? path.slice(idx + 1) : path;\n}\n\nfunction extOf(name: string): string | null {\n const idx = name.lastIndexOf(\".\");\n if (idx <= 0 || idx === name.length - 1) return null;\n return name.slice(idx + 1).toLowerCase();\n}\n\n/**\n * Dotfile heuristic (ported): unrecognized dotfiles are almost always text —\n * bias toward the text profile instead of the binary \"File\" default.\n */\nfunction dotfileLooksLikeText(filename: string): boolean {\n const name = basenameOf(filename);\n if (!name.startsWith(\".\")) return false;\n for (let i = 1; i < name.length; i++) {\n const c = name.charCodeAt(i);\n if (\n (c >= 48 && c <= 57) ||\n (c >= 65 && c <= 90) ||\n (c >= 97 && c <= 122) ||\n c === 95 ||\n c === 45\n ) {\n return true;\n }\n }\n return false;\n}\n\n/** Strip MIME parameters (`;codecs=opus`, etc.). */\nfunction canonicalMimeBase(raw: string): string {\n return raw.split(\";\")[0]?.trim().toLowerCase() ?? raw;\n}\n\n/**\n * Resolve icon details from a filename and (optionally) the server MIME.\n * MIME-prefix override handles \"the browser knows `image/avif` but the\n * extension table doesn't\" — and disambiguates audio/webm vs video/webm.\n */\nexport function getFileKindDetails(\n fileName: string,\n mimeType?: string | null,\n): FileKindDetails {\n const name = basenameOf(fileName);\n const lower = name.toLowerCase();\n const ext = lower === \"dockerfile\" || lower === \"containerfile\" ? lower : extOf(name);\n const fromExt = ext ? BY_EXTENSION.get(ext) : undefined;\n\n const mime = mimeType ? canonicalMimeBase(mimeType) : null;\n if (mime) {\n if (mime === \"image/svg+xml\") return fromExt ?? SVG_DETAILS;\n if (mime.startsWith(\"image/\")) return fromExt?.category === \"IMAGE\" ? fromExt : IMAGE_DETAILS;\n if (mime.startsWith(\"video/\")) return fromExt?.category === \"VIDEO\" ? fromExt : VIDEO_DETAILS;\n if (mime.startsWith(\"audio/\")) return fromExt?.category === \"AUDIO\" ? fromExt : AUDIO_DETAILS;\n if (mime === \"application/pdf\") return PDF_DETAILS;\n }\n\n if (fromExt) return fromExt;\n if (dotfileLooksLikeText(fileName)) return ASSUMED_TEXT_DETAILS;\n return UNKNOWN_DETAILS;\n}\n\n/** Folder icon details (open picks the open-folder glyph). */\nexport function getFolderKindDetails(open = false): FileKindDetails {\n return open ? { ...FOLDER_DETAILS, icon: \"folder-open\" } : FOLDER_DETAILS;\n}\n","/**\n * src/react/file-icon.tsx — icon tile for any file or folder.\n *\n * Verbatim port of matrx-frontend `components/core/FileIcon/FileIcon.tsx`\n * with two seam inversions: the registry lookup is the package's own\n * `getFileKindDetails` (`/core`), and the glyphs are the package's own\n * inlined SVGs (C19 — no lucide peer).\n */\n\nimport type { CSSProperties } from \"react\";\nimport {\n getFileKindDetails,\n getFolderKindDetails,\n type FileIconName,\n} from \"../core/file-kind\";\nimport { cn } from \"./cn\";\nimport {\n ArchiveIcon,\n BracesIcon,\n CodeIcon,\n DatabaseIcon,\n FileAudioIcon,\n FileCodeIcon,\n FileIcon as FileGlyph,\n FileJsonIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n FileTypeIcon,\n FileVideoIcon,\n FolderIcon,\n FolderOpenIcon,\n ImageIcon,\n MusicIcon,\n PackageBoxIcon,\n PenToolIcon,\n SubtitlesIcon,\n VideoIcon,\n type MediaIconProps,\n} from \"./icons\";\n\nconst ICONS: Record<FileIconName, (props: MediaIconProps) => ReturnType<typeof FileGlyph>> = {\n image: ImageIcon,\n \"pen-tool\": PenToolIcon,\n video: VideoIcon,\n music: MusicIcon,\n \"file-type\": FileTypeIcon,\n \"file-text\": FileTextIcon,\n code: CodeIcon,\n braces: BracesIcon,\n subtitles: SubtitlesIcon,\n \"file-code\": FileCodeIcon,\n \"file-json\": FileJsonIcon,\n \"file-spreadsheet\": FileSpreadsheetIcon,\n database: DatabaseIcon,\n package: PackageBoxIcon,\n archive: ArchiveIcon,\n folder: FolderIcon,\n \"folder-open\": FolderOpenIcon,\n file: FileGlyph,\n \"file-audio\": FileAudioIcon,\n \"file-video\": FileVideoIcon,\n};\n\nexport interface FileIconProps {\n /** Either the filename (for files) or omitted for folders. */\n fileName?: string | undefined;\n /** Server MIME — when set, resolves audio/webm vs video/webm correctly. */\n mimeType?: string | null | undefined;\n /** If true, renders a folder icon. `open` picks the open-folder glyph. */\n isFolder?: boolean | undefined;\n open?: boolean | undefined;\n /** Override the mapped color (useful for selected states). */\n colorClass?: string | undefined;\n className?: string | undefined;\n size?: number | undefined;\n}\n\nexport function FileIcon({\n fileName,\n mimeType = null,\n isFolder,\n open,\n colorClass,\n className,\n size = 16,\n}: FileIconProps) {\n const details = isFolder\n ? getFolderKindDetails(open)\n : getFileKindDetails(fileName ?? \"\", mimeType);\n const Icon = ICONS[details.icon];\n const style: CSSProperties = {\n width: `${size}px`,\n height: `${size}px`,\n minWidth: `${size}px`,\n };\n return (\n <Icon\n style={style}\n className={cn(\"shrink-0\", colorClass ?? details.colorClass, className)}\n aria-hidden=\"true\"\n />\n );\n}\n","/**\n * src/viewers/generic-viewer.tsx — the no-dedicated-viewer card.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/GenericPreview.tsx`.\n *\n * DEFECT FIXED IN THE PORT (recorded in CHANGELOG 0.4.0, never silently):\n * the original shipped a `DEBUG_RING_GENERIC_PREVIEW` fuchsia ring plus a\n * \"GenericPreview\" corner badge — a layering-debug artifact marked \"Rip this\n * out when done\" that reached users on every unpreviewable file. Absorption\n * kills it; the package has no debug chrome.\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { FileIcon } from \"../react/file-icon\";\nimport { DownloadIcon, FileTextIcon, SpinnerIcon } from \"../react/icons\";\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport type { MediaViewerProps } from \"./types\";\n\nexport function GenericViewer({\n fileName,\n fileSize,\n generic,\n className,\n}: MediaViewerProps) {\n const onDownload = generic?.onDownload;\n const onViewAsText = generic?.onViewAsText;\n const viewAsTextLabel = generic?.viewAsTextLabel ?? \"View as text\";\n const viewAsTextPrimary = generic?.viewAsTextPrimary ?? true;\n const viewAsTextBusy = generic?.viewAsTextBusy ?? false;\n const hasViewAsText = typeof onViewAsText === \"function\";\n const hasDownload = typeof onDownload === \"function\";\n\n return (\n <div\n className={cn(\n \"relative flex h-full w-full flex-col items-center justify-center gap-4 p-6 text-center\",\n className,\n )}\n >\n <FileIcon fileName={fileName} size={48} />\n <div>\n <p className=\"max-w-md truncate text-sm font-medium\">{fileName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {formatFileSize(fileSize ?? null)}\n </p>\n </div>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n {generic?.message ??\n (hasViewAsText\n ? \"No built-in previewer for this file type.\"\n : \"This file type can't be previewed here.\")}\n </p>\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n {onViewAsText && viewAsTextPrimary ? (\n <ViewAsTextButton\n onClick={onViewAsText}\n label={viewAsTextLabel}\n busy={viewAsTextBusy}\n variant=\"primary\"\n />\n ) : null}\n {onDownload ? (\n <button\n type=\"button\"\n onClick={onDownload}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm\",\n hasViewAsText && viewAsTextPrimary\n ? \"border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\",\n )}\n >\n <DownloadIcon className=\"h-4 w-4\" />\n Download\n </button>\n ) : null}\n {onViewAsText && !viewAsTextPrimary ? (\n <ViewAsTextButton\n onClick={onViewAsText}\n label={viewAsTextLabel}\n busy={viewAsTextBusy}\n variant=\"secondary\"\n />\n ) : null}\n </div>\n {!hasDownload && !hasViewAsText ? (\n <p className=\"max-w-sm text-[11px] text-muted-foreground/70\">\n Download it from the file's actions menu to open it in another\n application.\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction ViewAsTextButton({\n onClick,\n label,\n busy,\n variant,\n}: {\n onClick: () => void;\n label: string;\n busy: boolean;\n variant: \"primary\" | \"secondary\";\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={busy}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-60\",\n variant === \"primary\"\n ? \"bg-primary text-primary-foreground hover:bg-primary/90\"\n : \"border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n >\n {busy ? (\n <SpinnerIcon className=\"h-4 w-4 animate-spin\" />\n ) : (\n <FileTextIcon className=\"h-4 w-4\" />\n )}\n {label}\n </button>\n );\n}\n","/**\n * src/viewers/html-viewer.tsx — saved-HTML viewer (rendered + source).\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/HtmlPreview.tsx`.\n *\n * THE SANDBOX IS THE POINT, AND IT IS WHY THIS BELONGS IN THE PACKAGE. The\n * rendered view mounts `sandbox=\"allow-scripts allow-popups allow-forms\"`\n * WITHOUT `allow-same-origin`: the framed page may run scripts (most saved\n * pages need them to look right) but cannot read the host app's cookies,\n * browser persistence, or call its APIs, and cannot navigate the top frame.\n * `referrerPolicy=\"no-referrer\"` keeps the durable URL out of the framed\n * page's outbound requests. Every app that renders user-supplied HTML needs\n * exactly this attribute set, and getting one token wrong is a real XSS —\n * the textbook case for Arman's third test (\"less-than-perfect unless done\n * perfectly → in the package\"). Hosts do not get to configure it.\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { ViewerError, ViewerSkeleton } from \"./chrome\";\nimport { MarkupModeToggle, useMarkupMode } from \"./markup-chrome\";\nimport type { MediaViewerProps, MediaViewerViewport } from \"./types\";\nimport { useViewerDisplayUrl, useViewerText } from \"./use-viewer-bytes\";\n\n/** Device widths for the viewport simulator. Ported from the original. */\nconst VIEWPORT_WIDTH: Record<Exclude<MediaViewerViewport, \"auto\">, number> = {\n mobile: 390,\n tablet: 768,\n desktop: 1280,\n};\n\nexport function HtmlViewer(props: MediaViewerProps) {\n const { className, fileName, markupControls } = props;\n const { mode, setMode, controlled } = useMarkupMode(markupControls);\n\n return (\n <div className={cn(\"flex h-full w-full flex-col\", className)}>\n {controlled ? null : (\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-border/60 bg-background px-3 py-1.5 text-xs\">\n <span className=\"truncate font-medium text-foreground\">\n {fileName}\n </span>\n <MarkupModeToggle\n mode={mode}\n onChange={setMode}\n renderedLabel=\"Rendered\"\n renderedIcon=\"globe\"\n />\n </div>\n )}\n <div className=\"relative min-h-0 flex-1\">\n {mode === \"rendered\" ? (\n <HtmlRenderedView {...props} />\n ) : (\n <HtmlSourceView {...props} />\n )}\n </div>\n </div>\n );\n}\n\nfunction HtmlRenderedView({ source, fileName, markupControls }: MediaViewerProps) {\n const { url, unavailable } = useViewerDisplayUrl(source);\n const viewport = markupControls?.viewport ?? \"auto\";\n const reloadKey = markupControls?.reloadKey ?? 0;\n const [errored, setErrored] = useState(false);\n\n useEffect(() => {\n setErrored(false);\n }, [reloadKey, url]);\n\n if (unavailable) {\n return (\n <ViewerError\n title=\"This page isn't available\"\n hint=\"You may not have access to it, or it may have been deleted.\"\n />\n );\n }\n if (!url) return <ViewerSkeleton />;\n if (errored) return <ViewerError title=\"Preview unavailable\" />;\n\n const constrained = viewport !== \"auto\";\n const width = constrained ? VIEWPORT_WIDTH[viewport] : undefined;\n\n return (\n <div\n className={cn(\n \"h-full w-full overflow-auto bg-muted/10\",\n constrained && \"flex items-start justify-center\",\n )}\n >\n <div\n className={cn(\n \"h-full bg-background\",\n constrained\n ? \"my-4 overflow-hidden rounded-md border border-border/60 shadow-lg\"\n : \"w-full\",\n )}\n style={constrained ? { width } : undefined}\n >\n <iframe\n // `reloadKey` in the key forces a clean re-mount on an explicit reload.\n key={`${reloadKey}-${url}`}\n src={url}\n title={fileName}\n // NEVER add `allow-same-origin` here — see the module header.\n sandbox=\"allow-scripts allow-popups allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0 bg-white\"\n onError={() => setErrored(true)}\n />\n </div>\n </div>\n );\n}\n\nfunction HtmlSourceView({ source, maxBytes = 1024 * 1024 }: MediaViewerProps) {\n const { text, error, loading } = useViewerText(source, maxBytes);\n if (error) return <ViewerError title=\"Couldn't load source\" message={error} />;\n if (loading || text === null) return <ViewerSkeleton />;\n return (\n <pre className=\"h-full w-full overflow-auto bg-muted/10 p-4 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap\">\n {text}\n </pre>\n );\n}\n","/**\n * src/viewers/markup-chrome.tsx — the rendered/source switch shared by the\n * SVG and HTML viewers, and the controlled/uncontrolled mode resolution both\n * of them need.\n *\n * The matrx-frontend originals each hand-rolled this (SvgPreview a floating\n * segmented control, HtmlPreview a header strip), and each hard-wired itself\n * to the app's `FileViewerControlsContext`. Here the host rail arrives as\n * OPTIONAL props: when a host drives the mode, the viewer hides its own\n * toolbar and obeys; when nothing drives it, the viewer is fully capable on\n * its own (C23).\n */\n\n\"use client\";\n\nimport { useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { CodeIcon, GlobeIcon, ImageIcon } from \"../react/icons\";\nimport type { MediaViewerMarkupControls, MediaViewerMarkupMode } from \"./types\";\n\nexport interface ResolvedMarkupMode {\n mode: MediaViewerMarkupMode;\n setMode: (mode: MediaViewerMarkupMode) => void;\n /** True when the HOST drives the mode — the viewer must not draw a toolbar. */\n controlled: boolean;\n}\n\nexport function useMarkupMode(\n controls: MediaViewerMarkupControls | undefined,\n): ResolvedMarkupMode {\n const [localMode, setLocalMode] = useState<MediaViewerMarkupMode>(\"rendered\");\n const controlled = controls?.mode !== undefined;\n return {\n mode: controls?.mode ?? localMode,\n setMode: controls?.onModeChange ?? setLocalMode,\n controlled,\n };\n}\n\nexport function MarkupModeToggle({\n mode,\n onChange,\n renderedLabel = \"Rendered\",\n renderedIcon = \"image\",\n className,\n}: {\n mode: MediaViewerMarkupMode;\n onChange: (mode: MediaViewerMarkupMode) => void;\n renderedLabel?: string | undefined;\n renderedIcon?: \"image\" | \"globe\" | undefined;\n className?: string | undefined;\n}) {\n return (\n <div className={cn(\"flex items-center gap-0.5\", className)}>\n <ToggleButton\n active={mode === \"rendered\"}\n onClick={() => onChange(\"rendered\")}\n label={renderedLabel}\n icon={\n renderedIcon === \"globe\" ? (\n <GlobeIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <ImageIcon className=\"h-3.5 w-3.5\" />\n )\n }\n />\n <ToggleButton\n active={mode === \"source\"}\n onClick={() => onChange(\"source\")}\n label=\"Source\"\n icon={<CodeIcon className=\"h-3.5 w-3.5\" />}\n />\n </div>\n );\n}\n\nfunction ToggleButton({\n active,\n onClick,\n icon,\n label,\n}: {\n active: boolean;\n onClick: () => void;\n icon: React.ReactNode;\n label: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded px-2 py-1 text-[11px] font-medium transition-colors\",\n active\n ? \"bg-accent text-accent-foreground\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n )}\n >\n {icon}\n <span>{label}</span>\n </button>\n );\n}\n","/**\n * src/viewers/svg-viewer.tsx — SVG viewer (rendered + XML source).\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/SvgPreview.tsx`.\n *\n * SVG is the one image format that is also text, so it gets two views. The\n * rendered view obtains authenticated bytes through the MediaClient and binds\n * its lifecycle-owned object URL to `<img>`; the source view decodes the same\n * client-managed bytes only when the user asks. A private durable download URL\n * cannot attach a bearer token from an image element, so refs never bind that\n * locator directly.\n *\n * Seam inversions from the original: `recognizeOurFileUrl` (the host's\n * recoverability classifier) becomes `MediaResolution.recoverable`, which the\n * MediaClient already decides; `useFileBlob` becomes `useViewerText`; the\n * transparency grid ships as package CSS-in-style rather than the host's\n * `bg-checkerboard` utility (which no fresh app would have — C26).\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { useMediaBlob } from \"../core/use-media-blob\";\nimport { ViewerError, ViewerSkeleton } from \"./chrome\";\nimport { MarkupModeToggle, useMarkupMode } from \"./markup-chrome\";\nimport { TRANSPARENCY_GRID_STYLE } from \"./transparency-grid\";\nimport type { MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\nexport function SvgViewer(props: MediaViewerProps) {\n const { className, markupControls } = props;\n const { mode, setMode, controlled } = useMarkupMode(markupControls);\n\n return (\n <div\n className={cn(\n \"relative flex h-full min-h-0 w-full flex-col bg-background\",\n className,\n )}\n >\n {controlled ? null : (\n <MarkupModeToggle\n mode={mode}\n onChange={setMode}\n className=\"absolute top-3 right-3 z-10 rounded-md border border-border bg-background/95 p-0.5 shadow-sm backdrop-blur-sm\"\n />\n )}\n {mode === \"rendered\" ? (\n <SvgRenderedView {...props} />\n ) : (\n <SvgSourceView {...props} />\n )}\n </div>\n );\n}\n\nfunction SvgRenderedView({ source, fileName }: MediaViewerProps) {\n // An SVG is an active document, not just a passive image. Always render a\n // ref from authenticated bytes through the client's lifecycle-owned blob\n // URL: a private `/files/{id}/download` locator cannot attach a bearer token\n // when it is bound directly to `<img src>`, and a public display URL is not a\n // promise that its pixels are safe for every browser consumer. Blob sources\n // already carry their own host-owned URL and must never touch the client.\n const fromClient = useMediaBlob(source.kind === \"ref\" ? source.ref : null);\n const [normalizedUrl, setNormalizedUrl] = useState<string | null>(null);\n useEffect(() => {\n const blob = fromClient.blob;\n if (!blob || blob.type === \"image/svg+xml\") {\n setNormalizedUrl(null);\n return undefined;\n }\n // Upload/storage services commonly label SVG bytes as generic XML. An\n // object URL preserves that MIME, and browsers then reject it as an image\n // even though the authenticated bytes are valid SVG. Re-label the same\n // bytes locally; the package owns and revokes this derived URL.\n const normalized = new Blob([blob], { type: \"image/svg+xml\" });\n const objectUrl = URL.createObjectURL(normalized);\n setNormalizedUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [fromClient.blob]);\n const url =\n source.kind === \"blob\" ? source.url : normalizedUrl ?? fromClient.url;\n const loading = source.kind === \"ref\" && fromClient.loading;\n const error = source.kind === \"ref\" ? fromClient.error : null;\n\n if (error) {\n return (\n <ViewerError\n title=\"SVG could not be rendered\"\n message={error}\n hint=\"Switch to the Source view to inspect the markup.\"\n />\n );\n }\n if (loading || !url) return <ViewerSkeleton className=\"flex-1\" />;\n\n return (\n <div\n className=\"flex flex-1 items-center justify-center overflow-auto p-4\"\n style={TRANSPARENCY_GRID_STYLE}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n src={url}\n alt={fileName}\n className=\"max-h-full max-w-full object-contain drop-shadow-sm\"\n />\n </div>\n );\n}\n\nfunction SvgSourceView({ source, maxBytes = 1024 * 1024 }: MediaViewerProps) {\n const { text, error, loading } = useViewerText(source, maxBytes);\n if (error) return <ViewerError title=\"Could not load source\" message={error} />;\n if (loading || text === null) return <ViewerSkeleton className=\"flex-1\" />;\n return (\n <pre className=\"m-0 flex-1 overflow-auto bg-muted/20 px-4 py-3 font-mono text-xs leading-relaxed break-words whitespace-pre-wrap text-foreground\">\n {text}\n </pre>\n );\n}\n","/**\n * src/viewers/transparency-grid.ts — the alpha-channel checkerboard.\n *\n * Ships as inline style rather than a utility class: the matrx-frontend\n * originals used two different mechanisms for the same thing (an inline\n * gradient stack in ImagePreview, a `bg-checkerboard` utility in SvgPreview),\n * and a utility class is exactly the kind of host-owned dependency C26 bans a\n * package component from assuming. Sized in CSS pixels so the pattern reads\n * the same at any zoom.\n */\n\nexport const TRANSPARENCY_GRID_STYLE: {\n backgroundImage: string;\n backgroundSize: string;\n backgroundPosition: string;\n} = {\n backgroundImage:\n \"linear-gradient(45deg, rgb(0 0 0 / 0.08) 25%, transparent 25%), \" +\n \"linear-gradient(-45deg, rgb(0 0 0 / 0.08) 25%, transparent 25%), \" +\n \"linear-gradient(45deg, transparent 75%, rgb(0 0 0 / 0.08) 75%), \" +\n \"linear-gradient(-45deg, transparent 75%, rgb(0 0 0 / 0.08) 75%)\",\n backgroundSize: \"16px 16px\",\n backgroundPosition: \"0 0, 0 8px, 8px -8px, -8px 0\",\n};\n","/**\n * src/viewers/text-viewer.tsx — plain-text viewer.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/TextPreview.tsx`\n * (behavior ported verbatim; the byte/text/cap machinery moved to\n * `useViewerText`, the error card and copy button to `chrome.tsx`).\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { formatCount } from \"@ai-matrx/kit/format\";\nimport { ViewerCopyButton, ViewerError, ViewerSkeleton, ViewerToolbar, truncationNote } from \"./chrome\";\nimport type { MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\nexport function TextViewer({\n source,\n className,\n maxBytes = 1024 * 1024,\n}: MediaViewerProps) {\n const { text, error, loading, truncated } = useViewerText(source, maxBytes);\n\n if (error) return <ViewerError message={error} className={className} />;\n if (loading || text === null) {\n return <ViewerSkeleton tone=\"plain\" className={className} />;\n }\n\n return (\n <div\n className={cn(\"flex h-full w-full flex-col overflow-hidden\", className)}\n >\n <ViewerToolbar>\n <span className=\"text-muted-foreground\">\n {truncated\n ? `Preview ${truncationNote(maxBytes)}.`\n : `${formatCount(text.length)} characters`}\n </span>\n <ViewerCopyButton text={text} />\n </ViewerToolbar>\n <pre className=\"flex-1 overflow-auto bg-background p-3 font-mono text-xs leading-5 break-words whitespace-pre-wrap\">\n {text}\n </pre>\n </div>\n );\n}\n","/**\n * src/viewers/unavailable-viewer.tsx — THE ANNOUNCING DEFAULT (C23 + law 4,\n * \"nothing fails silently\").\n *\n * This renders when a kind needs a heavy engine the host has not registered\n * (PDF.js, a Markdown/KaTeX stack, SheetJS, an Office extractor). It is the\n * one place in the package where a default IS a shortfall, so unlike the\n * code viewer's un-highlighted default it says so — plainly, with the remedy\n * — and it still gives the user every action that remains possible: the\n * generic card's download / view-as-text escape hatches.\n *\n * The forbidden alternatives are a blank pane, a spinner that never resolves,\n * and a disabled-looking control. A screen is absent or honest.\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { GenericViewer } from \"./generic-viewer\";\nimport type { MediaViewerKind, MediaViewerProps } from \"./types\";\n\n/** What a host must register to make this kind render properly. */\nconst ENGINE_FOR_KIND: Partial<Record<MediaViewerKind, string>> = {\n pdf: \"a PDF engine (e.g. PDF.js / react-pdf)\",\n markdown: \"a Markdown renderer\",\n data: \"a spreadsheet/CSV parser\",\n spreadsheet: \"a spreadsheet/CSV parser\",\n office: \"an Office document extractor\",\n image: \"an image viewer\",\n video: \"a video player\",\n audio: \"an audio player\",\n};\n\nexport function MediaViewerUnavailable({\n kind,\n ...props\n}: MediaViewerProps & { kind: MediaViewerKind }) {\n const engine = ENGINE_FOR_KIND[kind] ?? `a \"${kind}\" viewer`;\n const generic = props.generic;\n return (\n <div className={cn(\"flex h-full w-full flex-col\", props.className)}>\n <div className=\"shrink-0 border-b border-amber-500/30 bg-amber-500/10 px-3 py-2 text-center text-xs text-amber-700 dark:text-amber-300\">\n No {kind} viewer is registered in this app, so this file can't be\n displayed here. An app developer registers {engine} with{\" \"}\n <code className=\"font-mono\">\n registerMediaViewer("{kind}", …)\n </code>\n .\n </div>\n <div className=\"min-h-0 flex-1\">\n <GenericViewer\n {...props}\n className={undefined}\n generic={{\n ...generic,\n message:\n generic?.message ??\n \"You can still download this file and open it in another application.\",\n }}\n />\n </div>\n </div>\n );\n}\n","/**\n * src/viewers/preview-kind.ts — filename/MIME → viewer kind.\n *\n * The DEFAULT resolution, derived from the package's own file-kind registry\n * (`getFileKindDetails`) so a fresh app gets correct dispatch with zero setup.\n * A host with a richer registry of its own — matrx-frontend's `FILE_TYPES`\n * carries preview/thumbnail/size-cap columns this package deliberately does\n * not absorb (C8) — passes `previewKind` explicitly and this is never called.\n */\n\nimport { getFileKindDetails } from \"../core/file-kind\";\nimport type { MediaViewerKind } from \"./types\";\n\nconst EXTENSION_KIND: Record<string, MediaViewerKind> = {\n svg: \"svg\",\n pdf: \"pdf\",\n md: \"markdown\",\n markdown: \"markdown\",\n mdx: \"markdown\",\n html: \"html\",\n htm: \"html\",\n csv: \"data\",\n tsv: \"data\",\n xlsx: \"spreadsheet\",\n xls: \"spreadsheet\",\n doc: \"office\",\n docx: \"office\",\n ppt: \"office\",\n pptx: \"office\",\n txt: \"text\",\n log: \"text\",\n text: \"text\",\n};\n\nfunction extensionOf(fileName: string): string {\n const base = fileName.split(/[\\\\/]/).pop() ?? fileName;\n const dot = base.lastIndexOf(\".\");\n if (dot <= 0) return \"\";\n return base.slice(dot + 1).toLowerCase();\n}\n\nexport function getPreviewKind(\n fileName: string,\n mimeType?: string | null,\n): MediaViewerKind {\n const explicit = EXTENSION_KIND[extensionOf(fileName)];\n if (explicit) return explicit;\n\n const details = getFileKindDetails(fileName, mimeType ?? undefined);\n switch (details.category) {\n case \"IMAGE\":\n return details.icon === \"pen-tool\" ? \"svg\" : \"image\";\n case \"VIDEO\":\n return \"video\";\n case \"AUDIO\":\n return \"audio\";\n case \"CODE\":\n return \"code\";\n case \"DATA\":\n return \"code\";\n case \"NOTEBOOK\":\n return \"code\";\n case \"SUBTITLES\":\n return \"text\";\n case \"DOCUMENT\":\n // The DOCUMENT bucket holds PDFs, markdown and plain text; the explicit\n // extension table above already caught the first two, so anything left\n // is text-shaped.\n return \"text\";\n default:\n return \"generic\";\n }\n}\n"],"mappings":"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","names":["createElement","createElement","useMemo","useState","jsx","jsxs","useEffect","useState","useState","useCallback","useCallback","useState","useEffect","useEffect","useState","useEffect","jsx","jsxs","useState","useMemo","createElement","jsx","FileIcon","formatFileSize","jsx","jsxs","FileIcon","useEffect","useState","useState","jsx","jsxs","useState","jsx","jsxs","useState","useEffect","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","jsx","jsxs","extensionOf","jsx","createElement"]}
|
|
1
|
+
{"version":3,"sources":["../src/viewers/media-file-viewer.tsx","../src/viewers/registry.ts","../src/viewers/code-viewer.tsx","../src/react/cn.ts","../src/viewers/chrome.tsx","../src/react/icons.tsx","../src/viewers/use-viewer-bytes.ts","../src/core/use-media-blob.ts","../src/core/context.ts","../src/core/diagnostics.ts","../src/core/ref-key.ts","../src/core/use-media-resolution.ts","../src/core/file-kind.ts","../src/react/file-icon.tsx","../src/viewers/generic-viewer.tsx","../src/viewers/html-viewer.tsx","../src/viewers/markup-chrome.tsx","../src/viewers/svg-viewer.tsx","../src/viewers/transparency-grid.ts","../src/viewers/text-viewer.tsx","../src/viewers/unavailable-viewer.tsx","../src/viewers/preview-kind.ts"],"sourcesContent":["/**\n * src/viewers/media-file-viewer.tsx — THE dispatcher.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/PreviewerSwitch.tsx`, which was\n * already the app's single kind→viewer switch across three surfaces (the\n * preview pane, the inline markdown file block, and the code editor's\n * binary-file fallback). The dispatch table, the kind vocabulary and the\n * degradation arms now belong to the package; the app keeps only the\n * registration of its own heavy engines.\n *\n * RESOLUTION ORDER (deliberate):\n * 1. a host registration for the kind — a real engine, or a feature's own\n * domain viewer overriding a built-in;\n * 2. the package's built-in body — text / code / svg / html / generic;\n * 3. the ANNOUNCING default — never a dead pane.\n *\n * FRAGMENTATION LAW: this module contains ZERO dynamic imports. Every body it\n * can render is statically part of the `./viewers` graph, which is already\n * behind whatever edge the consuming surface sits on. Heavy engines are lazy\n * on the HOST side of the registry seam — one boundary, at the edge, owned by\n * the app that knows its own chunking.\n */\n\n\"use client\";\n\nimport { createElement, type ComponentType } from \"react\";\nimport { getMediaViewer } from \"./registry\";\nimport { CodeViewer } from \"./code-viewer\";\nimport { GenericViewer } from \"./generic-viewer\";\nimport { HtmlViewer } from \"./html-viewer\";\nimport { SvgViewer } from \"./svg-viewer\";\nimport { TextViewer } from \"./text-viewer\";\nimport { MediaViewerUnavailable } from \"./unavailable-viewer\";\nimport { getPreviewKind } from \"./preview-kind\";\nimport type {\n MediaViewerComponent,\n MediaViewerKind,\n MediaViewerProps,\n} from \"./types\";\n\n/** The kinds the package renders itself, with no host registration. */\nconst BUILT_IN: Partial<Record<MediaViewerKind, MediaViewerComponent>> = {\n text: TextViewer as MediaViewerComponent,\n code: CodeViewer as MediaViewerComponent,\n svg: SvgViewer as MediaViewerComponent,\n html: HtmlViewer as MediaViewerComponent,\n generic: GenericViewer as MediaViewerComponent,\n};\n\nexport interface MediaFileViewerProps extends MediaViewerProps {\n /**\n * The kind to render. Omit to let the package derive it from the file name\n * and MIME type (`getPreviewKind`).\n */\n previewKind?: MediaViewerKind | undefined;\n}\n\nexport function MediaFileViewer({\n previewKind,\n ...props\n}: MediaFileViewerProps) {\n const kind =\n previewKind ?? getPreviewKind(props.fileName, props.mimeType ?? null);\n\n // MOUNTED AS AN ELEMENT, NEVER CALLED AS A FUNCTION. `viewer(props)` would\n // run the viewer's hooks inside THIS component's hook list, so a registered\n // viewer that uses hooks (every real engine adapter does — it resolves a\n // URL, reads a theme, joins a playback session) would blow up the moment\n // the kind changed between renders. `createElement` gives each body its own\n // component instance and its own hook list.\n const viewer = (getMediaViewer(kind) ?? BUILT_IN[kind]) as\n | ComponentType<MediaViewerProps>\n | undefined;\n if (viewer) return createElement(viewer, props);\n\n return <MediaViewerUnavailable {...props} kind={kind} />;\n}\n","/**\n * src/viewers/registry.ts — the heavy-engine seam.\n *\n * The package ships working bodies for every viewer kind it can render with\n * DOM primitives alone (text, code chrome, svg, html, generic). The kinds\n * whose rendering IS a multi-megabyte browser-only engine — PDF.js, a\n * Markdown/KaTeX stack, SheetJS, a server-side Office extractor — ride this\n * seam instead (C8 + the diff-package Monaco precedent): a host registers the\n * engine once, and until it does, the dispatcher renders an ANNOUNCING\n * default that names the missing engine and still offers download/open. A\n * dead pane is never an outcome.\n *\n * MODULE-LEVEL MUTABLE STATE IS BANNED (the dual ESM/CJS bundle rule): with\n * `splitting: false` and two formats, each loader graph instantiates its own\n * copy of this module, so a plain module-scope Map would silently split the\n * registry — a host registering through the CJS graph would be invisible to a\n * component rendered from the ESM graph. The maps therefore live on\n * `globalThis` under `Symbol.for` slots, and the tarball canary proves a\n * registration made in one graph is visible from the other.\n */\n\nimport type {\n MediaCodeHighlighter,\n MediaViewerComponent,\n MediaViewerKind,\n} from \"./types\";\n\nconst VIEWER_SLOT = Symbol.for(\"ai-matrx.media.viewer-registry\");\nconst HIGHLIGHTER_SLOT = Symbol.for(\"ai-matrx.media.code-highlighter\");\n\ninterface RegistrySlots {\n [VIEWER_SLOT]?: Map<MediaViewerKind, MediaViewerComponent>;\n [HIGHLIGHTER_SLOT]?: MediaCodeHighlighter | null;\n}\n\nfunction slots(): RegistrySlots {\n return globalThis as unknown as RegistrySlots;\n}\n\nfunction viewerMap(): Map<MediaViewerKind, MediaViewerComponent> {\n const host = slots();\n const existing = host[VIEWER_SLOT];\n if (existing) return existing;\n const created = new Map<MediaViewerKind, MediaViewerComponent>();\n host[VIEWER_SLOT] = created;\n return created;\n}\n\n/**\n * Register the viewer body for a kind. Registering a kind the package already\n * renders REPLACES the built-in — that is the sanctioned host override (a\n * feature-specific domain viewer implementing the same contract).\n *\n * Returns an unregister function so a test or a hot-reloading host can undo it.\n */\nexport function registerMediaViewer(\n kind: MediaViewerKind,\n viewer: MediaViewerComponent,\n): () => void {\n const map = viewerMap();\n const previous = map.get(kind);\n map.set(kind, viewer);\n return () => {\n if (previous) map.set(kind, previous);\n else map.delete(kind);\n };\n}\n\n/** The registered viewer for a kind, or `null` when nothing is registered. */\nexport function getMediaViewer(\n kind: MediaViewerKind,\n): MediaViewerComponent | null {\n return viewerMap().get(kind) ?? null;\n}\n\n/** Every kind a host has registered — for diagnostics and tests. */\nexport function registeredMediaViewerKinds(): MediaViewerKind[] {\n return [...viewerMap().keys()];\n}\n\n/**\n * Register the syntax-highlighting engine for the built-in code viewer.\n * Without one the code viewer still renders — monospace, line-numbered,\n * copyable, truncation-honest — it simply is not colored.\n */\nexport function registerMediaCodeHighlighter(\n highlighter: MediaCodeHighlighter,\n): () => void {\n const host = slots();\n const previous = host[HIGHLIGHTER_SLOT] ?? null;\n host[HIGHLIGHTER_SLOT] = highlighter;\n return () => {\n host[HIGHLIGHTER_SLOT] = previous;\n };\n}\n\nexport function getMediaCodeHighlighter(): MediaCodeHighlighter | null {\n return slots()[HIGHLIGHTER_SLOT] ?? null;\n}\n","/**\n * src/viewers/code-viewer.tsx — source-code viewer.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/CodePreview.tsx`.\n *\n * THE ONE DELIBERATE DIVERGENCE (C8 + the diff-package Monaco precedent):\n * the original imported `react-syntax-highlighter` (Prism, ~150KB min) at the\n * top of the module. A syntax highlighter is a browser-only engine that a\n * headless consumer of this package must never be forced to carry, so the\n * ENGINE rides `registerMediaCodeHighlighter` and the package ships the\n * chrome plus a capable default: monospace, line-numbered, wrap-toggling,\n * copyable, truncation-honest — everything except color. The default is not\n * a stub and never announces a failure, because nothing failed; a host that\n * wants color registers an engine in one line.\n */\n\n\"use client\";\n\nimport { createElement, useMemo, useState, type ComponentType } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { ViewerCopyButton, ViewerError, ViewerSkeleton, truncationNote } from \"./chrome\";\nimport { getMediaCodeHighlighter } from \"./registry\";\nimport type { MediaCodeHighlighterProps, MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\n/**\n * Extension → Prism-style language id. Ported verbatim from the original;\n * unknown ids are handed through unchanged (every engine we target degrades\n * to no-highlight rather than throwing).\n */\nconst EXT_TO_LANGUAGE: Record<string, string> = {\n js: \"javascript\",\n jsx: \"jsx\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n ts: \"typescript\",\n tsx: \"tsx\",\n py: \"python\",\n rb: \"ruby\",\n go: \"go\",\n rs: \"rust\",\n java: \"java\",\n kt: \"kotlin\",\n swift: \"swift\",\n c: \"c\",\n h: \"c\",\n cpp: \"cpp\",\n cc: \"cpp\",\n cxx: \"cpp\",\n hpp: \"cpp\",\n cs: \"csharp\",\n php: \"php\",\n scala: \"scala\",\n html: \"markup\",\n htm: \"markup\",\n xml: \"markup\",\n svg: \"markup\",\n css: \"css\",\n scss: \"scss\",\n less: \"less\",\n json: \"json\",\n yaml: \"yaml\",\n yml: \"yaml\",\n toml: \"toml\",\n ini: \"ini\",\n sh: \"bash\",\n bash: \"bash\",\n zsh: \"bash\",\n fish: \"bash\",\n ps1: \"powershell\",\n sql: \"sql\",\n graphql: \"graphql\",\n gql: \"graphql\",\n proto: \"protobuf\",\n dockerfile: \"docker\",\n makefile: \"makefile\",\n lua: \"lua\",\n r: \"r\",\n};\n\nfunction extensionOf(fileName: string): string {\n const base = fileName.split(/[\\\\/]/).pop() ?? fileName;\n const dot = base.lastIndexOf(\".\");\n if (dot <= 0) return \"\";\n return base.slice(dot + 1).toLowerCase();\n}\n\n/** Filename → language id. Exported: hosts registering an engine reuse it. */\nexport function detectCodeLanguage(fileName: string): string {\n const ext = extensionOf(fileName);\n if (ext) return EXT_TO_LANGUAGE[ext] ?? \"text\";\n const lower = fileName.toLowerCase();\n if (lower === \"dockerfile\") return \"docker\";\n if (lower === \"makefile\") return \"makefile\";\n return \"text\";\n}\n\nexport function CodeViewer({\n source,\n fileName,\n className,\n maxBytes = 1024 * 1024,\n}: MediaViewerProps) {\n const { text, error, loading, truncated } = useViewerText(source, maxBytes);\n const [wrap, setWrap] = useState(false);\n const language = useMemo(() => detectCodeLanguage(fileName), [fileName]);\n const highlighter = getMediaCodeHighlighter();\n\n if (error) return <ViewerError message={error} className={className} />;\n if (loading || text === null) return <ViewerSkeleton className={className} />;\n\n const lines = text.split(\"\\n\");\n\n return (\n <div\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden bg-card\",\n className,\n )}\n >\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-border bg-muted/30 px-3 py-1.5\">\n <div className=\"flex min-w-0 items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-mono tracking-wide uppercase\">{language}</span>\n {truncated ? (\n <span className=\"text-warning\">· {truncationNote(maxBytes)}</span>\n ) : null}\n </div>\n <div className=\"flex items-center gap-1\">\n {highlighter ? null : (\n <button\n type=\"button\"\n onClick={() => setWrap((value) => !value)}\n aria-pressed={wrap}\n className={cn(\n \"rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground\",\n wrap && \"bg-accent text-accent-foreground\",\n )}\n >\n Wrap\n </button>\n )}\n <ViewerCopyButton text={text} />\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {highlighter ? (\n // Mounted as an element, never called — a real highlighter reads the\n // host's theme with a hook, and calling it would put that hook in\n // THIS component's list (see the note in media-file-viewer.tsx).\n createElement(\n highlighter as ComponentType<MediaCodeHighlighterProps>,\n { code: text, language },\n )\n ) : (\n <pre className=\"m-0 flex p-3 font-mono text-xs leading-5\">\n <code\n aria-hidden\n className=\"mr-3 shrink-0 border-r border-border/60 pr-3 text-right text-muted-foreground/60 select-none\"\n >\n {lines.map((_, index) => `${index + 1}\\n`).join(\"\")}\n </code>\n <code\n className={cn(\n \"min-w-0 flex-1 text-foreground\",\n wrap ? \"break-words whitespace-pre-wrap\" : \"whitespace-pre\",\n )}\n >\n {text}\n </code>\n </pre>\n )}\n </div>\n </div>\n );\n}\n","/**\n * src/react/cn.ts — conditional class join with last-wins Tailwind conflict\n * merging. The originals used the app's `cn` (clsx + tailwind-merge); public\n * `className` overrides depend on last-wins class-conflict merging, so a\n * naive join would be a behavior divergence (the kit `./confirm` precedent —\n * this is why `tailwind-merge` is a sanctioned runtime dep of `/react`).\n */\n\nimport { twMerge } from \"tailwind-merge\";\n\nexport type ClassValue = string | false | null | undefined | 0;\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(inputs.filter(Boolean).join(\" \"));\n}\n","/**\n * src/viewers/chrome.tsx — the shared viewer chrome.\n *\n * The five absorbed matrx-frontend previewers each hand-rolled the same\n * error card, the same skeleton, and the same copy button. One copy here;\n * one place to make them good.\n */\n\n\"use client\";\n\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport { useCallback, useState } from \"react\";\nimport { ErrorBox } from \"@ai-matrx/design-system\";\nimport { cn } from \"../react/cn\";\nimport { AlertCircleIcon, CheckIcon, CopyIcon } from \"../react/icons\";\n\n/** The uniform loading bar every viewer shows while bytes are in flight. */\nexport function ViewerSkeleton({\n className,\n tone = \"muted\",\n}: {\n className?: string | undefined;\n tone?: \"muted\" | \"plain\" | undefined;\n}) {\n return (\n <div\n className={cn(\n \"flex h-full w-full items-center justify-center\",\n tone === \"muted\" && \"bg-muted/20\",\n className,\n )}\n >\n <div className=\"h-6 w-40 animate-pulse rounded bg-muted\" />\n </div>\n );\n}\n\n/**\n * The honest failure card. It shows the REAL underlying message (HTTP\n * 401/403/404/network) rather than a generic \"Preview failed\" — the original\n * previewers' deliberate choice, kept: a user who can see the status can act\n * on it, and a support thread starts with a fact instead of a shrug.\n */\nexport function ViewerError({\n title = \"Couldn't load this file\",\n message,\n hint,\n className,\n}: {\n title?: string | undefined;\n message?: string | null | undefined;\n hint?: string | undefined;\n className?: string | undefined;\n}) {\n return (\n <ErrorBox\n as=\"div\"\n className={cn(\n \"flex h-full w-full flex-col items-center justify-center gap-3 p-6 text-center\",\n className,\n )}\n title={title}\n message={message ?? title}\n operation=\"Show this file\"\n origin=\"media/ViewerError\"\n >\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10\">\n <AlertCircleIcon className=\"h-6 w-6 text-destructive\" />\n </div>\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold\">{title}</h3>\n {message ? (\n <p className=\"max-w-md text-xs break-words text-muted-foreground\">\n {message}\n </p>\n ) : null}\n {hint ? (\n <p className=\"max-w-md text-[11px] text-muted-foreground/80\">{hint}</p>\n ) : null}\n </div>\n </ErrorBox>\n );\n}\n\n/**\n * Copy-to-clipboard button with the settled-state flip. Swallows the\n * clipboard rejection that non-secure contexts always throw — a failed copy\n * is not an error worth a card, and the un-flipped button IS the signal.\n */\nexport function ViewerCopyButton({\n text,\n className,\n}: {\n text: string | null;\n className?: string | undefined;\n}) {\n const [copied, setCopied] = useState(false);\n const onCopy = useCallback(() => {\n if (text == null) return;\n void copyText(text).then((landed) => {\n // A refused copy leaves the button un-flipped — the honest signal.\n if (!landed) return;\n setCopied(true);\n setTimeout(() => setCopied(false), 1600);\n });\n }, [text]);\n\n return (\n <button\n type=\"button\"\n onClick={onCopy}\n aria-label=\"Copy text to clipboard\"\n title=\"Copy text to clipboard\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground\",\n copied && \"text-emerald-600 dark:text-emerald-400\",\n className,\n )}\n >\n {copied ? (\n <CheckIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <CopyIcon className=\"h-3.5 w-3.5\" />\n )}\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n );\n}\n\n/** The strip above a text-shaped viewer: status on the left, copy on the right. */\nexport function ViewerToolbar({\n children,\n className,\n}: {\n children?: React.ReactNode;\n className?: string | undefined;\n}) {\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center justify-between gap-2 border-b border-border/60 bg-muted/20 px-3 py-1 text-xs\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\n/**\n * \"truncated to the first 1.0 MB\" — one phrasing across every text-shaped\n * viewer.\n *\n * THE SIZE IS `formatFileSize`'s, NOT OURS (2026-09-12). This body used to do\n * its own `maxBytes / 1024 / 1024` and print `${mb.toFixed(0)}MB` above a\n * megabyte and `${(maxBytes / 1024).toFixed(0)}KB` below it — a byte-size\n * formatter living in a PACKAGE, which is the worst place for one: every\n * consumer of `@ai-matrx/media` inherited its rounding. And it rounded badly in\n * both directions. A 1.5 MiB ceiling printed \"2MB\" (`toFixed(0)` rounds half\n * up, so the note over-stated the limit by half a megabyte), and anything under\n * ~512 bytes printed \"0KB\" — the confident zero `formatFileSize` exists to\n * refuse. `@ai-matrx/media` already depends on `@ai-matrx/kit` and already\n * imports this exact function two files away in `generic-viewer.tsx`.\n */\nexport function truncationNote(maxBytes: number): string {\n return `truncated to the first ${formatFileSize(maxBytes)}`;\n}\n","/**\n * src/react/icons.tsx — the package's OWN inlined SVG icons.\n *\n * Per campaign ruling C19 (2026-08-29): no icon-library dependency, ever.\n * Every glyph below is copied from lucide-react v1.22.0 (ISC license) exactly,\n * following the @ai-matrx/tap-target precedent. Add a new icon by copying the\n * lucide __iconNode data — never by adding a lucide peer.\n *\n * Internal module: icons are exported for the package's own components and for\n * hosts that want visual parity in slots, but they are not the product.\n */\n\nimport type { SVGProps } from \"react\";\n\nexport type MediaIconProps = SVGProps<SVGSVGElement>;\n\nfunction svgProps(props: MediaIconProps): MediaIconProps {\n return {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n width: 24,\n height: 24,\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n ...props,\n };\n}\n\n// lucide: archive\nexport function ArchiveIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"20\" height=\"5\" x=\"2\" y=\"3\" rx=\"1\" />\n <path d=\"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8\" />\n <path d=\"M10 12h4\" />\n </svg>\n );\n}\n\n// lucide: braces\nexport function BracesIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" />\n <path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />\n </svg>\n );\n}\n\n// lucide: check\nexport function CheckIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\n// lucide: code\nexport function CodeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m16 18 6-6-6-6\" />\n <path d=\"m8 6-6 6 6 6\" />\n </svg>\n );\n}\n\n// lucide: copy\nexport function CopyIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </svg>\n );\n}\n\n// lucide: database\nexport function DatabaseIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M3 5V19A9 3 0 0 0 21 19V5\" />\n <path d=\"M3 12A9 3 0 0 0 21 12\" />\n </svg>\n );\n}\n\n// lucide: download\nexport function DownloadIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M12 15V3\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n <path d=\"m7 10 5 5 5-5\" />\n </svg>\n );\n}\n\n// lucide: externalLink\nexport function ExternalLinkIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n </svg>\n );\n}\n\n// lucide: file\nexport function FileIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n </svg>\n );\n}\n\n// lucide: fileAudio\nexport function FileAudioIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M4 6.835V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-.343\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M2 19a2 2 0 0 1 4 0v1a2 2 0 0 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 0 1-4 0v-1a2 2 0 0 1 4 0\" />\n </svg>\n );\n}\n\n// lucide: fileCode\nexport function FileCodeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12.5 8 15l2 2.5\" />\n <path d=\"m14 12.5 2 2.5-2 2.5\" />\n </svg>\n );\n}\n\n// lucide: fileJson\nexport function FileJsonIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1\" />\n <path d=\"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1\" />\n </svg>\n );\n}\n\n// lucide: fileSpreadsheet\nexport function FileSpreadsheetIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M8 13h2\" />\n <path d=\"M14 13h2\" />\n <path d=\"M8 17h2\" />\n <path d=\"M14 17h2\" />\n </svg>\n );\n}\n\n// lucide: fileText\nexport function FileTextIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n}\n\n// lucide: fileType\nexport function FileTypeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M11 18h2\" />\n <path d=\"M12 12v6\" />\n <path d=\"M9 13v-.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5v.5\" />\n </svg>\n );\n}\n\n// lucide: fileVideo\nexport function FileVideoIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" />\n <path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />\n <path d=\"M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z\" />\n </svg>\n );\n}\n\n// lucide: folder\nexport function FolderIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n}\n\n// lucide: folderOpen\nexport function FolderOpenIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\" />\n </svg>\n );\n}\n\n// lucide: image\nexport function ImageIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </svg>\n );\n}\n\n// lucide: imageOff\nexport function ImageOffIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M10.41 10.41a2 2 0 1 1-2.83-2.83\" />\n <line x1=\"13.5\" x2=\"6\" y1=\"13.5\" y2=\"21\" />\n <line x1=\"18\" x2=\"21\" y1=\"12\" y2=\"15\" />\n <path d=\"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59\" />\n <path d=\"M21 15V5a2 2 0 0 0-2-2H9\" />\n </svg>\n );\n}\n\n// lucide: music\nexport function MusicIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M9 18V5l12-2v13\" />\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\n </svg>\n );\n}\n\n// lucide: packageBox\nexport function PackageBoxIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\" />\n <path d=\"M12 22V12\" />\n <polyline points=\"3.29 7 12 12 20.71 7\" />\n <path d=\"m7.5 4.27 9 5.15\" />\n </svg>\n );\n}\n\n// lucide: penTool\nexport function PenToolIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z\" />\n <path d=\"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18\" />\n <path d=\"m2.3 2.3 7.286 7.286\" />\n <circle cx=\"11\" cy=\"11\" r=\"2\" />\n </svg>\n );\n}\n\n// lucide: share2\nexport function Share2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"18\" cy=\"5\" r=\"3\" />\n <circle cx=\"6\" cy=\"12\" r=\"3\" />\n <circle cx=\"18\" cy=\"19\" r=\"3\" />\n <line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" />\n <line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />\n </svg>\n );\n}\n\n// lucide: subtitles\nexport function SubtitlesIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 15h4M15 15h2M7 11h2M13 11h4\" />\n </svg>\n );\n}\n\n// lucide: upload\nexport function UploadIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M12 3v12\" />\n <path d=\"m17 8-5-5-5 5\" />\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\n </svg>\n );\n}\n\n// lucide: video\nexport function VideoIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\n// lucide: videoOff\nexport function VideoOffIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196\" />\n <path d=\"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2\" />\n <path d=\"m2 2 20 20\" />\n </svg>\n );\n}\n\n// lucide: volumeX\nexport function VolumeXIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" />\n <line x1=\"22\" x2=\"16\" y1=\"9\" y2=\"15\" />\n <line x1=\"16\" x2=\"22\" y1=\"9\" y2=\"15\" />\n </svg>\n );\n}\n\n// lucide: x\nexport function XIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\n// lucide: alertCircle\nexport function AlertCircleIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\n </svg>\n );\n}\n\n// lucide: checkCircle2\nexport function CheckCircle2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M21.801 10A10 10 0 1 1 17 3.335\" />\n <path d=\"m9 11 3 3L22 4\" />\n </svg>\n );\n}\n\n// lucide: globe\nexport function GlobeIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n// lucide: link-2\nexport function Link2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M9 17H7A5 5 0 0 1 7 7h2\" />\n <path d=\"M15 7h2a5 5 0 1 1 0 10h-2\" />\n <line x1=\"8\" x2=\"16\" y1=\"12\" y2=\"12\" />\n </svg>\n );\n}\n\n// lucide: settings-2\nexport function Settings2Icon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M20 7h-9\" />\n <path d=\"M14 17H5\" />\n <circle cx=\"17\" cy=\"17\" r=\"3\" />\n <circle cx=\"7\" cy=\"7\" r=\"3\" />\n </svg>\n );\n}\n\n// lucide: loader-circle (a.k.a. Loader2)\nexport function SpinnerIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// lucide: plus\nexport function PlusIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M5 12h14\" />\n <path d=\"M12 5v14\" />\n </svg>\n );\n}\n\n// lucide: search\nexport function SearchIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n );\n}\n\n// lucide: pause (lucide-react v1.48.0)\nexport function PauseIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <rect x=\"14\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n <rect x=\"5\" y=\"3\" width=\"5\" height=\"18\" rx=\"1\" />\n </svg>\n );\n}\n\n// lucide: play (lucide-react v1.48.0)\nexport function PlayIcon(props: MediaIconProps) {\n return (\n <svg {...svgProps(props)}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </svg>\n );\n}\n","/**\n * src/viewers/use-viewer-bytes.ts — the ONE byte/text/URL machinery every\n * viewer body shares.\n *\n * Four separate matrx-frontend previewers (Text, Code, the SVG source view,\n * the HTML source view) each carried their own copy of \"read the blob, cap it\n * at N bytes, mark it truncated, surface the REAL backend error verbatim,\n * cancel on unmount\". Four copies is four places to drift; C22 says that\n * machinery lives in the package exactly once.\n */\n\nimport { useEffect, useState } from \"react\";\nimport { useMediaBlob } from \"../core/use-media-blob\";\nimport { useMediaResolution } from \"../core/use-media-resolution\";\nimport type { MediaViewerSource } from \"./types\";\n\nexport interface ViewerBytesState {\n blob: Blob | null;\n loading: boolean;\n /** The real underlying message (HTTP 401/403/404/network) — never generic. */\n error: string | null;\n}\n\n/**\n * Bytes for a viewer source. A `blob` source is already resolved; a `ref`\n * source goes through `MediaClient.getBlob` (which is also what emits the\n * terminal-failure diagnostics — see `useMediaBlob`).\n *\n * `useMediaBlob` is called UNCONDITIONALLY (with `null` for blob sources) so\n * the hook order never changes with the source shape.\n */\nexport function useViewerBytes(source: MediaViewerSource): ViewerBytesState {\n const fromClient = useMediaBlob(source.kind === \"ref\" ? source.ref : null);\n if (source.kind === \"blob\") {\n return { blob: source.blob, loading: false, error: null };\n }\n return {\n blob: fromClient.blob,\n loading: fromClient.loading,\n error: fromClient.error,\n };\n}\n\n/**\n * Blob → string, across every runtime we ship into.\n *\n * `Blob.prototype.text()` is the modern one-liner and is what the\n * matrx-frontend originals used — but it does not exist in Safari < 14, in\n * older WebViews (the Tauri shell's floor), or in jsdom, and the failure mode\n * is a raw \"blob.text is not a function\" TypeError rendered to the user as if\n * the FILE were broken. Per C22 this quirk branch belongs in the package, once.\n */\nasync function readBlobText(blob: Blob): Promise<string> {\n const maybeText = (blob as { text?: () => Promise<string> }).text;\n if (typeof maybeText === \"function\") return await maybeText.call(blob);\n\n const maybeArrayBuffer = (blob as { arrayBuffer?: () => Promise<ArrayBuffer> })\n .arrayBuffer;\n if (typeof maybeArrayBuffer === \"function\") {\n return new TextDecoder().decode(await maybeArrayBuffer.call(blob));\n }\n\n return await new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result ?? \"\"));\n reader.onerror = () =>\n reject(reader.error ?? new Error(\"could not read the file's bytes\"));\n reader.readAsText(blob);\n });\n}\n\nexport interface ViewerTextState {\n text: string | null;\n loading: boolean;\n error: string | null;\n /** True when the file exceeded `maxBytes` and only the head was read. */\n truncated: boolean;\n}\n\n/**\n * Bytes → text, capped. The cap is not a nicety: a 500MB log file decoded in\n * full takes the tab down, which is how the original previewers were written\n * and why the cap must travel with the package rather than be re-derived.\n */\nexport function useViewerText(\n source: MediaViewerSource,\n maxBytes = 1024 * 1024,\n): ViewerTextState {\n const { blob, loading, error: bytesError } = useViewerBytes(source);\n const [text, setText] = useState<string | null>(null);\n const [readError, setReadError] = useState<string | null>(null);\n const [truncated, setTruncated] = useState(false);\n\n useEffect(() => {\n if (!blob) {\n setText(null);\n return undefined;\n }\n let cancelled = false;\n setReadError(null);\n setText(null);\n setTruncated(false);\n void (async () => {\n try {\n const oversized = blob.size > maxBytes;\n const value = await readBlobText(\n oversized ? blob.slice(0, maxBytes) : blob,\n );\n if (cancelled) return;\n setTruncated(oversized);\n setText(value);\n } catch (err) {\n if (cancelled) return;\n setReadError(err instanceof Error ? err.message : String(err));\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [blob, maxBytes]);\n\n const error = readError ?? bytesError;\n return {\n text,\n error,\n truncated,\n loading: (loading || text === null) && error === null,\n };\n}\n\nexport interface ViewerDisplayUrlState {\n /**\n * The URL a media element may bind. Durable by construction: it is either\n * a `MediaClient.resolve()` result or the host's own object URL.\n */\n url: string | null;\n /**\n * Whether the client's ONE retry policy can rescue a load failure. False\n * for object URLs and for resolutions the client marked unrecoverable\n * (foreign links) — a session refresh cannot resurrect someone else's URL.\n */\n recoverable: boolean;\n /** `resolve()` refused the ref — render the honest unavailable state. */\n unavailable: boolean;\n loading: boolean;\n}\n\n/**\n * The display URL for a viewer source. Law 2: even for a `ref` carrying a\n * caller-supplied URL, resolution goes through the client — the package never\n * trusts a string it was handed.\n */\nexport function useViewerDisplayUrl(\n source: MediaViewerSource,\n): ViewerDisplayUrlState {\n const resolved = useMediaResolution(\n source.kind === \"ref\" ? source.ref : null,\n );\n if (source.kind === \"blob\") {\n return {\n url: source.url,\n recoverable: false,\n unavailable: false,\n loading: false,\n };\n }\n return {\n url: resolved.resolution?.src ?? null,\n recoverable: resolved.resolution?.recoverable !== false,\n unavailable: resolved.status === \"unavailable\",\n loading: resolved.status === \"empty\",\n };\n}\n","/**\n * src/core/use-media-blob.ts — bytes for canvas/crossOrigin/private-pixel\n * consumers, as state.\n *\n * The behavior contract is ported from matrx-frontend `hooks/useFileBlob.ts`;\n * the byte machinery (auth, caching, in-flight dedup, IDB tiers, progress) is\n * the CLIENT's (C10 persistence-injected — the package owns no cache). The\n * hook owns only the React lifecycle: load on mount/ref change, release the\n * handle on unmount, expose a retry.\n */\n\nimport { useEffect, useState } from \"react\";\nimport type { MediaRefLike } from \"../types\";\nimport { useMediaClient } from \"./context\";\nimport { failureMediaIdentity, useMediaFailureCapture } from \"./diagnostics\";\nimport { stableRefKey } from \"./ref-key\";\n\n/** Structural HTTP status probe for client errors (never a validation). */\nfunction statusOf(err: unknown): number | undefined {\n if (err && typeof err === \"object\") {\n const candidate =\n (err as { status?: unknown }).status ??\n (err as { statusCode?: unknown }).statusCode;\n if (typeof candidate === \"number\") return candidate;\n }\n return undefined;\n}\n\nexport interface MediaBlobState {\n /** `blob:` object URL safe to feed into any browser API. `null` until ready. */\n url: string | null;\n blob: Blob | null;\n loading: boolean;\n error: string | null;\n /** Force a fresh byte read (the client decides whether to drop its cache). */\n retry: () => void;\n}\n\nexport function useMediaBlob(\n ref: MediaRefLike | null | undefined,\n): MediaBlobState {\n const client = useMediaClient();\n const capture = useMediaFailureCapture();\n const refKey = stableRefKey(ref);\n const [state, setState] = useState<{\n url: string | null;\n blob: Blob | null;\n loading: boolean;\n error: string | null;\n }>({ url: null, blob: null, loading: !!ref, error: null });\n const [retryToken, setRetryToken] = useState(0);\n\n useEffect(() => {\n if (!ref) {\n setState({ url: null, blob: null, loading: false, error: null });\n return undefined;\n }\n let cancelled = false;\n let release: (() => void) | null = null;\n setState({ url: null, blob: null, loading: true, error: null });\n client.getBlob(ref).then(\n (handle) => {\n if (cancelled) {\n handle.release();\n return;\n }\n release = handle.release;\n setState({ url: handle.url, blob: handle.blob, loading: false, error: null });\n },\n (err: unknown) => {\n if (cancelled) return;\n const message =\n err instanceof Error ? err.message : String(err ?? \"Failed to load file\");\n setState({ url: null, blob: null, loading: false, error: message });\n // Terminal-failure capture (phase \"blob\"): the private-pixels bytes\n // never arrived. Latched per media identity by the machinery.\n const status = statusOf(err);\n capture({\n phase: \"blob\",\n mediaRef: failureMediaIdentity(ref),\n terminal: true,\n message: `getBlob() failed: ${message}`,\n ...(status !== undefined ? { status } : {}),\n });\n },\n );\n return () => {\n cancelled = true;\n release?.();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, refKey, retryToken]);\n\n return {\n ...state,\n retry: () => setRetryToken((t) => t + 1),\n };\n}\n","/**\n * src/core/context.ts — the MediaClient / host-ports React contexts.\n *\n * The context OBJECTS live on `globalThis` under `Symbol.for` slots — NOT at\n * module level. With `splitting: false` this module is duplicated into the\n * `/core` and `/react` bundles, and CJS/ESM each instantiate their own module\n * graph; a module-level `createContext` would silently produce two different\n * contexts (a Provider from one graph invisible to a consumer from the\n * other) — the kit tap-target/link-registry lesson. Never \"clean this up\".\n */\n\nimport {\n createContext,\n createElement,\n useContext,\n type Context,\n type ReactNode,\n} from \"react\";\nimport type { MediaClient, MediaHostPorts } from \"../types\";\n\nconst CLIENT_SLOT = Symbol.for(\"ai-matrx.media.client-context\");\nconst PORTS_SLOT = Symbol.for(\"ai-matrx.media.host-ports-context\");\n\ntype SlotHost = typeof globalThis & {\n [CLIENT_SLOT]?: Context<MediaClient | null>;\n [PORTS_SLOT]?: Context<MediaHostPorts>;\n};\n\nfunction clientContext(): Context<MediaClient | null> {\n const host = globalThis as SlotHost;\n host[CLIENT_SLOT] ??= createContext<MediaClient | null>(null);\n return host[CLIENT_SLOT];\n}\n\nconst INERT_PORTS: MediaHostPorts = {};\n\nfunction portsContext(): Context<MediaHostPorts> {\n const host = globalThis as SlotHost;\n host[PORTS_SLOT] ??= createContext<MediaHostPorts>(INERT_PORTS);\n return host[PORTS_SLOT];\n}\n\nexport interface MediaProviderProps {\n client: MediaClient;\n /**\n * Optional host ports (playback session, actions, ImageComponent). Must be\n * referentially stable — the playback port members are hooks.\n */\n ports?: MediaHostPorts | undefined;\n children?: ReactNode;\n}\n\n/** Wire the injected MediaClient (and optional host ports) into the tree. */\nexport function MediaProvider({ client, ports, children }: MediaProviderProps) {\n const ClientCtx = clientContext();\n const PortsCtx = portsContext();\n return createElement(\n ClientCtx.Provider,\n { value: client },\n createElement(PortsCtx.Provider, { value: ports ?? INERT_PORTS }, children),\n );\n}\n\n/** The injected MediaClient. Throws when no MediaProvider is mounted. */\nexport function useMediaClient(): MediaClient {\n const client = useContext(clientContext());\n if (!client) {\n throw new Error(\n \"@ai-matrx/media: no MediaClient. Mount <MediaProvider client={...}> \" +\n \"above every media surface (canonically wired to @ai-matrx/data/files).\",\n );\n }\n return client;\n}\n\n/** The injected host ports; inert defaults when none were provided. */\nexport function useMediaHostPorts(): MediaHostPorts {\n return useContext(portsContext());\n}\n","/**\n * src/core/diagnostics.ts — the terminal-failure capture machinery.\n *\n * Born from the 2026-08-30 prod outage: server-side cookie-secret drift\n * killed every private image, the package rendered its honest \"unavailable\"\n * panel — and nothing reached the host's Error Inspector or error DB,\n * because the package had no diagnostics port and the host cannot capture\n * what it never learns about. Per ruling C22 the capture logic lives HERE,\n * so every consuming repo inherits it.\n *\n * The contract:\n *\n * - every terminal failure path emits exactly ONE {@link MediaFailureInfo}\n * per media identity (latched — re-renders, remounts and the unavailable\n * panel backstop never spam);\n * - a bound `MediaHostPorts.diagnostics.capture` receives the payload;\n * WITHOUT one (or if it throws) the package `console.error`s the same\n * structured payload — the loud default. A media failure is NEVER silent;\n * - the payload never carries a signed URL: identity is the file id or a\n * query-stripped URL key ({@link failureMediaIdentity}).\n *\n * The latch lives on `globalThis` under a `Symbol.for` slot (same reason as\n * context.ts: with `splitting: false` + dual formats, module-level state\n * silently duplicates across bundle/loader graphs).\n */\n\nimport { useCallback, useRef } from \"react\";\nimport type { MediaFailureInfo, MediaRefLike } from \"../types\";\nimport { useMediaHostPorts } from \"./context\";\n\nconst LATCH_SLOT = Symbol.for(\"ai-matrx.media.failure-latch\");\n\ntype SlotHost = typeof globalThis & {\n [LATCH_SLOT]?: Set<string>;\n};\n\nfunction latch(): Set<string> {\n const host = globalThis as SlotHost;\n host[LATCH_SLOT] ??= new Set<string>();\n return host[LATCH_SLOT];\n}\n\n/**\n * Clear the once-per-failure latch. For tests, and for hosts at auth\n * boundaries (a sign-in can genuinely fix a previously-terminal failure, and\n * a recurrence after it deserves a fresh capture).\n */\nexport function resetMediaFailureLatch(): void {\n latch().clear();\n}\n\n/**\n * Durable diagnostics identity for a media reference. NEVER a signed URL:\n * file ids win, and any URL is stripped to origin + path (signatures ride\n * query strings).\n */\nexport function failureMediaIdentity(\n ref: MediaRefLike | null | undefined,\n src?: string | null,\n): string {\n if (ref && typeof ref === \"object\" && ref.file_id) return `file:${ref.file_id}`;\n let raw: string | null | undefined;\n if (typeof ref === \"string\") raw = ref;\n else if (ref && typeof ref === \"object\" && ref.url) raw = ref.url;\n else raw = src;\n if (!raw) return \"<unknown-media>\";\n if (raw.startsWith(\"blob:\")) return \"blob:object-url\";\n try {\n const u = new URL(raw);\n return `url:${u.origin}${u.pathname}`;\n } catch {\n // A bare fileId string, or an unparseable fragment — still strip any query.\n const clean = raw.split(/[?#]/, 1)[0] ?? raw;\n return `ref:${clean}`;\n }\n}\n\n/**\n * Emit one media-failure capture through the host sink, or the loud\n * console.error default when no sink is bound (or the sink throws).\n * Latched per (terminal|warning, mediaRef) — one capture per failure,\n * however many renders, hooks, or backstops observe it.\n */\nexport function emitMediaFailure(\n capture: ((info: MediaFailureInfo) => void) | undefined,\n info: MediaFailureInfo,\n): void {\n const key = `${info.terminal ? \"terminal\" : \"warning\"}|${info.mediaRef}`;\n const seen = latch();\n if (seen.has(key)) return;\n seen.add(key);\n if (capture) {\n try {\n capture(info);\n return;\n } catch {\n // A broken sink must not re-silence the failure — fall through.\n }\n }\n console.error(\n \"[@ai-matrx/media] media failure (no diagnostics sink captured it — \" +\n \"bind MediaHostPorts.diagnostics.capture to your error system)\",\n info,\n );\n}\n\n/**\n * Hook form: a stable capture function wired to the host ports. Every core\n * hook and the unavailable-panel backstop route through this — the phase\n * vocabulary and the latch stay in ONE place.\n */\nexport function useMediaFailureCapture(): (\n info: Omit<MediaFailureInfo, \"source\">,\n) => void {\n const ports = useMediaHostPorts();\n const capture = ports.diagnostics?.capture;\n // The latest sink without invalidating effect deps in the calling hooks —\n // the port object is referentially stable by contract, but a fresh binding\n // (e.g. tests swapping providers) must not capture stale.\n const captureRef = useRef(capture);\n captureRef.current = capture;\n return useCallback((info: Omit<MediaFailureInfo, \"source\">) => {\n emitMediaFailure(captureRef.current, { source: \"media\", ...info });\n }, []);\n}\n","/**\n * src/core/ref-key.ts — stable identity key for a MediaRefLike.\n *\n * Callers routinely pass fresh object literals every render; hooks key their\n * effects/memos on this string instead of object identity. Ported from the\n * original `stableSourceKey` (matrx-frontend `handler/hooks/useFileAs.ts`).\n */\n\nimport type { MediaRefLike } from \"../types\";\n\nexport function stableRefKey(ref: MediaRefLike | null | undefined): string {\n if (!ref) return \"<none>\";\n if (typeof ref === \"string\") return `s:${ref}`;\n if (ref.file_id) return `id:${ref.file_id}:${ref.mime_type ?? \"\"}`;\n if (ref.url) return `url:${ref.url}:${ref.mime_type ?? \"\"}`;\n return \"<empty-ref>\";\n}\n","/**\n * src/core/use-media-resolution.ts — ref → durable resolution, as state.\n *\n * Law 2: every consumer resolves media through the client, unconditionally —\n * even a caller-supplied URL string is classified, never trusted. Law 15 of\n * the handler (unavailable is a rendered state): a throwing `resolve()` is\n * classified via `classifyError` and returned as typed state — never\n * re-thrown. It IS however a terminal failure, so it also emits exactly one\n * `MediaFailureInfo` (phase \"resolve\") through the diagnostics machinery —\n * the 2026-08-30 outage rule: an unavailable render is honest to the USER but\n * must never be silent to the SYSTEM.\n */\n\nimport { useEffect, useMemo } from \"react\";\nimport type {\n MediaRefLike,\n MediaResolution,\n MediaUnavailableReason,\n} from \"../types\";\nimport { useMediaClient } from \"./context\";\nimport { failureMediaIdentity, useMediaFailureCapture } from \"./diagnostics\";\nimport { stableRefKey } from \"./ref-key\";\n\nexport interface MediaResolutionState {\n resolution: MediaResolution | null;\n /**\n * \"empty\" — no ref, or a ref with no usable identity (render fallback)\n * \"ready\" — resolution available\n * \"unavailable\" — resolve() refused (signed URL, access denied…); render\n * the typed unavailable state, never an incident\n */\n status: \"empty\" | \"ready\" | \"unavailable\";\n reason: MediaUnavailableReason | null;\n}\n\nexport function useMediaResolution(\n ref: MediaRefLike | null | undefined,\n): MediaResolutionState {\n const client = useMediaClient();\n const capture = useMediaFailureCapture();\n const refKey = stableRefKey(ref);\n const { state, failureMessage } = useMemo<{\n state: MediaResolutionState;\n failureMessage: string | null;\n }>(() => {\n if (!ref) {\n return {\n state: { resolution: null, status: \"empty\", reason: null },\n failureMessage: null,\n };\n }\n try {\n const resolution = client.resolve(ref);\n if (!resolution) {\n return {\n state: { resolution: null, status: \"empty\", reason: null },\n failureMessage: null,\n };\n }\n return {\n state: { resolution, status: \"ready\", reason: null },\n failureMessage: null,\n };\n } catch (err) {\n return {\n state: {\n resolution: null,\n status: \"unavailable\",\n reason: client.classifyError(err),\n },\n failureMessage:\n err instanceof Error ? err.message : String(err ?? \"resolve() failed\"),\n };\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, refKey]);\n\n // Terminal-failure capture (phase \"resolve\") — an effect, never a render\n // side effect; latched per media identity by the diagnostics machinery.\n useEffect(() => {\n if (state.status !== \"unavailable\") return;\n capture({\n phase: \"resolve\",\n mediaRef: failureMediaIdentity(ref ?? null),\n terminal: true,\n message: `resolve() refused (${state.reason ?? \"unknown\"}): ${\n failureMessage ?? \"no error message\"\n }`,\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refKey, state.status]);\n\n return state;\n}\n","/**\n * src/core/file-kind.ts — filename/MIME → category, icon name, color.\n *\n * Condensed port of the icon-relevant slice of matrx-frontend\n * `features/files/utils/file-types.ts` (the FILE_TYPES registry): every\n * extension→{category,icon,color,displayName} row is preserved; the\n * preview/thumbnail/size-cap columns stay in the app (C8 — they belong to\n * the previewer world, not the media kit). MIME-prefix fallback, the\n * dotfile-looks-like-text heuristic, folder details and the unknown default\n * are ported verbatim in behavior.\n *\n * Platform-free: icon NAMES only — `/react` maps names to its inlined SVGs;\n * a future `/react-native` binding maps the same names to its own glyphs.\n */\n\nexport type FileCategory =\n | \"CODE\"\n | \"DOCUMENT\"\n | \"AUDIO\"\n | \"IMAGE\"\n | \"VIDEO\"\n | \"ARCHIVE\"\n | \"DATA\"\n | \"NOTEBOOK\"\n | \"SUBTITLES\"\n | \"EMAIL\"\n | \"EBOOK\"\n | \"MODEL_3D\"\n | \"UNKNOWN\"\n | \"FOLDER\";\n\nexport type FileIconName =\n | \"image\"\n | \"pen-tool\"\n | \"video\"\n | \"music\"\n | \"file-type\"\n | \"file-text\"\n | \"code\"\n | \"braces\"\n | \"subtitles\"\n | \"file-code\"\n | \"file-json\"\n | \"file-spreadsheet\"\n | \"database\"\n | \"package\"\n | \"archive\"\n | \"folder\"\n | \"folder-open\"\n | \"file\"\n | \"file-audio\"\n | \"file-video\";\n\nexport interface FileKindDetails {\n category: FileCategory;\n displayName: string;\n /** Tailwind text color token, matching the original registry exactly. */\n colorClass: string;\n icon: FileIconName;\n}\n\ntype Row = [\n extensions: string[],\n category: FileCategory,\n colorClass: string,\n icon: FileIconName,\n displayName: string,\n];\n\n// Rows ported from the FILE_TYPES registry (icon-relevant columns), grouped\n// exactly as the original's icon/color assignments group them.\nconst ROWS: Row[] = [\n [[\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"avif\", \"heic\", \"heif\", \"bmp\", \"tif\", \"tiff\", \"ico\"], \"IMAGE\", \"text-emerald-500\", \"image\", \"Image\"],\n [[\"svg\"], \"IMAGE\", \"text-amber-500\", \"pen-tool\", \"SVG image\"],\n [[\"mp4\", \"mov\", \"webm\", \"mkv\", \"avi\", \"m4v\"], \"VIDEO\", \"text-purple-500\", \"video\", \"Video\"],\n [[\"mp3\", \"wav\", \"ogg\", \"m4a\", \"aac\", \"flac\", \"opus\"], \"AUDIO\", \"text-pink-500\", \"music\", \"Audio\"],\n [[\"pdf\"], \"DOCUMENT\", \"text-red-500\", \"file-type\", \"PDF Document\"],\n [[\"md\", \"markdown\", \"mdx\", \"rst\", \"adoc\", \"asciidoc\", \"org\"], \"DOCUMENT\", \"text-slate-400\", \"file-text\", \"Markdown\"],\n [[\"txt\", \"text\", \"asc\", \"me\", \"log\", \"out\", \"err\"], \"DOCUMENT\", \"text-muted-foreground\", \"file-text\", \"Text\"],\n [[\"dockerfile\", \"containerfile\", \"lua\"], \"CODE\", \"text-blue-500\", \"code\", \"Code\"],\n [[\"mk\", \"make\", \"swift\", \"ml\", \"mli\", \"fs\", \"fsi\", \"fsx\", \"svelte\"], \"CODE\", \"text-orange-500\", \"code\", \"Code\"],\n [[\"diff\", \"patch\", \"pem\", \"csr\", \"crt\", \"cer\", \"der\", \"key\", \"pub\", \"p7b\", \"p7c\", \"pfx\", \"p12\"], \"CODE\", \"text-amber-500\", \"file-text\", \"Text\"],\n [[\"ini\", \"cfg\", \"conf\", \"config\", \"properties\", \"prefs\"], \"CODE\", \"text-amber-400\", \"braces\", \"Config\"],\n [[\"tex\", \"latex\", \"ltx\", \"sty\", \"cls\", \"bib\"], \"CODE\", \"text-emerald-500\", \"file-text\", \"LaTeX\"],\n [[\"srt\", \"vtt\"], \"SUBTITLES\", \"text-cyan-500\", \"subtitles\", \"Subtitles\"],\n [[\"js\", \"mjs\", \"cjs\", \"jsx\"], \"CODE\", \"text-yellow-500\", \"file-code\", \"JavaScript\"],\n [[\"ts\", \"tsx\"], \"CODE\", \"text-blue-500\", \"file-code\", \"TypeScript\"],\n [[\"py\", \"clj\", \"cljs\", \"cljc\", \"edn\", \"vue\", \"styl\", \"stylus\"], \"CODE\", \"text-emerald-500\", \"code\", \"Code\"],\n [[\"rb\", \"rbw\", \"rake\", \"ru\", \"gemspec\", \"scala\", \"sbt\"], \"CODE\", \"text-red-500\", \"code\", \"Code\"],\n [[\"go\", \"dart\"], \"CODE\", \"text-cyan-500\", \"code\", \"Code\"],\n [[\"rs\"], \"CODE\", \"text-orange-600\", \"code\", \"Rust\"],\n [[\"java\"], \"CODE\", \"text-red-600\", \"code\", \"Java\"],\n [[\"c\", \"h\"], \"CODE\", \"text-blue-600\", \"code\", \"C\"],\n [[\"cpp\", \"cc\", \"cxx\", \"hpp\"], \"CODE\", \"text-blue-700\", \"code\", \"C++\"],\n [[\"cs\"], \"CODE\", \"text-purple-600\", \"code\", \"C#\"],\n [[\"html\", \"htm\", \"kt\", \"kts\"], \"CODE\", \"text-orange-400\", \"code\", \"Code\"],\n [[\"css\"], \"CODE\", \"text-sky-400\", \"code\", \"CSS\"],\n [[\"scss\"], \"CODE\", \"text-pink-400\", \"code\", \"SCSS\"],\n [[\"sh\", \"bash\", \"zsh\", \"fish\", \"ksh\", \"ash\", \"bat\", \"cmd\", \"twig\", \"jinja\", \"j2\", \"njk\"], \"CODE\", \"text-emerald-400\", \"code\", \"Script\"],\n [[\"sql\"], \"CODE\", \"text-amber-400\", \"code\", \"SQL\"],\n [[\"pl\", \"pm\"], \"CODE\", \"text-indigo-400\", \"code\", \"Perl\"],\n [[\"r\", \"rmd\", \"proto\", \"ps1\", \"psm1\", \"psd1\", \"less\"], \"CODE\", \"text-blue-400\", \"code\", \"Code\"],\n [[\"ex\", \"exs\"], \"CODE\", \"text-purple-400\", \"code\", \"Elixir\"],\n [[\"erl\", \"hrl\"], \"CODE\", \"text-rose-500\", \"code\", \"Erlang\"],\n [[\"hs\", \"lhs\"], \"CODE\", \"text-violet-500\", \"code\", \"Haskell\"],\n [[\"zig\"], \"CODE\", \"text-yellow-500\", \"code\", \"Zig\"],\n [[\"nim\", \"nims\"], \"CODE\", \"text-yellow-400\", \"code\", \"Nim\"],\n [[\"jl\"], \"CODE\", \"text-purple-500\", \"code\", \"Julia\"],\n [[\"astro\"], \"CODE\", \"text-fuchsia-500\", \"code\", \"Astro\"],\n [[\"graphql\", \"gql\", \"graphqls\"], \"CODE\", \"text-pink-500\", \"code\", \"GraphQL\"],\n [[\"sol\"], \"CODE\", \"text-slate-400\", \"code\", \"Solidity\"],\n [[\"php\", \"phtml\", \"phps\"], \"CODE\", \"text-indigo-500\", \"code\", \"PHP\"],\n [[\"hbs\", \"handlebars\", \"mustache\", \"ejs\", \"liquid\"], \"CODE\", \"text-amber-500\", \"code\", \"Template\"],\n [[\"json\", \"jsonc\", \"json5\", \"har\", \"geojson\", \"topojson\"], \"DATA\", \"text-amber-500\", \"file-json\", \"JSON\"],\n [[\"yaml\", \"yml\", \"toml\"], \"CODE\", \"text-amber-500\", \"braces\", \"Config\"],\n [[\"xml\"], \"DATA\", \"text-amber-500\", \"braces\", \"XML\"],\n [[\"csv\", \"tsv\"], \"DATA\", \"text-orange-500\", \"file-spreadsheet\", \"Spreadsheet data\"],\n [[\"sqlite\", \"sqlite3\", \"db\"], \"DATA\", \"text-blue-400\", \"database\", \"Database\"],\n [[\"ttl\", \"n3\", \"nt\", \"nq\", \"trig\"], \"DATA\", \"text-fuchsia-400\", \"braces\", \"RDF data\"],\n [[\"xlsx\", \"xls\"], \"DOCUMENT\", \"text-emerald-600\", \"file-spreadsheet\", \"Excel workbook\"],\n [[\"doc\", \"docx\"], \"DOCUMENT\", \"text-blue-500\", \"file-text\", \"Word document\"],\n [[\"ppt\", \"pptx\"], \"DOCUMENT\", \"text-orange-600\", \"file-type\", \"Presentation\"],\n [[\"ipynb\"], \"NOTEBOOK\", \"text-orange-400\", \"file-json\", \"Notebook\"],\n [[\"epub\"], \"EBOOK\", \"text-indigo-500\", \"file-text\", \"eBook\"],\n [[\"eml\"], \"EMAIL\", \"text-blue-400\", \"file-text\", \"Email\"],\n [[\"glb\", \"gltf\", \"stl\", \"obj\", \"fbx\"], \"MODEL_3D\", \"text-violet-400\", \"package\", \"3D model\"],\n [[\"zip\", \"rar\", \"7z\"], \"ARCHIVE\", \"text-amber-600\", \"archive\", \"Archive\"],\n [[\"tar\", \"gz\", \"tgz\"], \"ARCHIVE\", \"text-amber-600\", \"package\", \"Archive\"],\n];\n\nconst BY_EXTENSION = new Map<string, FileKindDetails>();\nfor (const [extensions, category, colorClass, icon, displayName] of ROWS) {\n for (const ext of extensions) {\n BY_EXTENSION.set(ext, { category, colorClass, icon, displayName });\n }\n}\n\nconst UNKNOWN_DETAILS: FileKindDetails = {\n category: \"UNKNOWN\",\n displayName: \"File\",\n colorClass: \"text-muted-foreground\",\n icon: \"file\",\n};\n\nconst ASSUMED_TEXT_DETAILS: FileKindDetails = {\n category: \"DOCUMENT\",\n displayName: \"Text\",\n colorClass: \"text-muted-foreground\",\n icon: \"file-text\",\n};\n\nconst FOLDER_DETAILS: FileKindDetails = {\n category: \"FOLDER\",\n displayName: \"Folder\",\n colorClass: \"text-sky-500\",\n icon: \"folder\",\n};\n\nconst IMAGE_DETAILS = BY_EXTENSION.get(\"png\") as FileKindDetails;\nconst VIDEO_DETAILS = BY_EXTENSION.get(\"mp4\") as FileKindDetails;\nconst AUDIO_DETAILS = BY_EXTENSION.get(\"mp3\") as FileKindDetails;\nconst PDF_DETAILS = BY_EXTENSION.get(\"pdf\") as FileKindDetails;\nconst SVG_DETAILS = BY_EXTENSION.get(\"svg\") as FileKindDetails;\n\nfunction basenameOf(path: string): string {\n const idx = Math.max(path.lastIndexOf(\"/\"), path.lastIndexOf(\"\\\\\"));\n return idx >= 0 ? path.slice(idx + 1) : path;\n}\n\nfunction extOf(name: string): string | null {\n const idx = name.lastIndexOf(\".\");\n if (idx <= 0 || idx === name.length - 1) return null;\n return name.slice(idx + 1).toLowerCase();\n}\n\n/**\n * Dotfile heuristic (ported): unrecognized dotfiles are almost always text —\n * bias toward the text profile instead of the binary \"File\" default.\n */\nfunction dotfileLooksLikeText(filename: string): boolean {\n const name = basenameOf(filename);\n if (!name.startsWith(\".\")) return false;\n for (let i = 1; i < name.length; i++) {\n const c = name.charCodeAt(i);\n if (\n (c >= 48 && c <= 57) ||\n (c >= 65 && c <= 90) ||\n (c >= 97 && c <= 122) ||\n c === 95 ||\n c === 45\n ) {\n return true;\n }\n }\n return false;\n}\n\n/** Strip MIME parameters (`;codecs=opus`, etc.). */\nfunction canonicalMimeBase(raw: string): string {\n return raw.split(\";\")[0]?.trim().toLowerCase() ?? raw;\n}\n\n/**\n * Resolve icon details from a filename and (optionally) the server MIME.\n * MIME-prefix override handles \"the browser knows `image/avif` but the\n * extension table doesn't\" — and disambiguates audio/webm vs video/webm.\n */\nexport function getFileKindDetails(\n fileName: string,\n mimeType?: string | null,\n): FileKindDetails {\n const name = basenameOf(fileName);\n const lower = name.toLowerCase();\n const ext = lower === \"dockerfile\" || lower === \"containerfile\" ? lower : extOf(name);\n const fromExt = ext ? BY_EXTENSION.get(ext) : undefined;\n\n const mime = mimeType ? canonicalMimeBase(mimeType) : null;\n if (mime) {\n if (mime === \"image/svg+xml\") return fromExt ?? SVG_DETAILS;\n if (mime.startsWith(\"image/\")) return fromExt?.category === \"IMAGE\" ? fromExt : IMAGE_DETAILS;\n if (mime.startsWith(\"video/\")) return fromExt?.category === \"VIDEO\" ? fromExt : VIDEO_DETAILS;\n if (mime.startsWith(\"audio/\")) return fromExt?.category === \"AUDIO\" ? fromExt : AUDIO_DETAILS;\n if (mime === \"application/pdf\") return PDF_DETAILS;\n }\n\n if (fromExt) return fromExt;\n if (dotfileLooksLikeText(fileName)) return ASSUMED_TEXT_DETAILS;\n return UNKNOWN_DETAILS;\n}\n\n/** Folder icon details (open picks the open-folder glyph). */\nexport function getFolderKindDetails(open = false): FileKindDetails {\n return open ? { ...FOLDER_DETAILS, icon: \"folder-open\" } : FOLDER_DETAILS;\n}\n","/**\n * src/react/file-icon.tsx — icon tile for any file or folder.\n *\n * Verbatim port of matrx-frontend `components/core/FileIcon/FileIcon.tsx`\n * with two seam inversions: the registry lookup is the package's own\n * `getFileKindDetails` (`/core`), and the glyphs are the package's own\n * inlined SVGs (C19 — no lucide peer).\n */\n\nimport type { CSSProperties } from \"react\";\nimport {\n getFileKindDetails,\n getFolderKindDetails,\n type FileIconName,\n} from \"../core/file-kind\";\nimport { cn } from \"./cn\";\nimport {\n ArchiveIcon,\n BracesIcon,\n CodeIcon,\n DatabaseIcon,\n FileAudioIcon,\n FileCodeIcon,\n FileIcon as FileGlyph,\n FileJsonIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n FileTypeIcon,\n FileVideoIcon,\n FolderIcon,\n FolderOpenIcon,\n ImageIcon,\n MusicIcon,\n PackageBoxIcon,\n PenToolIcon,\n SubtitlesIcon,\n VideoIcon,\n type MediaIconProps,\n} from \"./icons\";\n\nconst ICONS: Record<FileIconName, (props: MediaIconProps) => ReturnType<typeof FileGlyph>> = {\n image: ImageIcon,\n \"pen-tool\": PenToolIcon,\n video: VideoIcon,\n music: MusicIcon,\n \"file-type\": FileTypeIcon,\n \"file-text\": FileTextIcon,\n code: CodeIcon,\n braces: BracesIcon,\n subtitles: SubtitlesIcon,\n \"file-code\": FileCodeIcon,\n \"file-json\": FileJsonIcon,\n \"file-spreadsheet\": FileSpreadsheetIcon,\n database: DatabaseIcon,\n package: PackageBoxIcon,\n archive: ArchiveIcon,\n folder: FolderIcon,\n \"folder-open\": FolderOpenIcon,\n file: FileGlyph,\n \"file-audio\": FileAudioIcon,\n \"file-video\": FileVideoIcon,\n};\n\nexport interface FileIconProps {\n /** Either the filename (for files) or omitted for folders. */\n fileName?: string | undefined;\n /** Server MIME — when set, resolves audio/webm vs video/webm correctly. */\n mimeType?: string | null | undefined;\n /** If true, renders a folder icon. `open` picks the open-folder glyph. */\n isFolder?: boolean | undefined;\n open?: boolean | undefined;\n /** Override the mapped color (useful for selected states). */\n colorClass?: string | undefined;\n className?: string | undefined;\n size?: number | undefined;\n}\n\nexport function FileIcon({\n fileName,\n mimeType = null,\n isFolder,\n open,\n colorClass,\n className,\n size = 16,\n}: FileIconProps) {\n const details = isFolder\n ? getFolderKindDetails(open)\n : getFileKindDetails(fileName ?? \"\", mimeType);\n const Icon = ICONS[details.icon];\n const style: CSSProperties = {\n width: `${size}px`,\n height: `${size}px`,\n minWidth: `${size}px`,\n };\n return (\n <Icon\n style={style}\n className={cn(\"shrink-0\", colorClass ?? details.colorClass, className)}\n aria-hidden=\"true\"\n />\n );\n}\n","/**\n * src/viewers/generic-viewer.tsx — the no-dedicated-viewer card.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/GenericPreview.tsx`.\n *\n * DEFECT FIXED IN THE PORT (recorded in CHANGELOG 0.4.0, never silently):\n * the original shipped a `DEBUG_RING_GENERIC_PREVIEW` fuchsia ring plus a\n * \"GenericPreview\" corner badge — a layering-debug artifact marked \"Rip this\n * out when done\" that reached users on every unpreviewable file. Absorption\n * kills it; the package has no debug chrome.\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { FileIcon } from \"../react/file-icon\";\nimport { DownloadIcon, FileTextIcon, SpinnerIcon } from \"../react/icons\";\nimport { formatFileSize } from \"@ai-matrx/kit/format\";\nimport type { MediaViewerProps } from \"./types\";\n\nexport function GenericViewer({\n fileName,\n fileSize,\n generic,\n className,\n}: MediaViewerProps) {\n const onDownload = generic?.onDownload;\n const onViewAsText = generic?.onViewAsText;\n const viewAsTextLabel = generic?.viewAsTextLabel ?? \"View as text\";\n const viewAsTextPrimary = generic?.viewAsTextPrimary ?? true;\n const viewAsTextBusy = generic?.viewAsTextBusy ?? false;\n const hasViewAsText = typeof onViewAsText === \"function\";\n const hasDownload = typeof onDownload === \"function\";\n\n return (\n <div\n className={cn(\n \"relative flex h-full w-full flex-col items-center justify-center gap-4 p-6 text-center\",\n className,\n )}\n >\n <FileIcon fileName={fileName} size={48} />\n <div>\n <p className=\"max-w-md truncate text-sm font-medium\">{fileName}</p>\n <p className=\"text-xs text-muted-foreground\">\n {formatFileSize(fileSize ?? null)}\n </p>\n </div>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n {generic?.message ??\n (hasViewAsText\n ? \"No built-in previewer for this file type.\"\n : \"This file type can't be previewed here.\")}\n </p>\n <div className=\"flex flex-wrap items-center justify-center gap-2\">\n {onViewAsText && viewAsTextPrimary ? (\n <ViewAsTextButton\n onClick={onViewAsText}\n label={viewAsTextLabel}\n busy={viewAsTextBusy}\n variant=\"primary\"\n />\n ) : null}\n {onDownload ? (\n <button\n type=\"button\"\n onClick={onDownload}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm\",\n hasViewAsText && viewAsTextPrimary\n ? \"border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\",\n )}\n >\n <DownloadIcon className=\"h-4 w-4\" />\n Download\n </button>\n ) : null}\n {onViewAsText && !viewAsTextPrimary ? (\n <ViewAsTextButton\n onClick={onViewAsText}\n label={viewAsTextLabel}\n busy={viewAsTextBusy}\n variant=\"secondary\"\n />\n ) : null}\n </div>\n {!hasDownload && !hasViewAsText ? (\n <p className=\"max-w-sm text-[11px] text-muted-foreground/70\">\n Download it from the file's actions menu to open it in another\n application.\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction ViewAsTextButton({\n onClick,\n label,\n busy,\n variant,\n}: {\n onClick: () => void;\n label: string;\n busy: boolean;\n variant: \"primary\" | \"secondary\";\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={busy}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-60\",\n variant === \"primary\"\n ? \"bg-primary text-primary-foreground hover:bg-primary/90\"\n : \"border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground\",\n )}\n >\n {busy ? (\n <SpinnerIcon className=\"h-4 w-4 animate-spin\" />\n ) : (\n <FileTextIcon className=\"h-4 w-4\" />\n )}\n {label}\n </button>\n );\n}\n","/**\n * src/viewers/html-viewer.tsx — saved-HTML viewer (rendered + source).\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/HtmlPreview.tsx`.\n *\n * THE SANDBOX IS THE POINT, AND IT IS WHY THIS BELONGS IN THE PACKAGE. The\n * rendered view mounts `sandbox=\"allow-scripts allow-popups allow-forms\"`\n * WITHOUT `allow-same-origin`: the framed page may run scripts (most saved\n * pages need them to look right) but cannot read the host app's cookies,\n * browser persistence, or call its APIs, and cannot navigate the top frame.\n * `referrerPolicy=\"no-referrer\"` keeps the durable URL out of the framed\n * page's outbound requests. Every app that renders user-supplied HTML needs\n * exactly this attribute set, and getting one token wrong is a real XSS —\n * the textbook case for Arman's third test (\"less-than-perfect unless done\n * perfectly → in the package\"). Hosts do not get to configure it.\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { ViewerError, ViewerSkeleton } from \"./chrome\";\nimport { MarkupModeToggle, useMarkupMode } from \"./markup-chrome\";\nimport type { MediaViewerProps, MediaViewerViewport } from \"./types\";\nimport { useViewerDisplayUrl, useViewerText } from \"./use-viewer-bytes\";\n\n/** Device widths for the viewport simulator. Ported from the original. */\nconst VIEWPORT_WIDTH: Record<Exclude<MediaViewerViewport, \"auto\">, number> = {\n mobile: 390,\n tablet: 768,\n desktop: 1280,\n};\n\nexport function HtmlViewer(props: MediaViewerProps) {\n const { className, fileName, markupControls } = props;\n const { mode, setMode, controlled } = useMarkupMode(markupControls);\n\n return (\n <div className={cn(\"flex h-full w-full flex-col\", className)}>\n {controlled ? null : (\n <div className=\"flex shrink-0 items-center justify-between gap-2 border-b border-border/60 bg-background px-3 py-1.5 text-xs\">\n <span className=\"truncate font-medium text-foreground\">\n {fileName}\n </span>\n <MarkupModeToggle\n mode={mode}\n onChange={setMode}\n renderedLabel=\"Rendered\"\n renderedIcon=\"globe\"\n />\n </div>\n )}\n <div className=\"relative min-h-0 flex-1\">\n {mode === \"rendered\" ? (\n <HtmlRenderedView {...props} />\n ) : (\n <HtmlSourceView {...props} />\n )}\n </div>\n </div>\n );\n}\n\nfunction HtmlRenderedView({ source, fileName, markupControls }: MediaViewerProps) {\n const { url, unavailable } = useViewerDisplayUrl(source);\n const viewport = markupControls?.viewport ?? \"auto\";\n const reloadKey = markupControls?.reloadKey ?? 0;\n const [errored, setErrored] = useState(false);\n\n useEffect(() => {\n setErrored(false);\n }, [reloadKey, url]);\n\n if (unavailable) {\n return (\n <ViewerError\n title=\"This page isn't available\"\n hint=\"You may not have access to it, or it may have been deleted.\"\n />\n );\n }\n if (!url) return <ViewerSkeleton />;\n if (errored) return <ViewerError title=\"Preview unavailable\" />;\n\n const constrained = viewport !== \"auto\";\n const width = constrained ? VIEWPORT_WIDTH[viewport] : undefined;\n\n return (\n <div\n className={cn(\n \"h-full w-full overflow-auto bg-muted/10\",\n constrained && \"flex items-start justify-center\",\n )}\n >\n <div\n className={cn(\n \"h-full bg-background\",\n constrained\n ? \"my-4 overflow-hidden rounded-md border border-border/60 shadow-lg\"\n : \"w-full\",\n )}\n style={constrained ? { width } : undefined}\n >\n <iframe\n // `reloadKey` in the key forces a clean re-mount on an explicit reload.\n key={`${reloadKey}-${url}`}\n src={url}\n title={fileName}\n // NEVER add `allow-same-origin` here — see the module header.\n sandbox=\"allow-scripts allow-popups allow-forms\"\n referrerPolicy=\"no-referrer\"\n className=\"h-full w-full border-0 bg-white\"\n onError={() => setErrored(true)}\n />\n </div>\n </div>\n );\n}\n\nfunction HtmlSourceView({ source, maxBytes = 1024 * 1024 }: MediaViewerProps) {\n const { text, error, loading } = useViewerText(source, maxBytes);\n if (error) return <ViewerError title=\"Couldn't load source\" message={error} />;\n if (loading || text === null) return <ViewerSkeleton />;\n return (\n <pre className=\"h-full w-full overflow-auto bg-muted/10 p-4 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap\">\n {text}\n </pre>\n );\n}\n","/**\n * src/viewers/markup-chrome.tsx — the rendered/source switch shared by the\n * SVG and HTML viewers, and the controlled/uncontrolled mode resolution both\n * of them need.\n *\n * The matrx-frontend originals each hand-rolled this (SvgPreview a floating\n * segmented control, HtmlPreview a header strip), and each hard-wired itself\n * to the app's `FileViewerControlsContext`. Here the host rail arrives as\n * OPTIONAL props: when a host drives the mode, the viewer hides its own\n * toolbar and obeys; when nothing drives it, the viewer is fully capable on\n * its own (C23).\n */\n\n\"use client\";\n\nimport { useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { CodeIcon, GlobeIcon, ImageIcon } from \"../react/icons\";\nimport type { MediaViewerMarkupControls, MediaViewerMarkupMode } from \"./types\";\n\nexport interface ResolvedMarkupMode {\n mode: MediaViewerMarkupMode;\n setMode: (mode: MediaViewerMarkupMode) => void;\n /** True when the HOST drives the mode — the viewer must not draw a toolbar. */\n controlled: boolean;\n}\n\nexport function useMarkupMode(\n controls: MediaViewerMarkupControls | undefined,\n): ResolvedMarkupMode {\n const [localMode, setLocalMode] = useState<MediaViewerMarkupMode>(\"rendered\");\n const controlled = controls?.mode !== undefined;\n return {\n mode: controls?.mode ?? localMode,\n setMode: controls?.onModeChange ?? setLocalMode,\n controlled,\n };\n}\n\nexport function MarkupModeToggle({\n mode,\n onChange,\n renderedLabel = \"Rendered\",\n renderedIcon = \"image\",\n className,\n}: {\n mode: MediaViewerMarkupMode;\n onChange: (mode: MediaViewerMarkupMode) => void;\n renderedLabel?: string | undefined;\n renderedIcon?: \"image\" | \"globe\" | undefined;\n className?: string | undefined;\n}) {\n return (\n <div className={cn(\"flex items-center gap-0.5\", className)}>\n <ToggleButton\n active={mode === \"rendered\"}\n onClick={() => onChange(\"rendered\")}\n label={renderedLabel}\n icon={\n renderedIcon === \"globe\" ? (\n <GlobeIcon className=\"h-3.5 w-3.5\" />\n ) : (\n <ImageIcon className=\"h-3.5 w-3.5\" />\n )\n }\n />\n <ToggleButton\n active={mode === \"source\"}\n onClick={() => onChange(\"source\")}\n label=\"Source\"\n icon={<CodeIcon className=\"h-3.5 w-3.5\" />}\n />\n </div>\n );\n}\n\nfunction ToggleButton({\n active,\n onClick,\n icon,\n label,\n}: {\n active: boolean;\n onClick: () => void;\n icon: React.ReactNode;\n label: string;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={active}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded px-2 py-1 text-[11px] font-medium transition-colors\",\n active\n ? \"bg-accent text-accent-foreground\"\n : \"text-muted-foreground hover:bg-muted hover:text-foreground\",\n )}\n >\n {icon}\n <span>{label}</span>\n </button>\n );\n}\n","/**\n * src/viewers/svg-viewer.tsx — SVG viewer (rendered + XML source).\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/SvgPreview.tsx`.\n *\n * SVG is the one image format that is also text, so it gets two views. The\n * rendered view obtains authenticated bytes through the MediaClient and binds\n * its lifecycle-owned object URL to `<img>`; the source view decodes the same\n * client-managed bytes only when the user asks. A private durable download URL\n * cannot attach a bearer token from an image element, so refs never bind that\n * locator directly.\n *\n * Seam inversions from the original: `recognizeOurFileUrl` (the host's\n * recoverability classifier) becomes `MediaResolution.recoverable`, which the\n * MediaClient already decides; `useFileBlob` becomes `useViewerText`; the\n * transparency grid ships as package CSS-in-style rather than the host's\n * `bg-checkerboard` utility (which no fresh app would have — C26).\n */\n\n\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cn } from \"../react/cn\";\nimport { useMediaBlob } from \"../core/use-media-blob\";\nimport { ViewerError, ViewerSkeleton } from \"./chrome\";\nimport { MarkupModeToggle, useMarkupMode } from \"./markup-chrome\";\nimport { TRANSPARENCY_GRID_STYLE } from \"./transparency-grid\";\nimport type { MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\nexport function SvgViewer(props: MediaViewerProps) {\n const { className, markupControls } = props;\n const { mode, setMode, controlled } = useMarkupMode(markupControls);\n\n return (\n <div\n className={cn(\n \"relative flex h-full min-h-0 w-full flex-col bg-background\",\n className,\n )}\n >\n {controlled ? null : (\n <MarkupModeToggle\n mode={mode}\n onChange={setMode}\n className=\"absolute top-3 right-3 z-10 rounded-md border border-border bg-background/95 p-0.5 shadow-sm backdrop-blur-sm\"\n />\n )}\n {mode === \"rendered\" ? (\n <SvgRenderedView {...props} />\n ) : (\n <SvgSourceView {...props} />\n )}\n </div>\n );\n}\n\nfunction SvgRenderedView({ source, fileName }: MediaViewerProps) {\n // An SVG is an active document, not just a passive image. Always render a\n // ref from authenticated bytes through the client's lifecycle-owned blob\n // URL: a private `/files/{id}/download` locator cannot attach a bearer token\n // when it is bound directly to `<img src>`, and a public display URL is not a\n // promise that its pixels are safe for every browser consumer. Blob sources\n // already carry their own host-owned URL and must never touch the client.\n const fromClient = useMediaBlob(source.kind === \"ref\" ? source.ref : null);\n const [normalizedUrl, setNormalizedUrl] = useState<string | null>(null);\n useEffect(() => {\n const blob = fromClient.blob;\n if (!blob || blob.type === \"image/svg+xml\") {\n setNormalizedUrl(null);\n return undefined;\n }\n // Upload/storage services commonly label SVG bytes as generic XML. An\n // object URL preserves that MIME, and browsers then reject it as an image\n // even though the authenticated bytes are valid SVG. Re-label the same\n // bytes locally; the package owns and revokes this derived URL.\n const normalized = new Blob([blob], { type: \"image/svg+xml\" });\n const objectUrl = URL.createObjectURL(normalized);\n setNormalizedUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [fromClient.blob]);\n const url =\n source.kind === \"blob\" ? source.url : normalizedUrl ?? fromClient.url;\n const loading = source.kind === \"ref\" && fromClient.loading;\n const error = source.kind === \"ref\" ? fromClient.error : null;\n\n if (error) {\n return (\n <ViewerError\n title=\"SVG could not be rendered\"\n message={error}\n hint=\"Switch to the Source view to inspect the markup.\"\n />\n );\n }\n if (loading || !url) return <ViewerSkeleton className=\"flex-1\" />;\n\n return (\n <div\n className=\"flex flex-1 items-center justify-center overflow-auto p-4\"\n style={TRANSPARENCY_GRID_STYLE}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n src={url}\n alt={fileName}\n className=\"max-h-full max-w-full object-contain drop-shadow-sm\"\n />\n </div>\n );\n}\n\nfunction SvgSourceView({ source, maxBytes = 1024 * 1024 }: MediaViewerProps) {\n const { text, error, loading } = useViewerText(source, maxBytes);\n if (error) return <ViewerError title=\"Could not load source\" message={error} />;\n if (loading || text === null) return <ViewerSkeleton className=\"flex-1\" />;\n return (\n <pre className=\"m-0 flex-1 overflow-auto bg-muted/20 px-4 py-3 font-mono text-xs leading-relaxed break-words whitespace-pre-wrap text-foreground\">\n {text}\n </pre>\n );\n}\n","/**\n * src/viewers/transparency-grid.ts — the alpha-channel checkerboard.\n *\n * Ships as inline style rather than a utility class: the matrx-frontend\n * originals used two different mechanisms for the same thing (an inline\n * gradient stack in ImagePreview, a `bg-checkerboard` utility in SvgPreview),\n * and a utility class is exactly the kind of host-owned dependency C26 bans a\n * package component from assuming. Sized in CSS pixels so the pattern reads\n * the same at any zoom.\n */\n\nexport const TRANSPARENCY_GRID_STYLE: {\n backgroundImage: string;\n backgroundSize: string;\n backgroundPosition: string;\n} = {\n backgroundImage:\n \"linear-gradient(45deg, rgb(0 0 0 / 0.08) 25%, transparent 25%), \" +\n \"linear-gradient(-45deg, rgb(0 0 0 / 0.08) 25%, transparent 25%), \" +\n \"linear-gradient(45deg, transparent 75%, rgb(0 0 0 / 0.08) 75%), \" +\n \"linear-gradient(-45deg, transparent 75%, rgb(0 0 0 / 0.08) 75%)\",\n backgroundSize: \"16px 16px\",\n backgroundPosition: \"0 0, 0 8px, 8px -8px, -8px 0\",\n};\n","/**\n * src/viewers/text-viewer.tsx — plain-text viewer.\n *\n * Absorbed from matrx-frontend\n * `features/files/components/core/FilePreview/previewers/TextPreview.tsx`\n * (behavior ported verbatim; the byte/text/cap machinery moved to\n * `useViewerText`, the error card and copy button to `chrome.tsx`).\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { formatCount } from \"@ai-matrx/kit/format\";\nimport { ViewerCopyButton, ViewerError, ViewerSkeleton, ViewerToolbar, truncationNote } from \"./chrome\";\nimport type { MediaViewerProps } from \"./types\";\nimport { useViewerText } from \"./use-viewer-bytes\";\n\nexport function TextViewer({\n source,\n className,\n maxBytes = 1024 * 1024,\n}: MediaViewerProps) {\n const { text, error, loading, truncated } = useViewerText(source, maxBytes);\n\n if (error) return <ViewerError message={error} className={className} />;\n if (loading || text === null) {\n return <ViewerSkeleton tone=\"plain\" className={className} />;\n }\n\n return (\n <div\n className={cn(\"flex h-full w-full flex-col overflow-hidden\", className)}\n >\n <ViewerToolbar>\n <span className=\"text-muted-foreground\">\n {truncated\n ? `Preview ${truncationNote(maxBytes)}.`\n : `${formatCount(text.length)} characters`}\n </span>\n <ViewerCopyButton text={text} />\n </ViewerToolbar>\n <pre className=\"flex-1 overflow-auto bg-background p-3 font-mono text-xs leading-5 break-words whitespace-pre-wrap\">\n {text}\n </pre>\n </div>\n );\n}\n","/**\n * src/viewers/unavailable-viewer.tsx — THE ANNOUNCING DEFAULT (C23 + law 4,\n * \"nothing fails silently\").\n *\n * This renders when a kind needs a heavy engine the host has not registered\n * (PDF.js, a Markdown/KaTeX stack, SheetJS, an Office extractor). It is the\n * one place in the package where a default IS a shortfall, so unlike the\n * code viewer's un-highlighted default it says so — plainly, with the remedy\n * — and it still gives the user every action that remains possible: the\n * generic card's download / view-as-text escape hatches.\n *\n * The forbidden alternatives are a blank pane, a spinner that never resolves,\n * and a disabled-looking control. A screen is absent or honest.\n */\n\n\"use client\";\n\nimport { cn } from \"../react/cn\";\nimport { GenericViewer } from \"./generic-viewer\";\nimport type { MediaViewerKind, MediaViewerProps } from \"./types\";\n\n/** What a host must register to make this kind render properly. */\nconst ENGINE_FOR_KIND: Partial<Record<MediaViewerKind, string>> = {\n pdf: \"a PDF engine (e.g. PDF.js / react-pdf)\",\n markdown: \"a Markdown renderer\",\n data: \"a spreadsheet/CSV parser\",\n spreadsheet: \"a spreadsheet/CSV parser\",\n office: \"an Office document extractor\",\n image: \"an image viewer\",\n video: \"a video player\",\n audio: \"an audio player\",\n};\n\nexport function MediaViewerUnavailable({\n kind,\n ...props\n}: MediaViewerProps & { kind: MediaViewerKind }) {\n const engine = ENGINE_FOR_KIND[kind] ?? `a \"${kind}\" viewer`;\n const generic = props.generic;\n return (\n <div className={cn(\"flex h-full w-full flex-col\", props.className)}>\n <div className=\"shrink-0 border-b border-amber-500/30 bg-amber-500/10 px-3 py-2 text-center text-xs text-amber-700 dark:text-amber-300\">\n No {kind} viewer is registered in this app, so this file can't be\n displayed here. An app developer registers {engine} with{\" \"}\n <code className=\"font-mono\">\n registerMediaViewer("{kind}", …)\n </code>\n .\n </div>\n <div className=\"min-h-0 flex-1\">\n <GenericViewer\n {...props}\n className={undefined}\n generic={{\n ...generic,\n message:\n generic?.message ??\n \"You can still download this file and open it in another application.\",\n }}\n />\n </div>\n </div>\n );\n}\n","/**\n * src/viewers/preview-kind.ts — filename/MIME → viewer kind.\n *\n * The DEFAULT resolution, derived from the package's own file-kind registry\n * (`getFileKindDetails`) so a fresh app gets correct dispatch with zero setup.\n * A host with a richer registry of its own — matrx-frontend's `FILE_TYPES`\n * carries preview/thumbnail/size-cap columns this package deliberately does\n * not absorb (C8) — passes `previewKind` explicitly and this is never called.\n */\n\nimport { getFileKindDetails } from \"../core/file-kind\";\nimport type { MediaViewerKind } from \"./types\";\n\nconst EXTENSION_KIND: Record<string, MediaViewerKind> = {\n svg: \"svg\",\n pdf: \"pdf\",\n md: \"markdown\",\n markdown: \"markdown\",\n mdx: \"markdown\",\n html: \"html\",\n htm: \"html\",\n csv: \"data\",\n tsv: \"data\",\n xlsx: \"spreadsheet\",\n xls: \"spreadsheet\",\n doc: \"office\",\n docx: \"office\",\n ppt: \"office\",\n pptx: \"office\",\n txt: \"text\",\n log: \"text\",\n text: \"text\",\n};\n\nfunction extensionOf(fileName: string): string {\n const base = fileName.split(/[\\\\/]/).pop() ?? fileName;\n const dot = base.lastIndexOf(\".\");\n if (dot <= 0) return \"\";\n return base.slice(dot + 1).toLowerCase();\n}\n\nexport function getPreviewKind(\n fileName: string,\n mimeType?: string | null,\n): MediaViewerKind {\n const explicit = EXTENSION_KIND[extensionOf(fileName)];\n if (explicit) return explicit;\n\n const details = getFileKindDetails(fileName, mimeType ?? undefined);\n switch (details.category) {\n case \"IMAGE\":\n return details.icon === \"pen-tool\" ? \"svg\" : \"image\";\n case \"VIDEO\":\n return \"video\";\n case \"AUDIO\":\n return \"audio\";\n case \"CODE\":\n return \"code\";\n case \"DATA\":\n return \"code\";\n case \"NOTEBOOK\":\n return \"code\";\n case \"SUBTITLES\":\n return \"text\";\n case \"DOCUMENT\":\n // The DOCUMENT bucket holds PDFs, markdown and plain text; the explicit\n // extension table above already caught the first two, so anything left\n // is text-shaped.\n return \"text\";\n default:\n return \"generic\";\n }\n}\n"],"mappings":"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","names":["createElement","createElement","useMemo","useState","jsx","jsxs","useEffect","useState","useState","useCallback","useCallback","useState","useEffect","useEffect","useState","useEffect","jsx","jsxs","useState","useMemo","createElement","jsx","FileIcon","formatFileSize","jsx","jsxs","FileIcon","useEffect","useState","useState","jsx","jsxs","useState","jsx","jsxs","useState","useEffect","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","jsx","jsxs","extensionOf","jsx","createElement"]}
|