{"version":3,"file":"index.mjs","names":[],"sources":["../../src/media/types.ts","../../src/media/local.ts"],"sourcesContent":["/**\n * Media Provider Types\n *\n * Media providers are pluggable sources for browsing, uploading, and embedding media.\n * They enable integration with external services (Unsplash, Cloudinary, Mux, etc.)\n * alongside the built-in local media library.\n */\n\n/**\n * Serializable media provider configuration descriptor\n * Returned by provider config functions (e.g., unsplash(), mux())\n */\nexport interface MediaProviderDescriptor<TConfig = Record<string, unknown>> {\n\t/** Unique identifier, used in MediaValue.provider */\n\tid: string;\n\n\t/** Display name for admin UI */\n\tname: string;\n\n\t/** Icon for tab UI (emoji or URL) */\n\ticon?: string;\n\n\t/** Module path exporting createMediaProvider function */\n\tentrypoint: string;\n\n\t/** Optional React component module for custom admin UI */\n\tadminModule?: string;\n\n\t/** Capability flags determine UI behavior */\n\tcapabilities: MediaProviderCapabilities;\n\n\t/** Serializable config passed to createMediaProvider at runtime */\n\tconfig: TConfig;\n}\n\n/**\n * Provider capabilities determine what UI elements to show\n */\nexport interface MediaProviderCapabilities {\n\t/** Can list/browse media */\n\tbrowse: boolean;\n\t/** Supports text search */\n\tsearch: boolean;\n\t/** Can upload new media */\n\tupload: boolean;\n\t/** Can delete media */\n\tdelete: boolean;\n}\n\n/**\n * Options for listing media\n */\nexport interface MediaListOptions {\n\t/** Pagination cursor */\n\tcursor?: string;\n\t/** Max items to return (default 20) */\n\tlimit?: number;\n\t/** Search query (if capabilities.search is true) */\n\tquery?: string;\n\t/** Filter by MIME type prefix, e.g., \"image/\", \"video/\" */\n\tmimeType?: string;\n}\n\n/**\n * Result from listing media\n */\nexport interface MediaListResult {\n\titems: MediaProviderItem[];\n\tnextCursor?: string;\n}\n\n/**\n * A media item as returned by a provider\n * This is the provider's view of the item, before it's selected\n */\nexport interface MediaProviderItem {\n\t/** Provider-specific ID */\n\tid: string;\n\t/** Original filename */\n\tfilename: string;\n\t/** MIME type */\n\tmimeType: string;\n\t/** File size in bytes (if known) */\n\tsize?: number;\n\t/** Dimensions (for images/video) */\n\twidth?: number;\n\theight?: number;\n\t/** LQIP blurhash placeholder (images only) */\n\tblurhash?: string;\n\t/** LQIP dominant-color placeholder, as a CSS color (images only) */\n\tdominantColor?: string;\n\t/** Accessibility text */\n\talt?: string;\n\t/** Preview URL for admin UI thumbnail */\n\tpreviewUrl?: string;\n\t/** Provider-specific metadata */\n\tmeta?: Record<string, unknown>;\n}\n\n/**\n * Input for uploading media\n */\nexport interface MediaUploadInput {\n\tfile: File;\n\tfilename: string;\n\talt?: string;\n}\n\n/**\n * Options for generating embed\n */\nexport interface EmbedOptions {\n\t/** Desired width (provider may use for optimization) */\n\twidth?: number;\n\t/** Desired height */\n\theight?: number;\n\t/** Image format preference */\n\tformat?: \"webp\" | \"avif\" | \"jpeg\" | \"png\" | \"auto\";\n}\n\n/**\n * Embed result types\n */\nexport type EmbedResult = ImageEmbed | VideoEmbed | AudioEmbed | ComponentEmbed;\n\nexport interface ImageEmbed {\n\ttype: \"image\";\n\tsrc: string;\n\tsrcset?: string;\n\tsizes?: string;\n\twidth?: number;\n\theight?: number;\n\t/** LQIP blurhash placeholder for rendering before the image loads */\n\tblurhash?: string;\n\t/** LQIP dominant-color placeholder, as a CSS color */\n\tdominantColor?: string;\n\talt?: string;\n\t/** Base URL without transforms, for responsive image generation */\n\tcdnBaseUrl?: string;\n\t/** For providers with URL-based transforms (Cloudinary, imgix) */\n\tgetSrc?: (opts: { width?: number; height?: number; format?: string }) => string;\n}\n\nexport interface VideoEmbed {\n\ttype: \"video\";\n\t/** Single source URL */\n\tsrc?: string;\n\t/** Multiple sources for format fallback */\n\tsources?: Array<{ src: string; type: string }>;\n\t/** Poster/thumbnail image */\n\tposter?: string;\n\twidth?: number;\n\theight?: number;\n\t/** Player controls */\n\tcontrols?: boolean;\n\tautoplay?: boolean;\n\tmuted?: boolean;\n\tloop?: boolean;\n\tplaysinline?: boolean;\n\tpreload?: \"none\" | \"metadata\" | \"auto\";\n\tcrossorigin?: \"anonymous\" | \"use-credentials\";\n}\n\nexport interface AudioEmbed {\n\ttype: \"audio\";\n\tsrc?: string;\n\tsources?: Array<{ src: string; type: string }>;\n\tcontrols?: boolean;\n\tautoplay?: boolean;\n\tmuted?: boolean;\n\tloop?: boolean;\n\tpreload?: \"none\" | \"metadata\" | \"auto\";\n}\n\nexport interface ComponentEmbed {\n\ttype: \"component\";\n\t/** Package to import from, e.g., \"@mux/player-react\" */\n\tpackage: string;\n\t/** Named export (default export if not specified) */\n\texport?: string;\n\t/** Props to pass to the component */\n\tprops: Record<string, unknown>;\n}\n\n/**\n * Options for thumbnail generation\n */\nexport interface ThumbnailOptions {\n\t/** Desired width */\n\twidth?: number;\n\t/** Desired height */\n\theight?: number;\n}\n\n/**\n * Runtime media provider interface\n * Implemented by provider entrypoints\n */\nexport interface MediaProvider {\n\t/**\n\t * List/search media items\n\t */\n\tlist(options: MediaListOptions): Promise<MediaListResult>;\n\n\t/**\n\t * Get a single item by ID (optional, for refresh/validation)\n\t */\n\tget?(id: string): Promise<MediaProviderItem | null>;\n\n\t/**\n\t * Upload new media (if capabilities.upload is true)\n\t */\n\tupload?(input: MediaUploadInput): Promise<MediaProviderItem>;\n\n\t/**\n\t * Delete media (if capabilities.delete is true)\n\t */\n\tdelete?(id: string): Promise<void>;\n\n\t/**\n\t * Get embed information for rendering this media item\n\t * Called at runtime when rendering content\n\t */\n\tgetEmbed(value: MediaValue, options?: EmbedOptions): Promise<EmbedResult> | EmbedResult;\n\n\t/**\n\t * Get a thumbnail URL for admin display\n\t * For images: returns a resized image URL\n\t * For videos: returns a poster/thumbnail URL\n\t */\n\tgetThumbnailUrl?(id: string, mimeType?: string, options?: ThumbnailOptions): string;\n}\n\n/**\n * Function signature for provider entrypoint modules\n */\nexport type CreateMediaProviderFn<TConfig = Record<string, unknown>> = (\n\tconfig: TConfig,\n) => MediaProvider;\n\n/**\n * Media value stored in content fields\n * This is what gets persisted when media is selected\n *\n * For backwards compatibility:\n * - `provider` defaults to \"local\" if not specified\n * - `src` is supported for legacy data or external URLs\n */\nexport interface MediaValue {\n\t/** Provider ID, e.g., \"local\", \"unsplash\", \"mux\" (defaults to \"local\") */\n\tprovider?: string;\n\n\t/** Provider-specific item ID */\n\tid: string;\n\n\t/** Direct URL (for local media or legacy data) */\n\tsrc?: string;\n\n\t/** Preview URL for admin display (external providers) */\n\tpreviewUrl?: string;\n\n\t/** Cached metadata for display without runtime lookup */\n\tfilename?: string;\n\tmimeType?: string;\n\twidth?: number;\n\theight?: number;\n\t/** Cached LQIP blurhash placeholder (images only) */\n\tblurhash?: string;\n\t/** Cached LQIP dominant-color placeholder, as a CSS color (images only) */\n\tdominantColor?: string;\n\talt?: string;\n\n\t/** Provider-specific data needed for embedding */\n\tmeta?: Record<string, unknown>;\n}\n\n/**\n * Convert a MediaProviderItem to a MediaValue for storage\n */\nexport function mediaItemToValue(providerId: string, item: MediaProviderItem): MediaValue {\n\treturn {\n\t\tprovider: providerId,\n\t\tid: item.id,\n\t\tfilename: item.filename,\n\t\tmimeType: item.mimeType,\n\t\twidth: item.width,\n\t\theight: item.height,\n\t\tblurhash: item.blurhash,\n\t\tdominantColor: item.dominantColor,\n\t\talt: item.alt,\n\t\tmeta: item.meta,\n\t};\n}\n","/**\n * Local Media Provider\n *\n * The built-in media provider that wraps the current storage adapter and media database.\n * This is the default provider and is available unless explicitly disabled.\n */\n\nimport type { MediaProviderDescriptor } from \"./types.js\";\n\nexport interface LocalMediaConfig {\n\t/** Whether the local provider is enabled (default true) */\n\tenabled?: boolean;\n}\n\n/**\n * Local media provider configuration\n *\n * @example\n * ```ts\n * import { localMedia } from \"@premium-cms/emdash/media\";\n *\n * emdash({\n *   mediaProviders: [\n *     localMedia(), // Uses defaults\n *     // or: localMedia({ enabled: false }) to disable\n *   ],\n * })\n * ```\n */\nexport function localMedia(config: LocalMediaConfig = {}): MediaProviderDescriptor {\n\treturn {\n\t\tid: \"local\",\n\t\tname: \"Library\",\n\t\ticon: \"📁\",\n\t\tentrypoint: \"@premium-cms/emdash/media/local-runtime\",\n\t\tcapabilities: {\n\t\t\tbrowse: true,\n\t\t\tsearch: false, // TODO: Add search support\n\t\t\tupload: true,\n\t\t\tdelete: true,\n\t\t},\n\t\tconfig: {\n\t\t\tenabled: config.enabled ?? true,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;AAuRA,SAAgB,iBAAiB,YAAoB,MAAqC;AACzF,QAAO;EACN,UAAU;EACV,IAAI,KAAK;EACT,UAAU,KAAK;EACf,UAAU,KAAK;EACf,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,eAAe,KAAK;EACpB,KAAK,KAAK;EACV,MAAM,KAAK;EACX;;;;;;;;;;;;;;;;;;;;ACtQF,SAAgB,WAAW,SAA2B,EAAE,EAA2B;AAClF,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM;EACN,YAAY;EACZ,cAAc;GACb,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR,QAAQ;GACR;EACD,QAAQ,EACP,SAAS,OAAO,WAAW,MAC3B;EACD"}