/** * Responsive-media intent — Save-Data / DPR / Client Hints projection (#125). * * Pure resolution and srcset/image-set builders. Hosts inject capabilities from * `@czap/edge` `ClientHints` or `@czap/detect`; core stays dependency-free. * * @module */ /** Capability slice required to resolve a responsive media intent. */ export interface ResponsiveMediaCapabilities { readonly devicePixelRatio: number; readonly saveData: boolean; } /** One candidate source in a responsive set. */ export interface ResponsiveMediaVariant { readonly src: string; /** Intrinsic width in CSS pixels — used for `Nw` descriptors. */ readonly width?: number; /** Explicit density descriptor (e.g. `2x`); overrides width-based DPR inference. */ readonly descriptor?: string; } /** Authoring input to {@link ResponsiveMedia.intent}. */ export interface ResponsiveMediaIntentInput { readonly id: string; readonly alt: string; readonly variants: readonly ResponsiveMediaVariant[]; /** Lighter asset used when Save-Data is on. */ readonly saveDataVariant?: ResponsiveMediaVariant; readonly sizes?: string; } /** Sealed responsive-media intent — data over graph, no behavior authority. */ export interface ResponsiveMediaIntent extends ResponsiveMediaIntentInput { readonly _tag: 'ResponsiveMediaIntent'; } /** Why a particular variant was chosen. */ export type ResponsiveMediaResolutionReason = 'save-data' | 'save-data-floor' | 'dpr-match' | 'dpr-floor' | 'fallback'; /** Resolved single source for SSR or runtime ``. */ export interface ResolvedResponsiveMedia { readonly src: string; readonly reason: ResponsiveMediaResolutionReason; } /** * The EFFECTIVE candidate set — the single law every responsive-media output derives * from ({@link selectCandidates}). Under `caps.saveData` the set is capped to the ONE * light/floor variant, so no artifact (`srcset`, ``, the preload `imagesrcset`, * CSS `image-set()`, the cache-key digest) can ever advertise a heavier candidate — the * browser cannot re-fetch what no output lists (F-RM-1a..e). */ export interface ResponsiveMediaCandidateSet { /** * The candidates safe to advertise under `caps`. Save-Data caps this to a single * light/floor variant; otherwise it is the full authored set. `srcset`, the general * ``, the preload `imagesrcset`, and CSS `image-set()` all enumerate THIS. */ readonly candidates: readonly ResponsiveMediaVariant[]; /** The single best variant for `` — the DPR pick WITHIN `candidates`. */ readonly resolved: ResponsiveMediaVariant; /** Why `resolved` was chosen and how `candidates` was capped. */ readonly reason: ResponsiveMediaResolutionReason; } /** Structured `` projection. */ export interface ResponsiveMediaPictureProjection { readonly picture: string; readonly img: string; readonly srcset: string; readonly sizes: string; readonly resolved: ResolvedResponsiveMedia; /** * Optional `` for the resolved (or full srcset) * asset — hosts put this in `` for LCP (#125). */ readonly preload: string; } /** * Build a `srcset` string from variants with `w` or `x` descriptors. * * Variants without enough metadata are skipped; result is empty when none qualify. */ export declare function buildResponsiveSrcset(variants: readonly ResponsiveMediaVariant[], baseWidth?: number): string; /** * Build a CSS `image-set()` value from variants (native CSS first). * * Uses `type()` only when variants carry standard image extensions; unknown * types are omitted rather than guessed. */ export declare function buildResponsiveImageSet(variants: readonly ResponsiveMediaVariant[], baseWidth?: number): string; /** * THE one effective-candidate law — the single function every responsive-media * output consumes (#140). Returns the {@link ResponsiveMediaCandidateSet}: the * candidates safe to advertise under `caps`, the single best `src`, and the reason. * * Save-Data wins over DPR and caps ALL candidates to the floor: the authored * `saveDataVariant` when present (`save-data`), else the LIGHTEST available variant * (`save-data-floor`) — a Save-Data client must never be advertised a heavier * candidate through ANY artifact, even when the author skipped the explicit light * variant. Otherwise the full authored set is advertised and `resolved` is the DPR * pick: the variant whose DPR is closest without going under the device ratio * (`dpr-match`), else the largest available (`dpr-floor`), else the first (`fallback`). */ export declare function selectCandidates(intent: ResponsiveMediaIntent, caps: ResponsiveMediaCapabilities): ResponsiveMediaCandidateSet; /** * Resolve the single best `src` for SSR / fallback `` given capabilities. * * A thin projection of {@link selectCandidates}: takes its `resolved` variant and * `reason`. Kept as its own export for hosts that only need the one `src` — but it * derives from the SAME law as `srcset` / `` / preload / image-set, so a * Save-Data client is never SILENTLY served a light `src` while a heavy candidate * leaks through another artifact. */ export declare function resolveResponsiveMedia(intent: ResponsiveMediaIntent, caps: ResponsiveMediaCapabilities): ResolvedResponsiveMedia; /** * Project a responsive-media intent to a `` + fallback ``. * * Native markup first: `` per density band; runtime/SSR picks * `resolved.src` on the inner `` for hosts without picture support. */ export declare function projectResponsiveMediaPicture(intent: ResponsiveMediaIntent, caps: ResponsiveMediaCapabilities): ResponsiveMediaPictureProjection; /** Authoring sugar namespace — data over intent, no behavior authority. */ export declare const ResponsiveMedia: { /** Seal a responsive-media intent from authoring input. */ readonly intent: (input: ResponsiveMediaIntentInput) => ResponsiveMediaIntent; }; //# sourceMappingURL=responsive-media.d.ts.map