import type { DesignDocument, DocumentMatrix, DocumentDiagnostic, DocumentDuplicateMetadataRemapper, DocumentNode, DocumentTransaction, DocumentValue } from './contracts.js'; import { type ImagePaintBox } from './imagePaintGeometry.js'; /** * Asset store of a design document. Images and SVG sources live under * `document.metadata.assets` as plain JSON so a saved document is * self-contained; nodes reference them by id through an image paint * (`{ type: 'image', assetId, scaleMode }` inside `properties.paints`) or, * for editable SVG imports, through `properties.sourceAssetId` on the * imported root. * * Ids are content-addressed (`asset:` + the first 24 hex digits of the * SHA-256 of the bytes), so importing the same file twice stores it once and * pasting between documents merges by id without renaming references. All * functions here are pure and free of DOM access; hashing and dimension * probing work on bytes. */ export declare const ASSETS_METADATA_KEY = "assets"; export declare const ASSET_STORE_VERSION = 1; export declare const IMAGE_MEDIA_TYPES: readonly ["image/png", "image/jpeg", "image/gif", "image/webp"]; export declare const IMAGE_SCALE_MODES: readonly ["fill", "fit", "crop", "tile"]; export declare const IMAGE_SCALE_MODE_LABELS: Readonly>; /** Placement default: an image larger than this is scaled down to fit when placed as a layer. */ export declare const IMAGE_PLACEMENT_MAX = 800; export type ImageMediaType = (typeof IMAGE_MEDIA_TYPES)[number]; export type ImageScaleMode = (typeof IMAGE_SCALE_MODES)[number]; export type ImageAssetSource = { type: 'data'; base64: string; } | { type: 'reference'; url: string; }; export interface ImageAsset { kind: 'image'; id: string; name: string; mediaType: ImageMediaType; width: number; height: number; /** SHA-256 of the encoded bytes, lowercase hex. Reference sources carry the hash the host supplied. */ contentHash: string; byteLength?: number; source: ImageAssetSource; } export interface SvgAsset { kind: 'svg'; id: string; name: string; markup: string; width: number; height: number; contentHash: string; } export type DocumentAsset = ImageAsset | SvgAsset; export interface AssetStore { version: 1; items: Record; } export interface ImagePaint { type: 'image'; assetId: string; scaleMode: ImageScaleMode; opacity?: number; visible?: boolean; blendMode?: string; scale?: number; imageTransform?: DocumentMatrix; } export interface ImageAssetInput { name: string; /** Encoded bytes, a base64 string, or a `data:` URL. */ data?: Uint8Array | string; /** A host-served location; requires `mediaType`, `width`, `height`, and `contentHash`. */ url?: string; mediaType?: ImageMediaType; width?: number; height?: number; contentHash?: string; } export interface SvgAssetInput { name: string; markup: string; width?: number; height?: number; } export interface AssetFileLike { name: string; type?: string; arrayBuffer(): Promise; } export type InventoryAssetMedia = { kind: 'svg'; markup: string; } | { kind: 'image'; mediaType?: ImageMediaType; width?: number; height?: number; data?: string; url?: string; contentHash?: string; }; export interface InventoryAssetEntry { id: string; name: string; media?: InventoryAssetMedia; } /** SHA-256 of bytes as lowercase hex; synchronous so the document engine can stay synchronous. */ export declare function sha256Hex(bytes: Uint8Array): string; export declare function bytesToBase64(bytes: Uint8Array): string; /** Decodes standard or URL-safe base64, with or without padding; null on any other character. */ export declare function base64ToBytes(text: string): Uint8Array | null; /** Media type from the byte signature; null for anything that is not PNG, JPEG, GIF, or WebP. */ export declare function sniffImageMediaType(bytes: Uint8Array): ImageMediaType | null; /** Pixel dimensions from the header of a PNG, JPEG, GIF, or WebP; null when the header is incomplete. */ export declare function readImageDimensions(bytes: Uint8Array): { width: number; height: number; mediaType: ImageMediaType; } | null; /** Width and height an SVG declares on its root: `width`/`height` in px, otherwise the `viewBox` size. */ export declare function svgIntrinsicSize(markup: string): { width: number; height: number; } | null; export declare const assetIdFor: (contentHash: string) => string; export declare const safeAssetUrl: (url: string) => boolean; export declare const safeSvgMarkup: (markup: string) => boolean; export declare function isDocumentAsset(value: unknown): value is DocumentAsset; export declare function isAssetStore(value: unknown): value is AssetStore; export declare function isImagePaint(value: unknown): value is ImagePaint; export declare const emptyAssetStore: () => AssetStore; /** Detached asset store of a document; absent metadata is an empty store. Invalid metadata is reported by `assetStoreDiagnostics`. */ export declare function documentAssets(document: Pick): AssetStore; /** Verifies payload bytes independently of the structural asset schema. */ export declare function assetIntegrityProblem(asset: DocumentAsset): string | null; export declare function assetStoreDiagnostics(document: Pick): DocumentDiagnostic[]; /** Canonical JSON for `metadata.assets`: known keys in a stable order; undefined when the store is empty. */ export declare function serializeAssetStore(store: AssetStore): { [key: string]: DocumentValue; } | undefined; /** The asset a node or paint refers to, or null. Provided for the appearance owner's image paints. */ export declare function resolveAsset(document: Pick, assetId: string): DocumentAsset | null; export declare function createImageAsset(input: ImageAssetInput): ImageAsset; export declare function createSvgAsset(input: SvgAssetInput): SvgAsset; /** Adds an asset; an identical asset (same id and hash) is a no-op that keeps the existing entry. */ export declare function addAsset(store: AssetStore, asset: DocumentAsset): AssetStore; export declare function removeAsset(store: AssetStore, assetId: string): AssetStore; export declare function renameAsset(store: AssetStore, assetId: string, name: string): AssetStore; /** Merges every asset of `source` into `target`; a same-id entry with different content is refused. */ export declare function mergeAssetStores(target: AssetStore, source: AssetStore): AssetStore; /** Writes the store to `metadata.assets`; an empty store removes the key so plain documents keep empty metadata. */ export declare function writeDocumentAssets(transaction: Pick, store: AssetStore): void; export declare function addDocumentAsset(transaction: Pick, document: Pick, asset: DocumentAsset): void; /** Every image paint of a node's own properties, in paint order. */ export declare function nodeImagePaints(node: Pick): ImagePaint[]; /** Asset ids a node refers to directly: image paints (own and override properties) and an SVG import source. */ export declare function nodeAssetIds(node: DocumentNode): string[]; /** Nodes per referenced asset id, including ids that are missing from the store. */ export declare function assetReferences(document: Pick): Record; export declare function unusedAssetIds(document: Pick): string[]; export declare function pruneUnusedAssets(document: Pick): AssetStore; /** Referenced asset ids that the store does not contain. */ export declare function missingAssetIds(document: Pick): string[]; /** Duplicating layers shares assets (ids are content-addressed), so the sidecar passes through unchanged. */ export declare const assetsDuplicateMetadata: DocumentDuplicateMetadataRemapper; /** A URL usable by `` or `background-image`: a data URL for stored bytes, the location for references. */ export declare function assetSourceUrl(asset: DocumentAsset): string; export declare const imagePaint: (assetId: string, scaleMode?: ImageScaleMode) => ImagePaint; /** * CSS for one image paint as a background, keyed like React `CSSProperties`. `fill` covers the box, * `fit` letterboxes, `crop` covers unless an explicit image-to-local transform is present, `tile` repeats at natural size. * A missing asset yields an empty object so the layer keeps its other paints. */ export declare function imagePaintCss(source: Pick | AssetStore, paint: ImagePaint, box?: ImagePaintBox): Record; /** SVG fragments need the SVG namespace when rendered as an image resource; stored markup stays unchanged. */ export declare function imagePaintSourceUrl(asset: DocumentAsset): string; /** SVG image envelopes cannot fetch external references when used as image backgrounds. */ export declare function imageCropDiagnostic(asset: DocumentAsset): DocumentDiagnostic | null; /** A clipped image envelope references original bytes and shares the canonical image projection. */ export declare function imagePaintBackground(asset: DocumentAsset, paint: ImagePaint, box: ImagePaintBox, opacity?: number): string; /** Background CSS of a node's first image paint; the appearance owner layers this under its own projection. */ export declare function nodeImageCss(document: Pick, node: Pick & Partial>): Record; /** Size for a newly placed image: natural size, scaled down uniformly to fit the limit. */ export declare function imagePlacementSize(asset: Pick, limit?: number): { width: number; height: number; }; /** A frame whose only paint is the image; this is the "image layer" of the editor. */ export declare function imageNode(input: { id: string; asset: DocumentAsset; name?: string; scaleMode?: ImageScaleMode; x?: number; y?: number; limit?: number; }): DocumentNode; export declare function isImageNode(node: DocumentNode): boolean; /** Reads dropped or chosen files into assets; failures become diagnostics that name the file. */ export declare function importAssetFiles(files: Iterable): Promise<{ assets: DocumentAsset[]; diagnostics: DocumentDiagnostic[]; }>; /** Builds a store from a host inventory whose entries carry media; entries without media are skipped. */ export declare function assetsFromInventory(entries: Iterable): { store: AssetStore; assetIds: Record; diagnostics: DocumentDiagnostic[]; }; /** Custom source compilers must acknowledge asset and export sidecars rather than silently dropping them. */ export declare function assetInteropSourceDeltaDiagnostics(before: DesignDocument, after: DesignDocument): DocumentDiagnostic[];