import * as zarr from 'zarrita'; export { registry as codecRegistry } from 'zarrita'; /** Bounds tuple: [xMin, yMin, xMax, yMax] */ type Bounds = [number, number, number, number]; interface RequestParameters extends Omit { url: string; headers?: { [key: string]: string; }; } /** * Options passed to transformRequest */ interface TransformRequestOptions { /** HTTP method that will be used for this request */ method?: 'GET' | 'HEAD'; } type TransformRequest = (url: string, options?: TransformRequestOptions) => RequestParameters | Promise; type ColormapArray = number[][] | string[]; type SelectorValue = number | number[] | string | string[]; interface SelectorSpec { selected: SelectorValue; type?: 'index' | 'value'; } type Selector = Record; /** * Override the names used to identify spatial dimensions (lat/lon). * Only needed if your dataset uses non-standard names that aren't auto-detected. * Standard names (lat, latitude, y, lon, longitude, x) are detected automatically. */ interface SpatialDimensions { lat?: string; lon?: string; } interface LoadingState { loading: boolean; metadata: boolean; chunks: boolean; error?: Error | null; } type LoadingStateCallback = (state: LoadingState) => void; interface ZarrLayerOptions { id: string; /** * URL to the Zarr store. Required unless `store` is provided. */ source?: string; variable: string; /** * Custom zarrita-compatible store to use instead of creating a FetchStore from source. * Useful for IcechunkStore or other custom storage backends. * * The store must implement the zarrita Readable interface with at minimum: * - `get(key: string): Promise` - fetch data at path * * Optionally implement AsyncReadable for range requests: * - `getRange(key: string, range: RangeQuery): Promise` * * When provided: * - `source` becomes optional (falls back to layer id for identification) * - Metadata caching is bypassed (each layer fetches fresh metadata) * * @example * ```ts * import { IcechunkStore } from '@icechunk/icechunk-python' * const store = await IcechunkStore.open(...) * new ZarrLayer({ id: 'my-layer', store, variable: 'temperature', ... }) * ``` */ store?: zarr.Readable; selector?: Selector; colormap: ColormapArray; clim: [number, number]; opacity?: number; minzoom?: number; maxzoom?: number; zarrVersion?: 2 | 3; spatialDimensions?: SpatialDimensions; /** * Explicit spatial bounds [xMin, yMin, xMax, yMax]. * Units depend on CRS: degrees for EPSG:4326, source CRS units (e.g. meters) when proj4 is provided. * If not provided, bounds are read from coordinate arrays or default to global. */ bounds?: Bounds; /** * CRS identifier for built-in projections (EPSG:4326 or EPSG:3857). * For any other CRS, provide a matching proj4 definition. */ crs?: string; latIsAscending?: boolean | null; fillValue?: number; customFrag?: string; uniforms?: Record; renderingMode?: '2d' | '3d'; onLoadingStateChange?: LoadingStateCallback; /** * Proj4 definition string for reprojection (untiled mode only). * When provided, bounds are interpreted as source CRS units and data is reprojected to Web Mercator. * Example: "+proj=lcc +lat_1=38.5 +lat_2=38.5 +lat_0=38.5 +lon_0=-97.5 +x_0=0 +y_0=0 +R=6371229 +units=m +no_defs" */ proj4?: string; /** * Function to transform request URLs and add custom headers/credentials. * Useful for authentication, proxy routing, or request customization. * When provided, the store cache is bypassed to prevent credential sharing between layers. */ transformRequest?: TransformRequest; /** * Enable full polar coverage in Mapbox globe view for untiled EPSG:4326 or * proj4 datasets. Has no effect on tiled or EPSG:3857 data. * * MapLibre globe always renders to the poles automatically. * * For Mapbox, this enables an experimental direct ECEF path that bypasses * tile draping. Only activates at the fully-globe zoom endpoint; during * the globe-to-mercator zoom morph the layer falls back to the standard * draped path. Incompatible with Mapbox terrain — when terrain is enabled * the layer uses the draped tile path. Relies on Mapbox internal APIs and * may break across Mapbox GL JS versions. * * Default: `false` */ renderPoles?: boolean; } interface BoundsLike { getWest(): number; getEast(): number; toArray(): [number, number][]; } interface MapLike { getProjection?(): { type?: unknown; name?: string; } | null; getRenderWorldCopies?(): boolean; getTerrain?(): unknown; on?(event: string, handler: (...args: unknown[]) => void): void; off?(event: string, handler: (...args: unknown[]) => void): void; triggerRepaint?(): void; getBounds?(): BoundsLike | null; getZoom?(): number; painter?: { context?: { gl?: unknown; }; }; renderer?: { getContext?: () => unknown; }; } /** * Nested values structure for multi-dimensional data queries. */ interface NestedValues { [key: string]: number[] | NestedValues; [key: number]: number[] | NestedValues; } /** * Values from a data query. Can be flat array or nested when selector has array values. * * Flat: `number[]` when selector = `{ month: 1 }` * Nested: `{ 1: number[], 2: number[] }` when selector = `{ month: [1, 2] }` */ type QueryDataValues = number[] | NestedValues; /** * Result from a query (point or region). * Matches carbonplan/maps structure: { [variable]: values, dimensions, coordinates } * * Spatial result keys are the store's own axis names (e.g. `y`/`x`, * `lat`/`lon`, `latitude`/`longitude`) and the coordinate arrays carry * source-CRS values: Web Mercator meters for EPSG:3857, degrees for * EPSG:4326, source units for custom-proj4 datasets. */ interface QueryResult { /** Variable name mapped to its values (flat array or nested based on selector) */ [variable: string]: QueryDataValues | string[] | { [key: string]: (number | string)[]; }; /** Dimension names in order, using the same spatial keys as coordinates */ dimensions: string[]; /** Coordinate arrays for each dimension */ coordinates: { [key: string]: (number | string)[]; }; } /** * GeoJSON Point geometry. */ interface GeoJSONPoint { type: 'Point'; coordinates: [number, number]; } /** * GeoJSON Polygon geometry. */ interface GeoJSONPolygon { type: 'Polygon'; coordinates: number[][][]; } /** * GeoJSON MultiPolygon geometry. */ interface GeoJSONMultiPolygon { type: 'MultiPolygon'; coordinates: number[][][][]; } /** * Supported GeoJSON geometry types for queries. */ type QueryGeometry = GeoJSONPoint | GeoJSONPolygon | GeoJSONMultiPolygon; /** * Options for queryData calls. */ interface QueryOptions { /** AbortSignal to cancel the query. */ signal?: AbortSignal; /** Include per-pixel coordinates in the result. Defaults to true. */ includeSpatialCoordinates?: boolean; } /** * @module zarr-layer * * MapLibre/Mapbox custom layer implementation for rendering Zarr datasets. * Implements CustomLayerInterface for direct WebGL rendering. */ declare class ZarrLayer { readonly type: 'custom'; readonly renderingMode: '2d' | '3d'; readonly wrapTileId = true; id: string; private url; private variable; private zarrVersion; private spatialDimensions; private bounds; private crs; private latIsAscending; private selector; private invalidate; private colormap; private clim; private opacity; private minZoom; private maxZoom; private selectorHash; private _fillValue; private scaleFactor; private offset; private fixedDataScale; private dataScaleLocked; private gl; private map; private renderer; private regionRenderer; private tileNeedsRender; private projectionChangeHandler; private resolveGl; private zarrStore; private levelInfos; private dimIndices; private dimensionValues; private normalizedSelector; private isRemoved; private fragmentShaderSource; private customFrag; private customUniforms; private bandNames; private customShaderConfig; private onLoadingStateChange; private metadataLoading; private chunksLoading; private initError; private proj4; private transformRequest; private customStore; private renderPoles; private lastIsGlobe; private usingDirectMapboxGlobePath; private mapboxDirectGlobePathAvailable; private canUseMapboxDirectGlobePath; private configureMapboxRenderPath; get fillValue(): number | null; private isGlobeProjection; /** Check for projection changes and notify mode. Returns current isGlobe state. */ private syncProjectionState; constructor({ id, source, variable, selector, colormap, clim, opacity, minzoom, maxzoom, zarrVersion, spatialDimensions, bounds, crs, latIsAscending, fillValue, customFrag, uniforms, renderingMode, onLoadingStateChange, proj4, transformRequest, store, renderPoles, }: ZarrLayerOptions); private emitLoadingState; private handleChunkLoadingChange; setOpacity(opacity: number): void; setClim(clim: [number, number]): void; setColormap(colormap: ColormapArray): void; setUniforms(uniforms: Record): void; setVariable(variable: string): Promise; setSelector(selector: Selector): Promise; onAdd(map: MapLike, gl: WebGL2RenderingContext | WebGLRenderingContext): void; private _onAddAsync; private initializeRenderer; private initialize; private loadInitialDimensionValues; private isZoomInRange; prerender(_gl: WebGL2RenderingContext | WebGLRenderingContext, _params: unknown): void; render(_gl: WebGL2RenderingContext | WebGLRenderingContext, params: unknown, projection?: { name: string; }, projectionToMercatorMatrix?: number[] | Float32Array | Float64Array, projectionToMercatorTransition?: number, _centerInMercator?: number[], _pixelsPerMeterRatio?: number): void; renderToTile(_gl: WebGL2RenderingContext | WebGLRenderingContext, tileId: { z: number; x: number; y: number; }): void; shouldRerenderTiles(): boolean; /** * Dispose all GL resources and internal state. * Does NOT remove the layer from the map - call map.removeLayer(id) for that. */ private _disposeResources; onRemove(_map: MapLike, gl: WebGL2RenderingContext | WebGLRenderingContext): void; /** * Query all data values within a geographic region. * @param geometry - GeoJSON Point, Polygon or MultiPolygon geometry. * @param selector - Optional selector to override the layer's selector. * @returns Promise resolving to the query result matching carbonplan/maps structure. */ queryData(geometry: QueryGeometry, selector?: Selector, options?: QueryOptions): Promise; } export { type ColormapArray, type LoadingState, type LoadingStateCallback, type QueryDataValues, type QueryGeometry, type QueryOptions, type QueryResult, type RequestParameters, type Selector, type SpatialDimensions, type TransformRequest, ZarrLayer, type ZarrLayerOptions };