@ai-matrx/media 0.1.0
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 +61 -0
- package/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/core.cjs +577 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +214 -0
- package/dist/core.d.ts +214 -0
- package/dist/core.js +559 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +227 -0
- package/dist/index.d.ts +227 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +2127 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +310 -0
- package/dist/react.d.ts +310 -0
- package/dist/react.js +2120 -0
- package/dist/react.js.map +1 -0
- package/dist/use-media-upload-VjUhqbyY.d.cts +270 -0
- package/dist/use-media-upload-VjUhqbyY.d.ts +270 -0
- package/package.json +114 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/cn.ts","../src/react/icons.tsx","../src/core/file-kind.ts","../src/react/file-icon.tsx","../src/react/inline-media-ref.tsx","../src/core/context.ts","../src/core/use-media-blob.ts","../src/core/ref-key.ts","../src/core/use-media-load-recovery.ts","../src/types.ts","../src/core/use-media-resolution.ts","../src/react/media-thumbnail.tsx","../src/core/use-thumbnail-source.ts","../src/react/use-media-dropzone.ts","../src/react/file-upload-dropzone.tsx","../src/core/use-media-upload.ts","../src/react/upload-progress-list.tsx","../src/react/media-action-toolbar.tsx","../src/core/use-media-actions.ts","../src/react/media-lightbox.tsx"],"sourcesContent":["/**\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/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 * 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/react/inline-media-ref.tsx — the canonical inline media renderer.\n *\n * Verbatim behavior port of matrx-frontend\n * `features/files/components/inline/InlineMediaRef.tsx` (849 LOC, 116\n * importers) with only the coupling seams inverted:\n *\n * - URL resolution / public-CDN detection / auth-transport choice →\n * `MediaClient.resolve` (`transport: \"blob\"` is the private-pixels lane;\n * the Redux `useEnsureCloudFile`/`selectFileById` hydration lives behind\n * the client now)\n * - bearer-authenticated bytes → `MediaClient.getBlob` via `useMediaBlob`\n * - session-refresh retry → `MediaClient.recoverLoadError` via\n * `useMediaLoadRecovery`\n * - `next/image` → the injected `MediaHostPorts.ImageComponent` (plain\n * `<img>` default)\n * - audio output sink + exclusive-playback join → the injected\n * `MediaHostPorts.playbackSession` (inert default)\n * - lucide icons → the package's own inlined SVGs (C19)\n *\n * Pass a `MediaRef` (or a fileId / EXTERNAL public URL string), get back a\n * correctly-sized `<img>` / `<video>` / `<audio>`. There is NO `src` prop —\n * durable refs are the only identity this component accepts (law 2/3).\n */\n\n\"use client\";\n\nimport React, {\n useCallback,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n} from \"react\";\nimport type {\n MediaImageComponentProps,\n MediaRef,\n MediaRefLike,\n PlaybackSessionPort,\n} from \"../types\";\nimport { useMediaHostPorts } from \"../core/context\";\nimport { useMediaBlob } from \"../core/use-media-blob\";\nimport { useMediaLoadRecovery } from \"../core/use-media-load-recovery\";\nimport { useMediaResolution } from \"../core/use-media-resolution\";\nimport { cn } from \"./cn\";\nimport {\n CheckIcon,\n CopyIcon,\n FileAudioIcon,\n FileIcon as FileGlyph,\n FileVideoIcon,\n ImageIcon,\n ImageOffIcon,\n VideoOffIcon,\n VolumeXIcon,\n} from \"./icons\";\n\nexport type InlineMediaRefSize =\n | \"xs\" // 24×24\n | \"sm\" // 32×32\n | \"md\" // 64×64\n | \"lg\" // 128×128\n | \"xl\" // 256×256\n | \"fill\" // parent-controlled — media fills its container via w-full h-full\n | { width: number; height: number };\n\nexport type InlineMediaRefFit = \"cover\" | \"contain\" | \"fill\";\n\nexport interface InlineMediaRefProps {\n /**\n * Reference to the media: a {@link MediaRef}, a bare fileId string, an\n * EXTERNAL public URL string, or null/undefined (renders the fallback).\n *\n * Named `ref` as a CONTENT prop, exactly like the original (React 19\n * treats ref as a regular prop on function components) — the 116 existing\n * call sites pass `ref={mediaRef}` and must keep working at the C9 swap.\n * Use `mediaElementRef` for imperative access to the DOM node.\n */\n ref?: MediaRefLike | null | undefined;\n /** Square dimension preset or explicit width/height. Default `\"md\"` (64×64). */\n size?: InlineMediaRefSize | undefined;\n /** CSS object-fit. Default `\"cover\"`. */\n fit?: InlineMediaRefFit | undefined;\n /** Rendered when the ref can't be resolved to a URL at all. Default `\"icon\"`. */\n fallback?: \"icon\" | \"skeleton\" | null | undefined;\n /** Override the icon shown in `fallback=\"icon\"`. */\n fallbackIcon?: React.ReactNode | undefined;\n /**\n * Rendered when the URL *was* resolved but the media element failed to\n * load. Default `\"info\"` — an informative destructive-tinted panel with\n * URL + copy button + alt text; compacts to icon-only below ~64px.\n */\n errorFallback?: \"info\" | \"icon\" | \"skeleton\" | null | undefined;\n /** Alt text for `<img>`. Defaults to \"\" (decorative). */\n alt?: string | undefined;\n /** Force the media element type. Default: infer from `mime_type` / resolution. */\n as?: \"img\" | \"video\" | \"audio\" | undefined;\n controls?: boolean | undefined;\n autoPlay?: boolean | undefined;\n loop?: boolean | undefined;\n muted?: boolean | undefined;\n playsInline?: boolean | undefined;\n preload?: \"none\" | \"metadata\" | \"auto\" | undefined;\n /** Space-separated native controls to hide — forwarded to `<video controlsList>`. */\n controlsList?: string | undefined;\n rounded?: \"none\" | \"sm\" | \"md\" | \"lg\" | \"full\" | undefined;\n /** Click handler — wires up cursor + role + keyboard activation. */\n onClick?: ((event: React.MouseEvent | React.KeyboardEvent) => void) | undefined;\n /**\n * Fires after the client's ONE recovery attempt is exhausted (or the\n * failure was unrecoverable). The internal error fallback still renders\n * unless `errorFallback={null}`.\n */\n onError?:\n | ((\n event: React.SyntheticEvent<\n HTMLImageElement | HTMLVideoElement | HTMLAudioElement\n >,\n ) => void)\n | undefined;\n onLoad?:\n | ((\n event: React.SyntheticEvent<\n HTMLImageElement | HTMLVideoElement | HTMLAudioElement\n >,\n ) => void)\n | undefined;\n /**\n * Forwarded to the underlying element for imperative DOM access. Not a\n * React `forwardRef` — pass any ref-like value here instead. When\n * supplied, the ImageComponent branch is skipped so the ref attaches to\n * the real DOM node.\n */\n mediaElementRef?:\n | React.Ref<HTMLImageElement | HTMLVideoElement | HTMLAudioElement>\n | undefined;\n /**\n * Canvas pixel reads: `crossOrigin` consumers route through the\n * bearer-authenticated blob lane unless the resolution is a CORS-safe\n * public CDN URL.\n */\n crossOrigin?: \"anonymous\" | \"use-credentials\" | undefined;\n border?: \"none\" | \"subtle\" | undefined;\n className?: string | undefined;\n}\n\nconst SIZE_PX: Record<\n Exclude<InlineMediaRefSize, \"fill\" | { width: number; height: number }>,\n number\n> = {\n xs: 24,\n sm: 32,\n md: 64,\n lg: 128,\n xl: 256,\n};\n\nconst ROUNDED_CLASS: Record<\n NonNullable<InlineMediaRefProps[\"rounded\"]>,\n string\n> = {\n none: \"\",\n sm: \"rounded-sm\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n full: \"rounded-full\",\n};\n\nfunction resolveDimensions(\n size: InlineMediaRefSize,\n): { width: number; height: number } | \"fill\" {\n if (typeof size === \"object\") return size;\n if (size === \"fill\") return \"fill\";\n const px = SIZE_PX[size];\n return { width: px, height: px };\n}\n\nfunction inferElementType(\n ref: MediaRefLike | null | undefined,\n resolutionKind: \"image\" | \"video\" | \"audio\" | \"file\" | undefined,\n override?: InlineMediaRefProps[\"as\"],\n): \"img\" | \"video\" | \"audio\" {\n if (override) return override;\n if (ref && typeof ref === \"object\" && ref.mime_type) {\n if (ref.mime_type.startsWith(\"video/\")) return \"video\";\n if (ref.mime_type.startsWith(\"audio/\")) return \"audio\";\n }\n if (resolutionKind === \"video\") return \"video\";\n if (resolutionKind === \"audio\") return \"audio\";\n return \"img\";\n}\n\n/**\n * Best-effort URL prettifier for the informative error panel. Parsing for\n * DISPLAY only — never construction (law 5).\n */\nfunction prettifyUrl(url: string): { host: string | null; tail: string } {\n try {\n const u = new URL(url);\n const tail = `${u.pathname}${u.search}`;\n return { host: u.host, tail: tail === \"/\" ? \"\" : tail };\n } catch {\n return { host: null, tail: url };\n }\n}\n\nconst INERT_PLAYBACK: PlaybackSessionPort = {\n useMediaElementSink(forward) {\n // eslint-disable-next-line react-hooks/rules-of-hooks -- stable inert implementation, called as a hook\n return useCallback(\n (node: unknown) => {\n if (!forward) return;\n if (typeof forward === \"function\") forward(node);\n else forward.current = node;\n },\n [forward],\n );\n },\n usePlaybackSession() {\n // inert\n },\n};\n\nfunction FallbackVisual({\n kind,\n dimensions,\n rounded,\n border,\n className,\n icon,\n}: {\n kind: \"icon\" | \"skeleton\";\n dimensions: { width: number; height: number } | \"fill\";\n rounded: NonNullable<InlineMediaRefProps[\"rounded\"]>;\n border: NonNullable<InlineMediaRefProps[\"border\"]>;\n className?: string | undefined;\n icon: React.ReactNode;\n}) {\n const isFill = dimensions === \"fill\";\n const wrapperCls = cn(\n \"flex items-center justify-center bg-muted/60 text-muted-foreground\",\n ROUNDED_CLASS[rounded],\n border === \"subtle\" && \"border border-border\",\n kind === \"skeleton\" && \"animate-pulse\",\n isFill && \"w-full h-full\",\n className,\n );\n return (\n <div\n className={wrapperCls}\n style={\n isFill\n ? undefined\n : { width: dimensions.width, height: dimensions.height }\n }\n aria-hidden={kind === \"skeleton\"}\n >\n {kind === \"icon\" ? icon : null}\n </div>\n );\n}\n\nfunction InformativeErrorFallback({\n url,\n alt,\n elementType,\n mediaRef,\n dimensions,\n rounded,\n className,\n}: {\n url: string;\n alt: string;\n elementType: \"img\" | \"video\" | \"audio\";\n mediaRef: MediaRefLike | null | undefined;\n dimensions: { width: number; height: number } | \"fill\";\n rounded: NonNullable<InlineMediaRefProps[\"rounded\"]>;\n className?: string | undefined;\n}) {\n const shortAxis =\n dimensions === \"fill\"\n ? Number.POSITIVE_INFINITY\n : Math.min(dimensions.width, dimensions.height);\n const isCompact = dimensions !== \"fill\" && shortAxis < 64;\n const isMidsize = shortAxis < 140;\n\n const fileId =\n mediaRef && typeof mediaRef === \"object\" && \"file_id\" in mediaRef\n ? (mediaRef.file_id ?? null)\n : null;\n\n const FailIcon =\n elementType === \"video\"\n ? VideoOffIcon\n : elementType === \"audio\"\n ? VolumeXIcon\n : ImageOffIcon;\n\n const tooltip = [\n `Failed to load ${elementType}`,\n alt && `alt: ${alt}`,\n `url: ${url}`,\n fileId && `file_id: ${fileId}`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n if (isCompact) {\n return (\n <div\n className={cn(\n \"flex items-center justify-center bg-destructive/5 text-destructive border border-destructive/40 border-dashed\",\n ROUNDED_CLASS[rounded],\n className,\n )}\n style={{ width: dimensions.width, height: dimensions.height }}\n role=\"img\"\n aria-label={`Failed to load ${elementType}${alt ? `: ${alt}` : \"\"}`}\n title={tooltip}\n >\n <FailIcon className=\"h-1/2 w-1/2 max-h-5 max-w-5\" />\n </div>\n );\n }\n\n return (\n <InformativeErrorPanel\n url={url}\n alt={alt}\n elementType={elementType}\n fileId={fileId}\n dimensions={dimensions}\n rounded={rounded}\n className={className}\n compact={isMidsize}\n icon={<FailIcon className=\"h-3.5 w-3.5 shrink-0\" />}\n tooltip={tooltip}\n />\n );\n}\n\nfunction InformativeErrorPanel({\n url,\n alt,\n elementType,\n fileId,\n dimensions,\n rounded,\n className,\n compact,\n icon,\n tooltip,\n}: {\n url: string;\n alt: string;\n elementType: \"img\" | \"video\" | \"audio\";\n fileId: string | null;\n dimensions: { width: number; height: number } | \"fill\";\n rounded: NonNullable<InlineMediaRefProps[\"rounded\"]>;\n className?: string | undefined;\n compact: boolean;\n icon: React.ReactNode;\n tooltip: string;\n}) {\n const [copied, setCopied] = useState(false);\n const isFill = dimensions === \"fill\";\n const { host, tail } = prettifyUrl(url);\n\n const handleCopy = useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n event.preventDefault();\n navigator.clipboard\n ?.writeText(url)\n .then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n })\n .catch(() => {\n // Clipboard API can fail in non-HTTPS / permission-denied\n // contexts. Tooltip + selectable text already give the user the\n // URL, so this is non-fatal.\n });\n },\n [url],\n );\n\n return (\n <div\n className={cn(\n \"flex flex-col bg-destructive/5 text-foreground border border-destructive/40 border-dashed overflow-hidden\",\n ROUNDED_CLASS[rounded],\n compact ? \"p-1.5 gap-0.5\" : \"p-2 gap-1\",\n isFill ? \"w-full h-full\" : \"\",\n className,\n )}\n style={\n isFill\n ? undefined\n : { width: dimensions.width, height: dimensions.height }\n }\n role=\"img\"\n aria-label={`Failed to load ${elementType}${alt ? `: ${alt}` : \"\"}`}\n title={tooltip}\n >\n <div\n className={cn(\n \"flex items-center gap-1.5 text-destructive font-medium leading-tight\",\n compact ? \"text-[10px]\" : \"text-xs\",\n )}\n >\n {icon}\n <span className=\"truncate\">\n {elementType === \"img\"\n ? \"Image failed to load\"\n : elementType === \"video\"\n ? \"Video failed to load\"\n : \"Audio failed to load\"}\n </span>\n </div>\n\n {alt && !compact && (\n <div\n className=\"text-[11px] text-muted-foreground italic line-clamp-1\"\n title={alt}\n >\n {alt}\n </div>\n )}\n\n <div\n className={cn(\n \"flex items-end gap-1 mt-auto min-w-0\",\n compact ? \"text-[9px]\" : \"text-[10px]\",\n )}\n >\n <div className=\"font-mono text-muted-foreground truncate flex-1 min-w-0\">\n {host ? (\n <>\n <span className=\"text-foreground/80\">{host}</span>\n {tail && <span className=\"opacity-70\">{tail}</span>}\n </>\n ) : (\n <span>{tail}</span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"shrink-0 p-0.5 rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive transition-colors focus:outline-none focus:ring-1 focus:ring-destructive/40\",\n copied && \"text-emerald-600 dark:text-emerald-500\",\n )}\n aria-label={copied ? \"URL copied\" : \"Copy URL\"}\n title={copied ? \"URL copied\" : \"Copy URL\"}\n >\n {copied ? (\n <CheckIcon className=\"h-3 w-3\" width={12} height={12} />\n ) : (\n <CopyIcon className=\"h-3 w-3\" width={12} height={12} />\n )}\n </button>\n </div>\n\n {fileId && !compact && (\n <div className=\"text-[9px] font-mono text-muted-foreground/70 truncate\">\n {fileId}\n </div>\n )}\n </div>\n );\n}\n\nexport function InlineMediaRef({\n ref: mediaRef,\n size = \"md\",\n fit = \"cover\",\n fallback = \"icon\",\n fallbackIcon,\n errorFallback = \"info\",\n alt = \"\",\n as,\n controls = true,\n autoPlay,\n loop,\n muted,\n playsInline,\n preload,\n controlsList,\n rounded = \"md\",\n onClick,\n onError,\n onLoad,\n mediaElementRef,\n crossOrigin,\n border = \"none\",\n className,\n}: InlineMediaRefProps) {\n const ports = useMediaHostPorts();\n const { resolution, status, reason } = useMediaResolution(mediaRef);\n const elementType = inferElementType(mediaRef, resolution?.kind, as);\n\n // Private pixels ride the bearer-authenticated blob lane; a verified\n // public CDN URL is the sole direct-url exception for crossOrigin\n // consumers. This is automatic: callers never select auth transport.\n const needsBlob = Boolean(\n resolution &&\n (resolution.transport === \"blob\" ||\n (crossOrigin && resolution.isCdn !== true)),\n );\n const blob = useMediaBlob(needsBlob ? mediaRef : null);\n const url = needsBlob ? blob.url : (resolution?.src ?? null);\n\n const recovery = useMediaLoadRecovery(url, {\n recoverable: !needsBlob && resolution?.recoverable !== false,\n onTerminal: (event) =>\n onError?.(\n event as React.SyntheticEvent<\n HTMLImageElement | HTMLVideoElement | HTMLAudioElement\n >,\n ),\n });\n\n // Host audio system: output-sink routing + exclusive-playback join.\n const playback = ports.playbackSession ?? INERT_PLAYBACK;\n const sessionElRef = useRef<unknown>(null);\n const [isMediaPlaying, setIsMediaPlaying] = useState(false);\n const portSinkRef = playback.useMediaElementSink(\n mediaElementRef as ((node: unknown) => void) | { current: unknown } | null | undefined,\n );\n const sinkRef = (node: HTMLVideoElement | HTMLAudioElement | null) => {\n sessionElRef.current = node;\n portSinkRef(node);\n };\n const trackKey = useMemo(() => {\n if (mediaRef && typeof mediaRef === \"object\" && mediaRef.file_id) {\n return mediaRef.file_id;\n }\n return typeof mediaRef === \"string\" ? mediaRef : undefined;\n }, [mediaRef]);\n playback.usePlaybackSession(\n {\n isPlaying: isMediaPlaying,\n source: \"file-media\",\n label: alt || \"Media file\",\n trackKey,\n },\n sessionElRef,\n );\n const mediaSessionEvents = {\n onPlay: () => setIsMediaPlaying(true),\n onPause: () => setIsMediaPlaying(false),\n onEnded: () => setIsMediaPlaying(false),\n };\n\n const mediaResolutionError =\n status === \"unavailable\" ? (reason ?? \"unknown\") : (blob.error ?? null);\n const dimensions = resolveDimensions(size);\n const isFill = dimensions === \"fill\";\n const hasLoadError = recovery.failed;\n const handleLoadError = recovery.onLoadError as React.ReactEventHandler<\n HTMLImageElement | HTMLVideoElement | HTMLAudioElement\n >;\n\n const defaultIcon =\n elementType === \"video\" ? (\n <FileVideoIcon className=\"h-1/2 w-1/2\" />\n ) : elementType === \"audio\" ? (\n <FileAudioIcon className=\"h-1/2 w-1/2\" />\n ) : mediaRef ? (\n <ImageIcon className=\"h-1/2 w-1/2\" />\n ) : (\n <FileGlyph className=\"h-1/2 w-1/2\" />\n );\n\n const unresolvedDisplayUrl =\n mediaRef && typeof mediaRef === \"object\" && mediaRef.file_id\n ? `file:${mediaRef.file_id}`\n : \"unresolved-media\";\n\n if (!url) {\n if (mediaResolutionError) {\n if (errorFallback === null) return null;\n if (errorFallback === \"info\") {\n return (\n <InformativeErrorFallback\n url={unresolvedDisplayUrl}\n alt={alt}\n elementType={elementType}\n mediaRef={mediaRef}\n dimensions={dimensions}\n rounded={rounded}\n className={className}\n />\n );\n }\n return (\n <FallbackVisual\n kind={errorFallback}\n dimensions={dimensions}\n rounded={rounded}\n border={border}\n className={className}\n icon={fallbackIcon ?? defaultIcon}\n />\n );\n }\n if (needsBlob && blob.loading) {\n return (\n <FallbackVisual\n kind=\"skeleton\"\n dimensions={dimensions}\n rounded={rounded}\n border={border}\n className={className}\n icon={null}\n />\n );\n }\n if (!fallback) return null;\n return (\n <FallbackVisual\n kind={fallback}\n dimensions={dimensions}\n rounded={rounded}\n border={border}\n className={className}\n icon={fallbackIcon ?? defaultIcon}\n />\n );\n }\n\n // URL resolved but the remote fetch failed — render the informative (or\n // caller-overridden) error fallback. Keeps the original dimensions so\n // layouts don't jump.\n if (hasLoadError) {\n if (errorFallback === null) return null;\n if (errorFallback === \"info\") {\n return (\n <InformativeErrorFallback\n url={url}\n alt={alt}\n elementType={elementType}\n mediaRef={mediaRef}\n dimensions={dimensions}\n rounded={rounded}\n className={className}\n />\n );\n }\n return (\n <FallbackVisual\n kind={errorFallback}\n dimensions={dimensions}\n rounded={rounded}\n border={border}\n className={className}\n icon={fallbackIcon ?? defaultIcon}\n />\n );\n }\n\n const interactiveProps = onClick\n ? {\n onClick,\n onKeyDown: (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onClick(event);\n }\n },\n role: \"button\" as const,\n tabIndex: 0,\n className: cn(\n \"cursor-pointer\",\n \"focus:outline-none focus:ring-2 focus:ring-primary/50\",\n ),\n }\n : {};\n\n const baseCls = cn(\n \"block\",\n isFill && \"w-full h-full\",\n ROUNDED_CLASS[rounded],\n border === \"subtle\" && \"border border-border\",\n onClick && \"cursor-pointer\",\n interactiveProps.className,\n className,\n );\n\n const objectFitClass =\n fit === \"cover\"\n ? \"object-cover\"\n : fit === \"contain\"\n ? \"object-contain\"\n : \"object-fill\";\n\n const sizeAttrs = isFill\n ? {}\n : { width: dimensions.width, height: dimensions.height };\n\n if (elementType === \"video\") {\n return (\n <video\n key={recovery.retryKey}\n ref={sinkRef}\n src={url}\n {...sizeAttrs}\n className={cn(baseCls, objectFitClass)}\n controls={controls}\n autoPlay={autoPlay}\n loop={loop}\n muted={muted}\n playsInline={playsInline}\n preload={preload}\n controlsList={controlsList}\n onLoadedData={\n onLoad as React.ReactEventHandler<HTMLVideoElement> | undefined\n }\n onError={handleLoadError as React.ReactEventHandler<HTMLVideoElement>}\n crossOrigin={crossOrigin}\n {...mediaSessionEvents}\n {...interactiveProps}\n />\n );\n }\n if (elementType === \"audio\") {\n return (\n <audio\n key={recovery.retryKey}\n ref={sinkRef}\n src={url}\n className={cn(baseCls)}\n controls={controls}\n autoPlay={autoPlay}\n loop={loop}\n muted={muted}\n preload={preload}\n {...mediaSessionEvents}\n onLoadedData={\n onLoad as React.ReactEventHandler<HTMLAudioElement> | undefined\n }\n onError={handleLoadError as React.ReactEventHandler<HTMLAudioElement>}\n crossOrigin={crossOrigin}\n {...interactiveProps}\n />\n );\n }\n\n // Bail to plain <img> when the caller needs an event-target escape hatch\n // (onLoad / element ref / crossOrigin) — the native events must reach the\n // caller with the original SyntheticEvent shape.\n const needsPlainImg = !!onLoad || !!mediaElementRef || !!crossOrigin;\n\n // Use the host's ImageComponent (e.g. a next/image adapter) for our own\n // CDN-hosted URLs — better lazy-loading + DPR handling; arbitrary external\n // URLs may not be on the host's remotePatterns list, so they fall back to\n // a plain <img>.\n const isCdnUrl =\n resolution?.isCdn ??\n (url.startsWith(\"https://cdn.\") || url.includes(\"/cdn/\"));\n const HostImage = ports.ImageComponent as\n | ComponentType<MediaImageComponentProps>\n | undefined;\n if (HostImage && isCdnUrl && !isFill && !needsPlainImg && !needsBlob) {\n return (\n <HostImage\n key={recovery.retryKey}\n src={url}\n alt={alt}\n width={dimensions.width}\n height={dimensions.height}\n className={cn(baseCls, objectFitClass)}\n onError={handleLoadError as (event: unknown) => void}\n {...(interactiveProps as Partial<MediaImageComponentProps>)}\n />\n );\n }\n return (\n <img\n key={recovery.retryKey}\n ref={mediaElementRef as React.Ref<HTMLImageElement> | undefined}\n src={url}\n alt={alt}\n {...sizeAttrs}\n className={cn(baseCls, objectFitClass)}\n onLoad={onLoad as React.ReactEventHandler<HTMLImageElement> | undefined}\n onError={handleLoadError}\n crossOrigin={crossOrigin}\n {...interactiveProps}\n />\n );\n}\n\nexport default InlineMediaRef;\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/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 { stableRefKey } from \"./ref-key\";\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 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 },\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/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-load-recovery.ts — the durable-URL load-error machine.\n *\n * Ported from matrx-frontend `handler/hooks/useDurableSrc.ts`, with the\n * recovery POLICY inverted onto `MediaClient.recoverLoadError` (session\n * refresh → same-URL retry → terminal; the package may not implement a retry\n * of its own — that invariant is what killed the divergent\n * useUnifiedImageUrl/useUnifiedVideoUrl copies).\n *\n * `recoverable: false` resolutions (foreign URLs, blob: object URLs) skip the\n * client and fail straight through — a session refresh can't resurrect\n * someone else's link rot.\n */\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { mintDurableSrc, type DurableSrc } from \"../types\";\nimport { useMediaClient } from \"./context\";\n\nexport interface MediaLoadRecovery {\n /**\n * Bump this into the media element's `key` (or otherwise force a remount)\n * so a retry actually re-fires the network request for the same src.\n */\n retryKey: number;\n /** Wire to the media element's `onError`. */\n onLoadError: (event?: unknown) => void;\n /** True once recovery is exhausted (or was never possible). */\n failed: boolean;\n}\n\nexport function useMediaLoadRecovery(\n src: DurableSrc | string | null,\n options?: {\n recoverable?: boolean | undefined;\n /** Fires once recovery is exhausted, with the original element event. */\n onTerminal?: ((event?: unknown) => void) | undefined;\n },\n): MediaLoadRecovery {\n const client = useMediaClient();\n const recoverable = options?.recoverable !== false;\n const onTerminal = options?.onTerminal;\n const [result, setResult] = useState<{\n source: string | null;\n retryKey: number;\n failed: boolean;\n }>({ source: src, retryKey: 0, failed: false });\n const attemptRef = useRef(0);\n\n // A different URL deserves a fresh recovery allowance. The visible state is\n // keyed by source below, so this effect only resets the attempt counter.\n useEffect(() => {\n attemptRef.current = 0;\n }, [src]);\n\n const onLoadError = (event?: unknown) => {\n if (!src || !recoverable) {\n setResult({ source: src, retryKey: 0, failed: true });\n onTerminal?.(event);\n return;\n }\n attemptRef.current += 1;\n const attempt = attemptRef.current;\n // Re-branding is sound here: only resolution srcs reach the recoverable\n // lane (blob:/foreign URLs come in with `recoverable: false`).\n client.recoverLoadError(mintDurableSrc(src), attempt).then(\n (verdict) => {\n if (verdict === \"retry\") {\n setResult((current) => ({\n source: src,\n retryKey: current.source === src ? current.retryKey + 1 : 1,\n failed: false,\n }));\n } else {\n setResult({ source: src, retryKey: 0, failed: true });\n onTerminal?.(event);\n }\n },\n () => {\n setResult({ source: src, retryKey: 0, failed: true });\n onTerminal?.(event);\n },\n );\n };\n\n return {\n retryKey: result.source === src ? result.retryKey : 0,\n onLoadError,\n failed: result.source === src ? result.failed : false,\n };\n}\n","/**\n * @ai-matrx/media — the root types: the MediaClient port and the host ports.\n *\n * The package renders Matrx durable media; it NEVER talks to a network.\n * Everything data-shaped arrives through the injected {@link MediaClient}\n * (canonically implemented by `@ai-matrx/data/files`; any structural\n * implementation works — the strangler step wires it over an app's existing\n * file handler). The five file-handling laws are enforced here at the type\n * level:\n *\n * 1. Never fetch a media URL yourself — the package contains zero network\n * primitives; bytes exist only via {@link MediaClient.getBlob}.\n * 2. Off-boundary code resolves media itself — every component takes a\n * {@link MediaRefLike} and calls `resolve()` unconditionally. There is\n * NO `src` prop on any component in this package.\n * 3. A signed URL is a handoff, never an identity — the only string that\n * reaches a media element is the branded {@link DurableSrc}, which only\n * a MediaClient implementation can mint (via {@link mintDurableSrc}).\n * 4. Public-facing media is persisted public, never signed —\n * {@link MediaClient.shareableUrl} fails closed (`null` → the action\n * renders disabled).\n * 5. One URL contract; the engine builds URLs — zero URL construction in\n * this package; `resolve()` is the only door.\n */\n\n// ---------------------------------------------------------------------------\n// Identity\n// ---------------------------------------------------------------------------\n\n/** The canonical durable media reference. `file_id` is the identity. */\nexport interface MediaRef {\n file_id?: string | null;\n url?: string | null;\n mime_type?: string | null;\n metadata?: Record<string, unknown> | null;\n}\n\n/**\n * Identity in. A raw string is a fileId or an EXTERNAL public URL — never a\n * signed URL (the client's `resolve()` classifies and screams on one).\n */\nexport type MediaRefLike = MediaRef | string;\n\ndeclare const durable: unique symbol;\n\n/**\n * A URL that has passed through `MediaClient.resolve()` — the only string\n * type any media element in this package will bind. A caller cannot pass an\n * expiring URL through the package's types without an explicit unsafe cast.\n */\nexport type DurableSrc = string & { readonly [durable]: true };\n\n/**\n * Brand a URL as durable. FOR MediaClient IMPLEMENTATIONS ONLY — the\n * implementation must classify the URL first (the ONE signed-URL classifier\n * lives with the platform's files layer; never re-implement it here or in a\n * host). Calling this on an unclassified string defeats law 3.\n */\nexport function mintDurableSrc(url: string): DurableSrc {\n return url as DurableSrc;\n}\n\n// ---------------------------------------------------------------------------\n// Resolution\n// ---------------------------------------------------------------------------\n\nexport type MediaKind = \"image\" | \"video\" | \"audio\" | \"file\";\n\nexport interface MediaResolution {\n src: DurableSrc;\n /** RN auth lane (`<Image source={{uri, headers}}>`); absent on web (cookie session). */\n headers?: Record<string, string> | undefined;\n mimeType?: string | undefined;\n kind: MediaKind;\n /**\n * How pixels must travel. `\"element\"` (default): bind `src` directly to the\n * media element. `\"blob\"`: the bytes require bearer auth the element cannot\n * attach — consumers go through {@link MediaClient.getBlob} and render the\n * returned object URL (the private-image lane).\n */\n transport?: \"element\" | \"blob\" | undefined;\n /**\n * A server-rendered thumbnail for this file, when the client knows one\n * (Matrx: `FileRecord.thumbnail_url` / asset variants). Consumed by the\n * thumbnail tier machine.\n */\n thumbnailSrc?: DurableSrc | undefined;\n /**\n * True when this is a permanent public CDN URL — lets a host-supplied\n * `ImageComponent` (e.g. a next/image adapter) take the render, and marks\n * the URL CORS-safe for element-level `crossOrigin`.\n */\n isCdn?: boolean | undefined;\n /**\n * Whether a load error can be recovered by the client's ONE retry policy\n * (session-refresh → same-URL retry). False for foreign/external URLs —\n * a session refresh can't resurrect someone else's link rot. Default true.\n */\n recoverable?: boolean | undefined;\n}\n\n/** Typed unavailable states — render-as-state, never thrown as incidents. */\nexport type MediaUnavailableReason =\n | \"access_denied\"\n | \"not_found\"\n | \"deleted\"\n | \"unknown\";\n\n// ---------------------------------------------------------------------------\n// Bytes / upload\n// ---------------------------------------------------------------------------\n\nexport interface MediaBlobHandle {\n /** `blob:` object URL safe for any browser API. */\n url: string;\n blob: Blob;\n /** Release the handle. Implementations backed by a shared cache may no-op. */\n release(): void;\n}\n\nexport interface MediaUploadOptions {\n onProgress?: ((loaded: number, total: number) => void) | undefined;\n fileName?: string | undefined;\n mimeType?: string | undefined;\n /** Host visibility vocabulary passes through structurally. */\n visibility?: string | undefined;\n parentFolderId?: string | null | undefined;\n metadata?: Record<string, unknown> | undefined;\n}\n\n/** Upload → durable identity. `fileId` is required at compile time and runtime. */\nexport interface MediaUploadResult {\n fileId: string;\n ref: MediaRef;\n}\n\nexport interface MediaMultiUploadResult {\n /** File ids for every successful upload. */\n uploaded: string[];\n /** Per-file failure with the real backend error message. */\n failed: Array<{ name: string; error: string }>;\n /** True when the host's pre-flight (e.g. a duplicate dialog) cancelled the batch. */\n cancelled: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// THE port — one structural interface, owned by this package, implemented by\n// the data layer (canonically `@ai-matrx/data/files`).\n// ---------------------------------------------------------------------------\n\nexport interface MediaClient {\n /**\n * Synchronous durable-URL build + classification. Returns `null` when the\n * ref carries no usable identity (components render their fallback).\n * THROWS (and screams via its own diagnostics sink) on a signed/expiring\n * URL — the D108 guard lives behind this door.\n */\n resolve(ref: MediaRefLike): MediaResolution | null;\n /** Bytes for canvas/crossOrigin/private-pixel consumers. */\n getBlob(ref: MediaRefLike): Promise<MediaBlobHandle>;\n /**\n * Session bootstrap + the ONE retry policy: refresh-then-same-URL-retry,\n * second failure terminal. Called by the package's onError path, never\n * re-implemented.\n */\n recoverLoadError(src: DurableSrc, attempt: number): Promise<\"retry\" | \"terminal\">;\n /** Upload → durable identity. */\n upload(file: File | Blob, opts?: MediaUploadOptions): Promise<MediaUploadResult>;\n /**\n * Optional batch upload with host pre-flight (dedup dialogs etc.). When\n * absent, `useMediaUpload().uploadMany` falls back to sequential `upload`.\n */\n uploadMany?(files: File[], opts?: MediaUploadOptions): Promise<MediaMultiUploadResult>;\n /** Share affordances — fails closed (null), never emits a signed URL. */\n shareableUrl(ref: MediaRefLike): Promise<string | null>;\n /** Typed unavailable states — render-as-state, never thrown as incidents. */\n classifyError(err: unknown): MediaUnavailableReason;\n}\n\n// ---------------------------------------------------------------------------\n// Host ports — all optional, all defaulting to inert.\n// ---------------------------------------------------------------------------\n\n/**\n * Structural component slot. `(props) => unknown` keeps the root entry free\n * of React type imports; any React function component satisfies it.\n */\nexport type MediaSlotComponent<P> = (props: P) => unknown;\n\nexport interface MediaImageComponentProps {\n src: string;\n alt: string;\n width: number;\n height: number;\n className?: string | undefined;\n onError?: ((event: unknown) => void) | undefined;\n onClick?: ((event: unknown) => void) | undefined;\n onKeyDown?: ((event: unknown) => void) | undefined;\n role?: string | undefined;\n tabIndex?: number | undefined;\n}\n\nexport interface PlaybackSessionRegistration {\n isPlaying: boolean;\n source: string;\n label: string;\n trackKey?: string | undefined;\n}\n\n/**\n * The host's audio system (exclusive-playback lock, output-sink routing).\n * Both members are HOOKS — the package calls them unconditionally on every\n * render of a media element, so implementations must obey the Rules of Hooks\n * and the port object must be referentially stable.\n */\nexport interface PlaybackSessionPort {\n /**\n * Returns a ref callback for the underlying media element (routes audio\n * output / setSinkId on hosts that support it) and forwards to the caller's\n * own element ref.\n */\n useMediaElementSink(\n forward:\n | ((node: unknown) => void)\n | { current: unknown }\n | null\n | undefined,\n ): (node: unknown) => void;\n /** Joins the host's unified playback session for the element. */\n usePlaybackSession(\n registration: PlaybackSessionRegistration,\n elementRef: { current: unknown },\n ): void;\n}\n\n// ---------------------------------------------------------------------------\n// THE SHARE MANDATE (C19) — the complete headless media-actions contract.\n//\n// v0.1 ships this contract plus toolbar/lightbox shells wired to it, typed so\n// the associations/sharing package can plug in WITHOUT a media release: it\n// implements MediaActionsPort (handlers and/or the SharePopover body) and the\n// host injects it through MediaHostPorts. Nothing here may change shape in a\n// breaking way for that wave.\n// ---------------------------------------------------------------------------\n\nexport type MediaActionKind = \"share\" | \"download\" | \"copy\" | \"open\";\n\nexport interface MediaActionContext {\n ref: MediaRefLike;\n resolution: MediaResolution | null;\n fileName?: string | undefined;\n alt?: string | undefined;\n}\n\nexport interface MediaSharePopoverProps {\n context: MediaActionContext;\n onClose: () => void;\n}\n\nexport type MediaActionHandler = (ctx: MediaActionContext) => Promise<void>;\n\nexport interface MediaActionsPort {\n /**\n * Quick-share handler (copy a share link, open the native share sheet…).\n * Implementations obtain URLs ONLY via `MediaClient.shareableUrl` /\n * durable identities — never a signed URL (law 4).\n */\n share?: MediaActionHandler | undefined;\n download?: MediaActionHandler | undefined;\n copy?: MediaActionHandler | undefined;\n open?: MediaActionHandler | undefined;\n /**\n * Rich share UI body — the slot the associations package fills. When\n * present, the shells open it instead of (or on top of) the `share`\n * handler. Receives {@link MediaSharePopoverProps}.\n */\n SharePopover?: MediaSlotComponent<MediaSharePopoverProps> | undefined;\n}\n\nexport interface MediaHostPorts {\n playbackSession?: PlaybackSessionPort | undefined;\n actions?: MediaActionsPort | undefined;\n /** Web host may pass a next/image adapter; default is a plain `<img>`. */\n ImageComponent?: MediaSlotComponent<MediaImageComponentProps> | undefined;\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, never console.error'd here (the client owns loud recovery for\n * unexpected failures via its own diagnostics sink).\n */\n\nimport { useMemo } from \"react\";\nimport type {\n MediaRefLike,\n MediaResolution,\n MediaUnavailableReason,\n} from \"../types\";\nimport { useMediaClient } from \"./context\";\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 refKey = stableRefKey(ref);\n return useMemo<MediaResolutionState>(() => {\n if (!ref) return { resolution: null, status: \"empty\", reason: null };\n try {\n const resolution = client.resolve(ref);\n if (!resolution) return { resolution: null, status: \"empty\", reason: null };\n return { resolution, status: \"ready\", reason: null };\n } catch (err) {\n return {\n resolution: null,\n status: \"unavailable\",\n reason: client.classifyError(err),\n };\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, refKey]);\n}\n","/**\n * src/react/media-thumbnail.tsx — the single thumbnail renderer.\n *\n * Behavior port of matrx-frontend\n * `features/files/components/core/MediaThumbnail/MediaThumbnail.tsx` with\n * the tier machine inverted onto `/core`'s `useThumbnailSource` (the asset\n * variant lookup, public/private lanes and blob cache now live behind\n * `MediaClient.resolve` / `getBlob`):\n *\n * 1. server-rendered thumbnail (`thumbnailUrl` prop / resolution metadata)\n * 2. live source render — `<img>` for images, `<video preload=\"metadata\">`\n * poster frame for videos (the window between upload and variant render)\n * 3. category icon fallback\n *\n * Load failures self-heal through the client's ONE recovery policy before\n * falling to the icon — a user's own file never just \"expires\".\n */\n\n\"use client\";\n\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport type { MediaRefLike } from \"../types\";\nimport { useMediaLoadRecovery } from \"../core/use-media-load-recovery\";\nimport { useThumbnailSource } from \"../core/use-thumbnail-source\";\nimport { cn } from \"./cn\";\nimport { FileIcon } from \"./file-icon\";\n\nexport interface MediaThumbnailProps {\n /** The file's durable ref (a MediaRef or bare fileId). */\n mediaRef: MediaRefLike;\n /** Display name — drives the icon fallback and alt text. */\n fileName: string;\n /** Server MIME, when known. */\n mimeType?: string | null | undefined;\n /** A known server-rendered thumbnail URL (`FileRecord.thumbnail_url`). */\n thumbnailUrl?: string | null | undefined;\n /** Pixel size for the icon fallback. Image/video fill their container. */\n iconSize?: number | undefined;\n /** Aspect ratio classes applied to the container, e.g. \"aspect-[4/3]\". */\n className?: string | undefined;\n /** Override the rounded corners of the container. */\n rounded?: string | undefined;\n /**\n * Whether to fall back to a source-file URL when no rendered thumbnail is\n * available. Disable in dense pickers to avoid a byte request per row.\n */\n allowSourceFallback?: boolean | undefined;\n}\n\nexport function MediaThumbnail({\n mediaRef,\n fileName,\n mimeType = null,\n thumbnailUrl,\n iconSize = 48,\n className,\n rounded,\n allowSourceFallback = true,\n}: MediaThumbnailProps) {\n const source = useThumbnailSource(mediaRef, {\n thumbnailUrl,\n allowSourceFallback,\n });\n\n const fallback = (\n <div className=\"flex h-full w-full items-center justify-center bg-muted/40\">\n <FileIcon fileName={fileName} mimeType={mimeType} size={iconSize} />\n </div>\n );\n\n let body: ReactNode = source.loading ? (\n <div className=\"h-full w-full animate-pulse bg-muted\" />\n ) : (\n fallback\n );\n\n if (source.src) {\n if (source.mode === \"live-video-poster\") {\n body = (\n <VideoPosterThumb\n url={source.src}\n recoverable={source.recoverable}\n fallback={fallback}\n />\n );\n } else {\n body = (\n <ImageThumb\n url={source.src}\n alt={fileName}\n recoverable={source.recoverable}\n fallback={fallback}\n />\n );\n }\n }\n\n return (\n <div\n className={cn(\"relative overflow-hidden bg-muted/40\", rounded, className)}\n >\n {body}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\nfunction ImageThumb({\n url,\n alt,\n recoverable,\n fallback,\n}: {\n url: string;\n alt: string;\n recoverable: boolean;\n fallback: ReactNode;\n}) {\n // Media durability: a load failure routes through the client's ONE\n // recovery (session refresh → same durable URL) before falling to the\n // icon. Foreign/blob URLs pass through untouched.\n const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {\n recoverable,\n });\n\n if (failed) return <>{fallback}</>;\n return (\n <img\n key={retryKey}\n src={url}\n alt={alt}\n loading=\"lazy\"\n className=\"h-full w-full object-cover\"\n onError={onLoadError}\n />\n );\n}\n\nfunction VideoPosterThumb({\n url,\n recoverable,\n fallback,\n}: {\n url: string;\n recoverable: boolean;\n fallback: ReactNode;\n}) {\n // Same self-heal contract as ImageThumb.\n const { retryKey, onLoadError, failed } = useMediaLoadRecovery(url, {\n recoverable,\n });\n const ref = useRef<HTMLVideoElement | null>(null);\n\n // Some browsers refuse to render a frame until they explicitly know how to\n // seek. Setting `currentTime = 0` after metadata loads ensures the first\n // frame is decoded and displayed.\n useEffect(() => {\n const v = ref.current;\n if (!v) return undefined;\n const onMeta = () => {\n try {\n v.currentTime = 0;\n } catch {\n /* ignore — some streams don't support setting currentTime */\n }\n };\n v.addEventListener(\"loadedmetadata\", onMeta);\n return () => v.removeEventListener(\"loadedmetadata\", onMeta);\n }, []);\n\n if (failed) return <>{fallback}</>;\n return (\n <video\n key={retryKey}\n ref={ref}\n src={url}\n className=\"h-full w-full object-cover pointer-events-none\"\n preload=\"metadata\"\n muted\n playsInline\n onError={onLoadError}\n />\n );\n}\n\nexport default MediaThumbnail;\n","/**\n * src/core/use-thumbnail-source.ts — the thumbnail tier machine.\n *\n * Ported from matrx-frontend `MediaThumbnail.tsx`'s source-priority logic\n * with the data seams inverted onto the MediaClient:\n *\n * 1. Caller-supplied `thumbnailUrl` (`FileRecord.thumbnail_url`) —\n * CLASSIFIED through `resolve()` like every string (law 2), never\n * trusted raw.\n * 2. `resolution.thumbnailSrc` — the client's asset-variant lookup\n * (rides `MediaClient.resolve` metadata).\n * 3. Live source render — the master itself, `<img>` for images or\n * `<video preload=\"metadata\">` for a video poster frame; the private\n * bearer-auth lane (`transport: \"blob\"`) goes through `getBlob`.\n * 4. Icon fallback (`src: null`).\n */\n\nimport { useMemo } from \"react\";\nimport type { DurableSrc, MediaRefLike, MediaResolution } from \"../types\";\nimport { useMediaClient } from \"./context\";\nimport { useMediaBlob } from \"./use-media-blob\";\nimport { useMediaResolution } from \"./use-media-resolution\";\n\nexport type ThumbnailMode =\n | \"thumbnail\"\n | \"live-image\"\n | \"live-video-poster\"\n | \"icon\";\n\nexport interface ThumbnailSourceState {\n /** URL to render, or null → render the icon fallback. */\n src: DurableSrc | string | null;\n mode: ThumbnailMode;\n /** True while the private-pixels blob lane is still loading. */\n loading: boolean;\n resolution: MediaResolution | null;\n /** False for blob object URLs — wire into useMediaLoadRecovery. */\n recoverable: boolean;\n}\n\nexport interface UseThumbnailSourceOptions {\n /** A known server-rendered thumbnail URL (e.g. `FileRecord.thumbnail_url`). */\n thumbnailUrl?: string | null | undefined;\n /**\n * Whether to fall back to the source file itself when no rendered\n * thumbnail exists. Disable in dense pickers to avoid per-row byte loads.\n */\n allowSourceFallback?: boolean | undefined;\n}\n\nexport function useThumbnailSource(\n ref: MediaRefLike | null | undefined,\n options: UseThumbnailSourceOptions = {},\n): ThumbnailSourceState {\n const { thumbnailUrl, allowSourceFallback = true } = options;\n const client = useMediaClient();\n const { resolution } = useMediaResolution(ref);\n\n // Tier 1 — caller-supplied thumbnail URL, classified like everything else.\n const explicitThumb = useMemo(() => {\n if (!thumbnailUrl) return null;\n try {\n return client.resolve(thumbnailUrl);\n } catch {\n // A refused thumbnail URL (signed, foreign junk) falls to lower tiers.\n return null;\n }\n }, [client, thumbnailUrl]);\n\n // Tier 3 blob lane — only engaged when we would actually render the source.\n const needsBlob =\n allowSourceFallback &&\n !explicitThumb &&\n !resolution?.thumbnailSrc &&\n resolution?.transport === \"blob\";\n const blob = useMediaBlob(needsBlob ? ref : null);\n\n if (explicitThumb) {\n return {\n src: explicitThumb.src,\n mode: \"thumbnail\",\n loading: false,\n resolution,\n recoverable: explicitThumb.recoverable !== false,\n };\n }\n if (resolution?.thumbnailSrc) {\n return {\n src: resolution.thumbnailSrc,\n mode: \"thumbnail\",\n loading: false,\n resolution,\n recoverable: resolution.recoverable !== false,\n };\n }\n if (allowSourceFallback && resolution) {\n if (needsBlob) {\n return {\n src: blob.url,\n mode: blob.url\n ? resolution.kind === \"video\"\n ? \"live-video-poster\"\n : \"live-image\"\n : \"icon\",\n loading: blob.loading,\n resolution,\n recoverable: false,\n };\n }\n if (resolution.kind === \"image\") {\n return {\n src: resolution.src,\n mode: \"live-image\",\n loading: false,\n resolution,\n recoverable: resolution.recoverable !== false,\n };\n }\n if (resolution.kind === \"video\") {\n return {\n src: resolution.src,\n mode: \"live-video-poster\",\n loading: false,\n resolution,\n recoverable: resolution.recoverable !== false,\n };\n }\n }\n return {\n src: null,\n mode: \"icon\",\n loading: false,\n resolution,\n recoverable: false,\n };\n}\n","/**\n * src/react/use-media-dropzone.ts — headless drag + paste + picker intake.\n *\n * Replaces the original's `react-dropzone` dependency with native DOM events\n * (the package's `/react` entry carries no UI-library deps). The behavior\n * contract is the original FileUploadDropzone's: drag-over highlight, hidden\n * input picker (`openPicker`), clipboard paste of images with a brief\n * highlight pulse, an optional window event that opens the picker, and\n * accept/maxSize filtering (UI-only; the server enforces its own caps).\n */\n\n\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type DragEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n} from \"react\";\n\nexport interface MediaDropzoneOptions {\n /** Receives every accepted batch (drop, paste, or picker). */\n onFiles: (files: File[]) => void;\n /** Restrict accepted types, e.g. [\"image/*\", \"application/pdf\", \".csv\"]. */\n accept?: string[] | undefined;\n /** Max size per file in bytes (UI-only filter). */\n maxSize?: number | undefined;\n /** Fires for files filtered out by accept/maxSize. */\n onRejected?: ((rejected: Array<{ file: File; reason: \"type\" | \"size\" }>) => void) | undefined;\n /** Enable clipboard paste (images only). Defaults true. */\n enablePaste?: boolean | undefined;\n /** Optional window event name that opens the native file picker. */\n pickerEventName?: string | undefined;\n disabled?: boolean | undefined;\n multiple?: boolean | undefined;\n}\n\nexport interface MediaDropzoneState {\n /** Spread onto the drop surface element. */\n getRootProps: () => HTMLAttributes<HTMLElement>;\n /** Spread onto a hidden `<input type=\"file\">`. */\n getInputProps: () => InputHTMLAttributes<HTMLInputElement> & {\n ref: (node: HTMLInputElement | null) => void;\n };\n isDragActive: boolean;\n /** Brief pulse after a successful clipboard paste. */\n pasteHighlight: boolean;\n openPicker: () => void;\n}\n\nfunction matchesAccept(file: File, accept: string[] | undefined): boolean {\n if (!accept || accept.length === 0) return true;\n const name = file.name.toLowerCase();\n const mime = file.type.toLowerCase();\n return accept.some((pattern) => {\n const p = pattern.trim().toLowerCase();\n if (!p) return false;\n if (p.startsWith(\".\")) return name.endsWith(p);\n if (p.endsWith(\"/*\")) return mime.startsWith(p.slice(0, -1));\n return mime === p;\n });\n}\n\nexport function useMediaDropzone(options: MediaDropzoneOptions): MediaDropzoneState {\n const {\n onFiles,\n accept,\n maxSize,\n onRejected,\n enablePaste = true,\n pickerEventName,\n disabled = false,\n multiple = true,\n } = options;\n\n const [isDragActive, setIsDragActive] = useState(false);\n const [pasteHighlight, setPasteHighlight] = useState(false);\n const dragDepth = useRef(0);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Latest-callback refs so the window listeners never go stale.\n const onFilesRef = useRef(onFiles);\n onFilesRef.current = onFiles;\n const onRejectedRef = useRef(onRejected);\n onRejectedRef.current = onRejected;\n\n const acceptKey = accept?.join(\",\") ?? \"\";\n\n const filterFiles = useCallback(\n (files: File[]): File[] => {\n const accepted: File[] = [];\n const rejected: Array<{ file: File; reason: \"type\" | \"size\" }> = [];\n for (const file of files) {\n if (!matchesAccept(file, acceptKey ? acceptKey.split(\",\") : undefined)) {\n rejected.push({ file, reason: \"type\" });\n } else if (maxSize != null && file.size > maxSize) {\n rejected.push({ file, reason: \"size\" });\n } else {\n accepted.push(file);\n }\n }\n if (rejected.length) onRejectedRef.current?.(rejected);\n return accepted;\n },\n [acceptKey, maxSize],\n );\n\n const emit = useCallback(\n (files: File[]) => {\n const accepted = filterFiles(files);\n if (accepted.length) onFilesRef.current(accepted);\n },\n [filterFiles],\n );\n\n const openPicker = useCallback(() => {\n if (!disabled) inputRef.current?.click();\n }, [disabled]);\n\n // Optional window event that opens the native file picker.\n useEffect(() => {\n if (!pickerEventName || typeof window === \"undefined\") return undefined;\n const handler = () => openPicker();\n window.addEventListener(pickerEventName, handler);\n return () => window.removeEventListener(pickerEventName, handler);\n }, [openPicker, pickerEventName]);\n\n // Clipboard paste — images only (the original's contract).\n useEffect(() => {\n if (!enablePaste || disabled || typeof window === \"undefined\") {\n return undefined;\n }\n const handler = (event: ClipboardEvent) => {\n if (!event.clipboardData?.items) return;\n const images: File[] = [];\n for (const item of Array.from(event.clipboardData.items)) {\n if (item.type.startsWith(\"image/\")) {\n const blob = item.getAsFile();\n if (!blob) continue;\n const ext = blob.type.split(\"/\")[1] ?? \"png\";\n const name = `pasted-${Date.now()}.${ext}`;\n images.push(new File([blob], name, { type: blob.type }));\n }\n }\n if (images.length > 0) {\n event.preventDefault();\n setPasteHighlight(true);\n setTimeout(() => setPasteHighlight(false), 400);\n emit(images);\n }\n };\n window.addEventListener(\"paste\", handler);\n return () => window.removeEventListener(\"paste\", handler);\n }, [enablePaste, disabled, emit]);\n\n const getRootProps = useCallback(\n (): HTMLAttributes<HTMLElement> => ({\n onDragEnter: (event: DragEvent) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current += 1;\n setIsDragActive(true);\n },\n onDragOver: (event: DragEvent) => {\n if (disabled) return;\n event.preventDefault();\n },\n onDragLeave: (event: DragEvent) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current = Math.max(0, dragDepth.current - 1);\n if (dragDepth.current === 0) setIsDragActive(false);\n },\n onDrop: (event: DragEvent) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current = 0;\n setIsDragActive(false);\n const files = Array.from(event.dataTransfer?.files ?? []);\n if (files.length) emit(multiple ? files : files.slice(0, 1));\n },\n }),\n [disabled, emit, multiple],\n );\n\n const inputAccept = useMemo(\n () => (acceptKey.length ? acceptKey : undefined),\n [acceptKey],\n );\n\n const getInputProps = useCallback(\n () => ({\n ref: (node: HTMLInputElement | null) => {\n inputRef.current = node;\n },\n type: \"file\" as const,\n multiple,\n accept: inputAccept,\n tabIndex: -1,\n style: { display: \"none\" } as const,\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n const files = Array.from(event.target.files ?? []);\n // Allow re-selecting the same file.\n event.target.value = \"\";\n if (files.length) emit(files);\n },\n }),\n [emit, inputAccept, multiple],\n );\n\n return { getRootProps, getInputProps, isDragActive, pasteHighlight, openPicker };\n}\n","/**\n * src/react/file-upload-dropzone.tsx — drag + paste + picker uploader.\n *\n * Behavior port of matrx-frontend\n * `FileUploadDropzone/FileUploadDropzone.tsx` with the seams inverted:\n * `react-dropzone` → the package's own `useMediaDropzone`; the Redux\n * `selectVisibleUploads` tray → `useMediaUpload().entries`; the app-shaped\n * acquisition sources (Google Drive, local folder, \"choose existing\") → the\n * `actions` render slot. Renders as a full-surface overlay (`mode=\"overlay\"`)\n * or an inline block with visible affordance (`mode=\"inline\"`).\n */\n\n\"use client\";\n\nimport { useCallback, type ReactNode } from \"react\";\nimport type { MediaUploadOptions } from \"../types\";\nimport { useMediaUpload } from \"../core/use-media-upload\";\nimport { cn } from \"./cn\";\nimport { UploadIcon } from \"./icons\";\nimport { UploadProgressList } from \"./upload-progress-list\";\nimport { useMediaDropzone } from \"./use-media-dropzone\";\n\nexport interface FileUploadDropzoneActions {\n openLocalPicker: () => void;\n uploadFiles: (files: File[]) => Promise<void>;\n}\n\nexport interface FileUploadDropzoneProps {\n /** Upload options forwarded to the client (visibility, folder, metadata…). */\n uploadOptions?: MediaUploadOptions | undefined;\n /** Restrict accepted types (e.g. [\"image/*\"]). */\n accept?: string[] | undefined;\n /** Max size per file in bytes (UI-only; server enforces its own cap). */\n maxSize?: number | undefined;\n /** Enable paste from clipboard (images only). Defaults true. */\n enablePaste?: boolean | undefined;\n /** Rendering mode. */\n mode?: \"overlay\" | \"inline\" | undefined;\n /** Children render inside the drop surface. */\n children?:\n | ReactNode\n | ((actions: FileUploadDropzoneActions) => ReactNode)\n | undefined;\n className?: string | undefined;\n /** Host-shaped acquisition sources (Drive, local folder, existing files…). */\n actions?: ReactNode | undefined;\n /** Fires the moment an upload batch STARTS (before any network completes). */\n onUploadStart?: ((files: File[]) => void) | undefined;\n onUploaded?: ((fileIds: string[]) => void) | undefined;\n onError?: ((message: string) => void) | undefined;\n /** Reveal a finished file from the upload tray. */\n onOpenFile?: ((fileId: string) => void) | undefined;\n /** Optional window event name that opens the native file picker. */\n pickerEventName?: string | undefined;\n}\n\nexport function FileUploadDropzone({\n uploadOptions,\n accept,\n maxSize,\n enablePaste = true,\n mode = \"overlay\",\n children,\n className,\n actions,\n onUploadStart,\n onUploaded,\n onError,\n onOpenFile,\n pickerEventName,\n}: FileUploadDropzoneProps) {\n const { uploadMany, entries, clearEntry } = useMediaUpload();\n\n const handleUpload = useCallback(\n async (files: File[]) => {\n if (!files.length) return;\n try {\n onUploadStart?.(files);\n const { uploaded, failed } = await uploadMany(files, uploadOptions);\n if (uploaded.length && onUploaded) onUploaded(uploaded);\n if (failed.length && onError) {\n // Surface BOTH the file and the real backend reason — joining\n // objects rendered \"[object Object]\" to the user, hiding every\n // actual failure cause (CORS, 413, 401…).\n const message = failed.map((f) => `${f.name}: ${f.error}`).join(\"; \");\n onError(message);\n }\n } catch (err) {\n onError?.(err instanceof Error ? err.message : String(err));\n }\n },\n [uploadMany, uploadOptions, onUploadStart, onUploaded, onError],\n );\n\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n pasteHighlight,\n openPicker,\n } = useMediaDropzone({\n onFiles: (files) => void handleUpload(files),\n accept,\n maxSize,\n enablePaste,\n pickerEventName,\n });\n\n const highlighted = isDragActive || pasteHighlight;\n const renderedChildren =\n typeof children === \"function\"\n ? children({ openLocalPicker: openPicker, uploadFiles: handleUpload })\n : children;\n\n if (mode === \"inline\") {\n return (\n <div\n {...getRootProps()}\n className={cn(\n \"flex flex-col items-center justify-center gap-3 rounded-md border-2 border-dashed p-6\",\n \"text-sm text-muted-foreground\",\n highlighted ? \"border-primary bg-primary/5\" : \"border-border\",\n className,\n )}\n >\n <input {...getInputProps()} />\n <UploadIcon className=\"h-8 w-8\" width={32} height={32} aria-hidden=\"true\" />\n <div className=\"text-center\">\n <p>Drag & drop files here.</p>\n {enablePaste ? (\n <p className=\"text-xs mt-1 opacity-75\">\n You can also paste an image with ⌘V.\n </p>\n ) : null}\n </div>\n <button\n type=\"button\"\n onClick={openPicker}\n className=\"rounded-md border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent\"\n >\n Browse files\n </button>\n {actions}\n {entries.length > 0 ? (\n <UploadProgressList\n uploads={entries}\n onDismiss={clearEntry}\n onOpenFile={onOpenFile}\n className=\"w-full\"\n />\n ) : null}\n </div>\n );\n }\n\n return (\n <div\n {...getRootProps()}\n className={cn(\"relative h-full w-full\", className)}\n data-drop-active={highlighted ? \"true\" : undefined}\n >\n <input {...getInputProps()} />\n {renderedChildren}\n {highlighted ? (\n <div\n className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-md border-2 border-dashed border-primary bg-primary/10\"\n aria-live=\"polite\"\n >\n <div className=\"flex flex-col items-center gap-2 text-primary\">\n <UploadIcon className=\"h-10 w-10\" width={40} height={40} aria-hidden=\"true\" />\n <span className=\"font-medium\">Drop to upload</span>\n </div>\n </div>\n ) : null}\n {entries.length > 0 ? (\n <div className=\"absolute bottom-3 right-3 z-20 w-80 max-w-[90%]\">\n <UploadProgressList\n uploads={entries}\n onDismiss={clearEntry}\n onOpenFile={onOpenFile}\n />\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * src/core/use-media-upload.ts — the React-side upload primitive.\n *\n * Ported from matrx-frontend `handler/hooks/useFileUpload.ts` with two seam\n * inversions: the transport is `MediaClient.upload` (never touched directly),\n * and the multi-file pre-flight (SHA-256 dedup dialog) is the client's\n * optional `uploadMany` — when absent, the batch runs sequentially through\n * `upload` with per-file results.\n *\n * Additionally exposes a per-file `entries` tray state (name, size, bytes,\n * status) so the dropzone's UploadProgressList works without any app store —\n * the Redux `selectVisibleUploads` coupling of the original, inverted.\n */\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type {\n MediaMultiUploadResult,\n MediaUploadOptions,\n MediaUploadResult,\n} from \"../types\";\nimport { useMediaClient } from \"./context\";\n\nexport interface MediaUploadProgress {\n loaded: number;\n total: number;\n ratio: number;\n}\n\nexport type MediaUploadEntryStatus = \"uploading\" | \"success\" | \"error\";\n\nexport interface MediaUploadEntry {\n id: string;\n fileName: string;\n fileSize: number;\n bytesUploaded: number;\n status: MediaUploadEntryStatus;\n error: string | null;\n fileId: string | null;\n completedAt: number | null;\n}\n\nexport interface UseMediaUploadResult {\n /** Upload one file/blob. Returns the durable identity. */\n upload: (\n file: File | Blob,\n opts?: MediaUploadOptions,\n ) => Promise<MediaUploadResult>;\n /**\n * Upload many files. Uses the client's `uploadMany` (host pre-flight /\n * dedup dialog) when implemented; otherwise a sequential per-file loop with\n * real per-file error messages.\n */\n uploadMany: (\n files: File[],\n opts?: MediaUploadOptions,\n ) => Promise<MediaMultiUploadResult>;\n uploading: boolean;\n progress: MediaUploadProgress | null;\n result: MediaUploadResult | null;\n error: Error | null;\n /** Live per-file tray entries for progress UI. */\n entries: MediaUploadEntry[];\n clearEntry: (id: string) => void;\n reset: () => void;\n}\n\nlet entrySeq = 0;\n\nexport function useMediaUpload(): UseMediaUploadResult {\n const client = useMediaClient();\n const [uploading, setUploading] = useState(false);\n const [progress, setProgress] = useState<MediaUploadProgress | null>(null);\n const [result, setResult] = useState<MediaUploadResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [entries, setEntries] = useState<MediaUploadEntry[]>([]);\n const activeCount = useRef(0);\n\n const patchEntry = useCallback(\n (id: string, patch: Partial<MediaUploadEntry>) => {\n setEntries((current) =>\n current.map((e) => (e.id === id ? { ...e, ...patch } : e)),\n );\n },\n [],\n );\n\n const upload = useCallback(\n async (\n file: File | Blob,\n opts: MediaUploadOptions = {},\n ): Promise<MediaUploadResult> => {\n const id = `up-${++entrySeq}`;\n const fileName =\n opts.fileName ?? (file instanceof File ? file.name : \"file\");\n setEntries((current) => [\n ...current,\n {\n id,\n fileName,\n fileSize: file.size,\n bytesUploaded: 0,\n status: \"uploading\",\n error: null,\n fileId: null,\n completedAt: null,\n },\n ]);\n activeCount.current += 1;\n setUploading(true);\n setError(null);\n setProgress(null);\n try {\n const uploaded = await client.upload(file, {\n ...opts,\n onProgress: (loaded, total) => {\n setProgress({ loaded, total, ratio: total > 0 ? loaded / total : 0 });\n patchEntry(id, { bytesUploaded: loaded });\n opts.onProgress?.(loaded, total);\n },\n });\n setResult(uploaded);\n patchEntry(id, {\n status: \"success\",\n fileId: uploaded.fileId,\n bytesUploaded: file.size,\n completedAt: Date.now(),\n });\n return uploaded;\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n patchEntry(id, {\n status: \"error\",\n error: e.message,\n completedAt: Date.now(),\n });\n throw e;\n } finally {\n activeCount.current -= 1;\n if (activeCount.current <= 0) setUploading(false);\n }\n },\n [client, patchEntry],\n );\n\n const uploadMany = useCallback(\n async (\n files: File[],\n opts: MediaUploadOptions = {},\n ): Promise<MediaMultiUploadResult> => {\n if (client.uploadMany) {\n activeCount.current += 1;\n setUploading(true);\n try {\n return await client.uploadMany(files, opts);\n } finally {\n activeCount.current -= 1;\n if (activeCount.current <= 0) setUploading(false);\n }\n }\n const uploaded: string[] = [];\n const failed: Array<{ name: string; error: string }> = [];\n for (const file of files) {\n try {\n const one = await upload(file, opts);\n uploaded.push(one.fileId);\n } catch (err) {\n // Surface BOTH the file and the real backend reason — joining\n // objects rendered \"[object Object]\" to the user in the original.\n failed.push({\n name: file.name,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return { uploaded, failed, cancelled: false };\n },\n [client, upload],\n );\n\n const clearEntry = useCallback((id: string) => {\n setEntries((current) => current.filter((e) => e.id !== id));\n }, []);\n\n const reset = useCallback(() => {\n setResult(null);\n setError(null);\n setProgress(null);\n setEntries([]);\n }, []);\n\n return {\n upload,\n uploadMany,\n uploading,\n progress,\n result,\n error,\n entries,\n clearEntry,\n reset,\n };\n}\n","/**\n * src/react/upload-progress-list.tsx — the live upload tray.\n *\n * Verbatim behavior port of matrx-frontend\n * `FileUploadDropzone/UploadProgressList.tsx` with the Redux seams inverted:\n * entries come from `useMediaUpload().entries` (or any structurally equal\n * list) and dismissal is the injected `onDismiss` instead of a dispatched\n * `clearUpload`.\n *\n * Behavior: in-flight entries show a live progress bar + percentage;\n * successful entries persist with an \"Open\" affordance and auto-dismiss\n * after 10s — the timer pauses while the pointer is over the tray; failed\n * entries persist until manually dismissed.\n */\n\n\"use client\";\n\nimport { memo, useEffect, useRef, useState } from \"react\";\nimport type { MediaUploadEntry } from \"../core/use-media-upload\";\nimport { cn } from \"./cn\";\nimport { FileIcon } from \"./file-icon\";\nimport {\n AlertCircleIcon,\n CheckCircle2Icon,\n ExternalLinkIcon,\n XIcon,\n} from \"./icons\";\n\n/** How long a successful upload lingers in the tray before auto-dismissing. */\nconst AUTO_DISMISS_MS = 10_000;\n\nexport function formatFileSize(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return \"0 B\";\n if (bytes < 1024) return `${bytes} B`;\n const units = [\"KB\", \"MB\", \"GB\", \"TB\"] as const;\n let value = bytes;\n let unit = -1;\n do {\n value /= 1024;\n unit += 1;\n } while (value >= 1024 && unit < units.length - 1);\n return `${value >= 10 ? Math.round(value) : value.toFixed(1)} ${units[unit] ?? \"TB\"}`;\n}\n\nexport interface UploadProgressListProps {\n uploads: MediaUploadEntry[];\n /** Remove an entry from the tray (wire to `useMediaUpload().clearEntry`). */\n onDismiss: (id: string) => void;\n /**\n * Reveal a finished file — opens the preview pane / scrolls the row.\n * When omitted, the \"Open\" affordance is hidden.\n */\n onOpenFile?: ((fileId: string) => void) | undefined;\n className?: string | undefined;\n}\n\nfunction UploadProgressListImpl({\n uploads,\n onDismiss,\n onOpenFile,\n className,\n}: UploadProgressListProps) {\n const [hovered, setHovered] = useState(false);\n\n const activeCount = uploads.filter((u) => u.status === \"uploading\").length;\n const successCount = uploads.filter((u) => u.status === \"success\").length;\n const errorCount = uploads.filter((u) => u.status === \"error\").length;\n\n // Auto-dismiss successful entries. The timer is paused (cleared) while the\n // pointer is over the tray so a user reaching for \"Open\" is never cut off.\n const timersRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(\n new Map(),\n );\n const onDismissRef = useRef(onDismiss);\n onDismissRef.current = onDismiss;\n useEffect(() => {\n const timers = timersRef.current;\n if (hovered) {\n timers.forEach((t) => clearTimeout(t));\n timers.clear();\n return;\n }\n for (const u of uploads) {\n if (u.status !== \"success\") continue;\n if (timers.has(u.id)) continue;\n const elapsed = u.completedAt ? Date.now() - u.completedAt : 0;\n const remaining = Math.max(0, AUTO_DISMISS_MS - elapsed);\n const handle = setTimeout(() => {\n timers.delete(u.id);\n onDismissRef.current(u.id);\n }, remaining);\n timers.set(u.id, handle);\n }\n const liveSuccessIds = new Set(\n uploads.filter((u) => u.status === \"success\").map((u) => u.id),\n );\n for (const [id, handle] of timers) {\n if (!liveSuccessIds.has(id)) {\n clearTimeout(handle);\n timers.delete(id);\n }\n }\n }, [uploads, hovered]);\n\n useEffect(() => {\n const timers = timersRef.current;\n return () => {\n timers.forEach((t) => clearTimeout(t));\n timers.clear();\n };\n }, []);\n\n if (uploads.length === 0) return null;\n\n const headerLabel =\n activeCount > 0\n ? `Uploading ${activeCount} file${activeCount === 1 ? \"\" : \"s\"}…`\n : errorCount > 0 && successCount === 0\n ? `${errorCount} upload${errorCount === 1 ? \"\" : \"s\"} failed`\n : `Uploaded ${successCount} file${successCount === 1 ? \"\" : \"s\"}`;\n\n const completedIds = uploads\n .filter((u) => u.status === \"success\" || u.status === \"error\")\n .map((u) => u.id);\n\n return (\n <div\n className={cn(\n \"overflow-hidden rounded-lg border bg-background/95 shadow-lg backdrop-blur\",\n className,\n )}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n aria-label=\"Uploads\"\n >\n <div className=\"flex items-center justify-between gap-2 border-b bg-muted/40 px-3 py-1.5\">\n <span className=\"truncate text-xs font-medium text-foreground\">\n {headerLabel}\n </span>\n {completedIds.length > 0 ? (\n <button\n type=\"button\"\n onClick={() => {\n for (const id of completedIds) onDismiss(id);\n }}\n className=\"shrink-0 rounded px-1.5 py-0.5 text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n Clear\n </button>\n ) : null}\n </div>\n\n <ul className=\"max-h-72 space-y-1 overflow-y-auto p-2\">\n {uploads.map((u) => {\n const percent =\n u.fileSize > 0\n ? Math.min(100, Math.round((u.bytesUploaded / u.fileSize) * 100))\n : 0;\n const done = u.status === \"success\";\n const failed = u.status === \"error\";\n const canOpen = done && !!u.fileId && !!onOpenFile;\n return (\n <li\n key={u.id}\n className={cn(\n \"flex items-center gap-2 rounded-md px-2 py-1.5 text-xs\",\n canOpen && \"cursor-pointer hover:bg-accent/60\",\n )}\n onClick={\n canOpen ? () => onOpenFile(u.fileId as string) : undefined\n }\n >\n <FileIcon fileName={u.fileName} size={18} className=\"shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"truncate font-medium text-foreground\">\n {u.fileName}\n </span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {failed ? \"Failed\" : done ? \"Done\" : `${percent}%`}\n </span>\n </div>\n {done ? null : (\n <div className=\"mt-1 h-1 w-full rounded bg-muted\">\n <div\n className={cn(\n \"h-1 rounded transition-all\",\n failed ? \"bg-destructive\" : \"bg-primary\",\n )}\n style={{ width: failed ? \"100%\" : `${percent}%` }}\n />\n </div>\n )}\n {failed && u.error ? (\n <p className=\"mt-0.5 truncate text-[10px] text-destructive\">\n {u.error}\n </p>\n ) : !done ? (\n <p className=\"mt-0.5 text-[10px] text-muted-foreground\">\n {formatFileSize(u.bytesUploaded)} /{\" \"}\n {formatFileSize(u.fileSize)}\n </p>\n ) : null}\n </div>\n\n {canOpen ? (\n <span className=\"flex shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium text-primary\">\n <ExternalLinkIcon className=\"h-3 w-3\" width={12} height={12} />\n Open\n </span>\n ) : done ? (\n <CheckCircle2Icon\n className=\"h-4 w-4 shrink-0 text-emerald-500\"\n width={16}\n height={16}\n />\n ) : failed ? (\n <AlertCircleIcon\n className=\"h-4 w-4 shrink-0 text-destructive\"\n width={16}\n height={16}\n />\n ) : null}\n\n {done || failed ? (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onDismiss(u.id);\n }}\n aria-label=\"Dismiss\"\n className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground\"\n >\n <XIcon className=\"h-3 w-3\" width={12} height={12} />\n </button>\n ) : null}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nexport const UploadProgressList = memo(UploadProgressListImpl);\n","/**\n * src/react/media-action-toolbar.tsx — THE SHARE MANDATE's toolbar shell.\n *\n * A headless-driven action strip (share / download / copy / open) wired to\n * the host's injected {@link MediaActionsPort} through `useMediaActions`.\n * FAILS CLOSED: an action without a handler renders disabled (or hidden with\n * `hideUnavailable`); nothing here mints a URL.\n *\n * The share action opens the injected `SharePopover` body when the port\n * provides one (the slot the associations package fills — mandated wave),\n * otherwise it runs the port's quick `share` handler.\n */\n\n\"use client\";\n\nimport { useState, type ComponentType } from \"react\";\nimport type {\n MediaActionKind,\n MediaRefLike,\n MediaSharePopoverProps,\n} from \"../types\";\nimport { useMediaActions } from \"../core/use-media-actions\";\nimport { cn } from \"./cn\";\nimport {\n CopyIcon,\n DownloadIcon,\n ExternalLinkIcon,\n Share2Icon,\n type MediaIconProps,\n} from \"./icons\";\n\nconst ACTION_META: Record<\n MediaActionKind,\n { label: string; Icon: (props: MediaIconProps) => ReturnType<typeof CopyIcon> }\n> = {\n share: { label: \"Share\", Icon: Share2Icon },\n download: { label: \"Download\", Icon: DownloadIcon },\n copy: { label: \"Copy\", Icon: CopyIcon },\n open: { label: \"Open\", Icon: ExternalLinkIcon },\n};\n\nconst DEFAULT_ORDER: MediaActionKind[] = [\"share\", \"download\", \"copy\", \"open\"];\n\nexport interface MediaActionToolbarProps {\n mediaRef: MediaRefLike | null | undefined;\n fileName?: string | undefined;\n alt?: string | undefined;\n /** Which actions to render, in order. Default: share, download, copy, open. */\n actions?: MediaActionKind[] | undefined;\n /** Hide unavailable actions instead of rendering them disabled. */\n hideUnavailable?: boolean | undefined;\n className?: string | undefined;\n buttonClassName?: string | undefined;\n}\n\nexport function MediaActionToolbar({\n mediaRef,\n fileName,\n alt,\n actions = DEFAULT_ORDER,\n hideUnavailable = false,\n className,\n buttonClassName,\n}: MediaActionToolbarProps) {\n const state = useMediaActions(mediaRef, { fileName, alt });\n const [shareOpen, setShareOpen] = useState(false);\n\n const SharePopover = state.SharePopover as\n | ComponentType<MediaSharePopoverProps>\n | null;\n\n const visible = hideUnavailable\n ? actions.filter((kind) => state.isAvailable(kind))\n : actions;\n\n if (visible.length === 0) return null;\n\n return (\n <div className={cn(\"relative inline-flex items-center gap-1\", className)}>\n {visible.map((kind) => {\n const { label, Icon } = ACTION_META[kind];\n const available = state.isAvailable(kind);\n const busy = state.busy === kind;\n return (\n <button\n key={kind}\n type=\"button\"\n aria-label={label}\n title={label}\n disabled={!available || busy}\n onClick={() => {\n if (kind === \"share\" && SharePopover) {\n setShareOpen((open) => !open);\n return;\n }\n void state.run(kind);\n }}\n className={cn(\n \"inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors\",\n available\n ? \"hover:bg-accent hover:text-foreground\"\n : \"opacity-40 cursor-not-allowed\",\n busy && \"animate-pulse\",\n buttonClassName,\n )}\n >\n <Icon className=\"h-4 w-4\" width={16} height={16} />\n </button>\n );\n })}\n {state.lastError ? (\n <span\n role=\"status\"\n className=\"ml-1 max-w-48 truncate text-[11px] text-destructive\"\n title={state.lastError.message}\n >\n {ACTION_META[state.lastError.kind].label} failed\n </span>\n ) : null}\n {shareOpen && SharePopover && state.context ? (\n <div className=\"absolute right-0 top-full z-30 mt-1\">\n <SharePopover\n context={state.context}\n onClose={() => setShareOpen(false)}\n />\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * src/core/use-media-actions.ts — THE SHARE MANDATE's headless engine.\n *\n * Wires a MediaRefLike to the host's injected {@link MediaActionsPort}\n * (share / download / copy / open + the SharePopover slot the associations\n * package fills). FAILS CLOSED: with no port — or no handler for a given\n * action — the action reports unavailable and the shells render it disabled.\n * Nothing here mints URLs; handlers reach bytes/links only through the\n * MediaClient they close over.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type {\n MediaActionContext,\n MediaActionKind,\n MediaRefLike,\n MediaSharePopoverProps,\n MediaSlotComponent,\n} from \"../types\";\nimport { useMediaHostPorts } from \"./context\";\nimport { useMediaResolution } from \"./use-media-resolution\";\n\nexport interface UseMediaActionsOptions {\n fileName?: string | undefined;\n alt?: string | undefined;\n}\n\nexport interface MediaActionsState {\n /** Null when no ref was supplied. */\n context: MediaActionContext | null;\n /** True when the host wired a handler for this action (share also counts the popover). */\n isAvailable: (kind: MediaActionKind) => boolean;\n /** Run an action. No-op (resolved) when unavailable. */\n run: (kind: MediaActionKind) => Promise<void>;\n /** The action currently executing, or null. */\n busy: MediaActionKind | null;\n /** Last handler failure, surfaced as state for the shell to render. */\n lastError: { kind: MediaActionKind; message: string } | null;\n /** The rich share body slot (associations package), when injected. */\n SharePopover: MediaSlotComponent<MediaSharePopoverProps> | null;\n}\n\nexport function useMediaActions(\n ref: MediaRefLike | null | undefined,\n options: UseMediaActionsOptions = {},\n): MediaActionsState {\n const ports = useMediaHostPorts();\n const { resolution } = useMediaResolution(ref);\n const [busy, setBusy] = useState<MediaActionKind | null>(null);\n const [lastError, setLastError] = useState<{\n kind: MediaActionKind;\n message: string;\n } | null>(null);\n\n const actions = ports.actions;\n const { fileName, alt } = options;\n\n const context = useMemo<MediaActionContext | null>(() => {\n if (!ref) return null;\n return { ref, resolution, fileName, alt };\n }, [ref, resolution, fileName, alt]);\n\n const isAvailable = useCallback(\n (kind: MediaActionKind): boolean => {\n if (!context || !actions) return false;\n if (kind === \"share\") return Boolean(actions.share || actions.SharePopover);\n return Boolean(actions[kind]);\n },\n [context, actions],\n );\n\n const run = useCallback(\n async (kind: MediaActionKind): Promise<void> => {\n if (!context || !actions) return;\n const handler = actions[kind];\n if (!handler) return;\n setBusy(kind);\n setLastError(null);\n try {\n await handler(context);\n } catch (err) {\n setLastError({\n kind,\n message: err instanceof Error ? err.message : String(err),\n });\n } finally {\n setBusy(null);\n }\n },\n [context, actions],\n );\n\n return {\n context,\n isAvailable,\n run,\n busy,\n lastError,\n SharePopover: actions?.SharePopover ?? null,\n };\n}\n","/**\n * src/react/media-lightbox.tsx — THE SHARE MANDATE's lightbox shell.\n *\n * Full-viewport media viewer: backdrop, Escape/backdrop-click close, the\n * media rendered through `InlineMediaRef` (durable refs only — no `src`\n * lane exists), and the `MediaActionToolbar` wired to the host's injected\n * actions port. The rich share body arrives through the same\n * `SharePopover` slot (associations package — mandated wave); until a host\n * injects handlers, every action renders disabled (fails closed).\n */\n\n\"use client\";\n\nimport { useEffect, type ReactNode } from \"react\";\nimport type { MediaActionKind, MediaRefLike } from \"../types\";\nimport { cn } from \"./cn\";\nimport { InlineMediaRef } from \"./inline-media-ref\";\nimport { MediaActionToolbar } from \"./media-action-toolbar\";\nimport { XIcon } from \"./icons\";\n\nexport interface MediaLightboxProps {\n open: boolean;\n onClose: () => void;\n mediaRef: MediaRefLike | null | undefined;\n fileName?: string | undefined;\n alt?: string | undefined;\n /** Force the media element type (default: inferred from the resolution). */\n as?: \"img\" | \"video\" | \"audio\" | undefined;\n /** Toolbar actions to offer. Default: share, download, copy, open. */\n actions?: MediaActionKind[] | undefined;\n /** Hide unavailable toolbar actions instead of disabling them. */\n hideUnavailableActions?: boolean | undefined;\n /** Extra chrome rendered in the header row (left of the toolbar). */\n headerExtra?: ReactNode | undefined;\n className?: string | undefined;\n}\n\nexport function MediaLightbox({\n open,\n onClose,\n mediaRef,\n fileName,\n alt,\n as,\n actions,\n hideUnavailableActions = false,\n headerExtra,\n className,\n}: MediaLightboxProps) {\n useEffect(() => {\n if (!open || typeof window === \"undefined\") return undefined;\n const handler = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n onClose();\n }\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [open, onClose]);\n\n if (!open) return null;\n\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={fileName ?? alt ?? \"Media viewer\"}\n className={cn(\n \"fixed inset-0 z-50 flex flex-col bg-black/80 backdrop-blur-sm\",\n className,\n )}\n onClick={onClose}\n >\n <div\n className=\"flex items-center justify-between gap-2 p-3\"\n onClick={(event) => event.stopPropagation()}\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"truncate text-sm font-medium text-white/90\">\n {fileName ?? alt ?? \"\"}\n </span>\n {headerExtra}\n </div>\n <div className=\"flex items-center gap-1\">\n <MediaActionToolbar\n mediaRef={mediaRef}\n fileName={fileName}\n alt={alt}\n actions={actions}\n hideUnavailable={hideUnavailableActions}\n buttonClassName=\"text-white/80 hover:bg-white/10 hover:text-white\"\n />\n <button\n type=\"button\"\n aria-label=\"Close\"\n onClick={onClose}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-white/80 transition-colors hover:bg-white/10 hover:text-white\"\n >\n <XIcon className=\"h-4 w-4\" width={16} height={16} />\n </button>\n </div>\n </div>\n <div\n className=\"flex min-h-0 flex-1 items-center justify-center p-4\"\n onClick={(event) => event.stopPropagation()}\n >\n <div className=\"h-full w-full\">\n <InlineMediaRef\n ref={mediaRef}\n size=\"fill\"\n fit=\"contain\"\n rounded=\"none\"\n alt={alt ?? fileName ?? \"\"}\n as={as}\n />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","FileIcon","useMemo","useRef","useState","useEffect","useState","useState","useEffect","jsx","jsxs","useState","useRef","useMemo","useEffect","useRef","useMemo","useMemo","Fragment","jsx","FileIcon","useRef","useEffect","useCallback","useEffect","useMemo","useRef","useState","useCallback","useCallback","useRef","useState","useState","useRef","useCallback","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","FileIcon","jsx","jsxs","useCallback","useState","useCallback","useMemo","useState","useState","useMemo","useCallback","jsx","jsxs","useState","useEffect","jsx","jsxs","useEffect"]}
|