@chrtco/sdk 0.10.46 → 0.10.47
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 +22 -0
- package/README.md +29 -6
- package/dist/atlas/browser.cjs +339 -5
- package/dist/atlas/browser.cjs.map +1 -1
- package/dist/atlas/browser.d.cts +1 -1
- package/dist/atlas/browser.d.ts +1 -1
- package/dist/atlas/browser.js +339 -5
- package/dist/atlas/browser.js.map +1 -1
- package/dist/index.cjs +2344 -1748
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1236 -1163
- package/dist/index.d.ts +1236 -1163
- package/dist/index.js +2332 -1748
- package/dist/index.js.map +1 -1
- package/dist/symbol-families-De7sN-p5.d.cts +93 -0
- package/dist/symbol-families-De7sN-p5.d.ts +93 -0
- package/package.json +1 -1
- package/dist/symbol-families-D2Kx20HJ.d.cts +0 -47
- package/dist/symbol-families-D2Kx20HJ.d.ts +0 -47
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { F as FileSystemAdapter } from './fs-adapter-D5iwdb1Q.js';
|
|
2
|
-
import { C as ColorTableName } from './symbol-families-
|
|
3
|
-
export { S as S52_COLORS,
|
|
2
|
+
import { C as ColorTableName } from './symbol-families-De7sN-p5.js';
|
|
3
|
+
export { E as EINK_COLOR_TABLES, a as EINK_MONO_GREYS, S as S52_COLORS, b as S52_DAY, c as S52_DUSK, d as S52_EINK_COLOR, e as S52_EINK_MONO, f as S52_EINK_NIGHT, g as S52_NIGHT, h as SYMBOL_FAMILIES, i as SYMBOL_FAMILY_META, j as SymbolFamily, k as SymbolFamilyMeta, l as getColorTable, m as iconExpressionForFamily, n as isEinkColorTable, o as isEinkGreyTable, p as parseSymbolFamily, r as resolveColor } from './symbol-families-De7sN-p5.js';
|
|
4
4
|
import maplibregl from 'maplibre-gl';
|
|
5
5
|
import { ExpressionSpecification } from '@maplibre/maplibre-gl-style-spec';
|
|
6
6
|
|
|
@@ -862,8 +862,10 @@ interface OfflineHeartbeatOptions {
|
|
|
862
862
|
* from `GET /v1/offline/styles/{region}`.
|
|
863
863
|
*/
|
|
864
864
|
interface OfflineFetchStyleOptions {
|
|
865
|
-
/**
|
|
866
|
-
|
|
865
|
+
/** Colour palette. Default: `"DAY"`. `"EINK_COLOR"` / `"EINK_MONO"` are
|
|
866
|
+
* the e-paper variants (colour and monochrome e-ink); `"EINK_NIGHT"` is
|
|
867
|
+
* e-ink at night. */
|
|
868
|
+
palette?: "DAY" | "DUSK" | "NIGHT" | "EINK_COLOR" | "EINK_MONO" | "EINK_NIGHT";
|
|
867
869
|
/**
|
|
868
870
|
* URL scheme baked into the source. Default: `"mbtiles"` (iOS/Android via
|
|
869
871
|
* MLN Native). Use `"file"` for desktop (Win/macOS/Linux).
|
|
@@ -894,7 +896,7 @@ interface OfflineFetchStyleOptions {
|
|
|
894
896
|
*/
|
|
895
897
|
interface OfflineStyleResponse {
|
|
896
898
|
region: string;
|
|
897
|
-
palette: "DAY" | "DUSK" | "NIGHT";
|
|
899
|
+
palette: "DAY" | "DUSK" | "NIGHT" | "EINK_COLOR" | "EINK_MONO" | "EINK_NIGHT";
|
|
898
900
|
protocol: "mbtiles" | "file";
|
|
899
901
|
/** Resolved symbol-artwork family (lowercased), echoed from `?symbols=`. */
|
|
900
902
|
symbols?: ChrtSymbolSet;
|
|
@@ -1558,12 +1560,20 @@ declare class TileAuth {
|
|
|
1558
1560
|
|
|
1559
1561
|
/** Symbol-artwork families served by the Style API. */
|
|
1560
1562
|
type ChrtSymbolSet = "s52" | "s101" | "chrt" | "raster";
|
|
1561
|
-
/**
|
|
1562
|
-
|
|
1563
|
+
/**
|
|
1564
|
+
* Palette themes served by the Style API: the S-52 colour tables (`day`,
|
|
1565
|
+
* `dusk`, `night`) and CHRT's e-paper variants — `eink_color` for colour
|
|
1566
|
+
* e-ink (E Ink Kaleido 3) and `eink_mono` for monochrome e-ink panels and
|
|
1567
|
+
* monitors, `eink_night` for any e-ink screen at night (a black page). The
|
|
1568
|
+
* e-ink themes change portrayal as well as colour (heavier
|
|
1569
|
+
* lines, a heavy safety contour, depth steps by pattern in mono).
|
|
1570
|
+
*/
|
|
1571
|
+
type ChrtStyleTheme = "day" | "dusk" | "night" | "eink_color" | "eink_mono" | "eink_night";
|
|
1563
1572
|
interface StyleUrlOptions {
|
|
1564
|
-
/** Palette: "day" (default), "dusk",
|
|
1565
|
-
* default — for keys with a bound
|
|
1566
|
-
* style's default palette
|
|
1573
|
+
/** Palette: "day" (default), "dusk", "night", "eink_color", "eink_mono"
|
|
1574
|
+
* or "eink_night". Omit to get the style's default — for keys with a bound
|
|
1575
|
+
* CHRTstyle custom style, that's the style's default palette (the e-ink
|
|
1576
|
+
* themes are always available, bound style or not). */
|
|
1567
1577
|
theme?: ChrtStyleTheme;
|
|
1568
1578
|
/** Symbol-artwork family: `s52` (default PresLib set), `s101` (official
|
|
1569
1579
|
* S-101 Portrayal Catalogue symbols), `chrt` (the CHRT house set), or
|
|
@@ -2822,1321 +2832,1379 @@ declare class InteractClient {
|
|
|
2822
2832
|
}
|
|
2823
2833
|
|
|
2824
2834
|
/**
|
|
2825
|
-
*
|
|
2826
|
-
*
|
|
2827
|
-
*
|
|
2828
|
-
*
|
|
2829
|
-
* primaries). That is the quantity a dark-adapted eye responds to, and it is
|
|
2830
|
-
* the one `sounding-legibility.test.ts` already measures soundings in. Scaling
|
|
2831
|
-
* the sRGB-ENCODED channels instead would dim dark colours far more than
|
|
2832
|
-
* bright ones and shift every hue it touched.
|
|
2835
|
+
* Post-consolidation (2026-04): one consolidated PMTiles per region, all
|
|
2836
|
+
* S-57 classes as distinct MVT layers inside. The MapLibre style emits one
|
|
2837
|
+
* vector source (id = region) and N paint layers that reference it via
|
|
2838
|
+
* `source-layer` = S-57 class name.
|
|
2833
2839
|
*
|
|
2834
|
-
*
|
|
2835
|
-
*
|
|
2836
|
-
*
|
|
2837
|
-
* the two stay one family by construction rather than by two hand-typed hexes
|
|
2838
|
-
* that happen to agree.
|
|
2839
|
-
*/
|
|
2840
|
-
/** WCAG 2.x relative luminance of a `#rrggbb` colour, 0 (black) to 1 (white). */
|
|
2841
|
-
declare function relativeLuminance(hex: string): number;
|
|
2842
|
-
/** WCAG 2.x contrast ratio between two `#rrggbb` colours, 1 to 21. */
|
|
2843
|
-
declare function contrastRatio(a: string, b: string): number;
|
|
2844
|
-
/**
|
|
2845
|
-
* The same hue at `factor` times its linear light. `factor` above 1 can clip a
|
|
2846
|
-
* channel, which shifts the hue; nothing in the palettes brightens, so callers
|
|
2847
|
-
* pass 0–1.
|
|
2848
|
-
*/
|
|
2849
|
-
declare function scaleLinearLight(hex: string, factor: number): string;
|
|
2850
|
-
/**
|
|
2851
|
-
* `hex` dimmed, hue kept, until its luminance is at most `ceiling`. A colour
|
|
2852
|
-
* already at or under the ceiling comes back unchanged (lower-cased).
|
|
2840
|
+
* `buildSources()` returns either the legacy Mapbox MTS shape (preserved for
|
|
2841
|
+
* demos / external style export — see generateStyle comments) or the PMTiles
|
|
2842
|
+
* shape pointing at a single tile URL per region.
|
|
2853
2843
|
*/
|
|
2854
|
-
|
|
2844
|
+
/** Vector source emitted for the legacy Mapbox MTS path. */
|
|
2845
|
+
interface MapboxVectorSource {
|
|
2846
|
+
type: "vector";
|
|
2847
|
+
url: string;
|
|
2848
|
+
}
|
|
2855
2849
|
/**
|
|
2856
|
-
*
|
|
2857
|
-
*
|
|
2858
|
-
*
|
|
2859
|
-
* text. The brightest thing NIGHT draws on purpose.
|
|
2860
|
-
* `NIGHT_MUTED_INK` that ink at 43% of its linear light, which is how
|
|
2861
|
-
* S52_NIGHT.SNDG1 (the deeper soundings) was derived.
|
|
2862
|
-
* Everything that orients rather than navigates is drawn
|
|
2863
|
-
* at or under this, and `night-luminance.test.ts` holds
|
|
2864
|
-
* every visible NIGHT colour to it unless an exemption
|
|
2865
|
-
* names a reason.
|
|
2850
|
+
* Vector source emitted for the tiles.chrt.co PMTiles path. Uses an explicit
|
|
2851
|
+
* `tiles` array (not a TileJSON `url`) because the tile-worker serves raw MVT
|
|
2852
|
+
* bytes without a TileJSON descriptor.
|
|
2866
2853
|
*/
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2854
|
+
interface PmtilesVectorSource {
|
|
2855
|
+
type: "vector";
|
|
2856
|
+
tiles: string[];
|
|
2857
|
+
minzoom: number;
|
|
2858
|
+
maxzoom: number;
|
|
2859
|
+
/** The credit a renderer shows for this source (MapLibre's attribution control). */
|
|
2860
|
+
attribution?: string;
|
|
2861
|
+
}
|
|
2870
2862
|
/**
|
|
2871
|
-
*
|
|
2872
|
-
*
|
|
2873
|
-
*
|
|
2874
|
-
*
|
|
2875
|
-
* ===========================================================================
|
|
2876
|
-
*
|
|
2877
|
-
* `map.remove()` deletes `map.style`, and after that nearly every method that
|
|
2878
|
-
* touches the style throws rather than returning: `hasImage`, `addImage`,
|
|
2879
|
-
* `updateImage`, `getSource`, `addLayer` all fail with "Cannot read properties
|
|
2880
|
-
* of undefined (reading 'getImage')" and its siblings. Code that was handed a
|
|
2881
|
-
* map, awaited a decode, an IndexedDB read or a fetch, and then wrote to the
|
|
2882
|
-
* map, throws from wherever it resumed — usually a promise nobody is awaiting,
|
|
2883
|
-
* so the throw is an uncaught error with no caller to explain it.
|
|
2884
|
-
*
|
|
2885
|
-
* Measured in CHRTdesktop (chip 63, 2026-10-04): with the page's main thread
|
|
2886
|
-
* held at 6× CPU, the chart removed its map in the middle of a pan, and the
|
|
2887
|
-
* S-52 image loader resumed onto it:
|
|
2888
|
-
*
|
|
2889
|
-
* TypeError: Cannot read properties of undefined (reading 'getImage')
|
|
2890
|
-
* at Map.hasImage
|
|
2891
|
-
* at addImageToMap (s52-image-cache.ts)
|
|
2892
|
-
*
|
|
2893
|
-
* The rule, for anything in this package or the app that takes a map: after
|
|
2894
|
-
* an `await` (or in a `.then`, a frame callback, an `onload`), check this
|
|
2895
|
-
* before the first call on the map, and stop quietly if it says no. A removed
|
|
2896
|
-
* map is not an error to report — whoever removed it is building the next one.
|
|
2897
|
-
*
|
|
2898
|
-
* ⚠ `_removed`, NOT `style`. maplibre sets `_removed = true` as the last step
|
|
2899
|
-
* of `remove()` (typed on `Map` in maplibre-gl 4 and 5), so it is the fact,
|
|
2900
|
-
* where `style === undefined` is a consequence. Test doubles that never had a
|
|
2901
|
-
* `style` read as live, which is what they are. The app pins the maplibre side
|
|
2902
|
-
* of this (`map-live.test.ts`), so an upgrade that renames the field fails a
|
|
2903
|
-
* test rather than silently making every check say yes.
|
|
2904
|
-
*
|
|
2905
|
-
* Typed `object` so the structural map shapes the app passes around (a tile
|
|
2906
|
-
* census, an errored-tile tracker) can be asked too, not only `maplibregl.Map`.
|
|
2863
|
+
* Terrarium elevation, served as PNG from `CHRT_RELIEF`. Separate from the
|
|
2864
|
+
* vector shapes because MapLibre needs `type: "raster-dem"` and an explicit
|
|
2865
|
+
* `encoding` — a raster-dem source read as a plain raster renders the encoded
|
|
2866
|
+
* RGB as a garish false-colour image rather than as elevation.
|
|
2907
2867
|
*/
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
interface AtlasStyle {
|
|
2918
|
-
type: GeomType;
|
|
2919
|
-
paint: Record<string, unknown>;
|
|
2920
|
-
layout?: Record<string, unknown>;
|
|
2921
|
-
/** Nautical symbol ID for symbol-type layers */
|
|
2922
|
-
iconImage?: string;
|
|
2923
|
-
}
|
|
2924
|
-
/** One row in the S-52 lookup table */
|
|
2925
|
-
interface LookupEntry {
|
|
2926
|
-
/** S-57 object class acronym */
|
|
2927
|
-
objectClass: string;
|
|
2928
|
-
/** Human-readable name */
|
|
2929
|
-
name: string;
|
|
2930
|
-
/** Chart No. 1 section */
|
|
2931
|
-
category: NauticalCategory;
|
|
2932
|
-
/** S-52 display category */
|
|
2933
|
-
displayCategory: DisplayCategory;
|
|
2934
|
-
/** Default style using S-52 color tokens (resolved later) */
|
|
2935
|
-
style: AtlasStyle;
|
|
2936
|
-
/** Whether conditional symbology may override the style */
|
|
2937
|
-
hasConditional?: boolean;
|
|
2938
|
-
/** Attributes that affect styling */
|
|
2939
|
-
conditionalAttributes?: string[];
|
|
2940
|
-
/** INT1 / Chart No. 1 reference (e.g. "Q130.1") */
|
|
2941
|
-
int1Ref?: string;
|
|
2942
|
-
/** S-52 viewing group number */
|
|
2943
|
-
viewingGroup?: number;
|
|
2944
|
-
/** Minimum compilation scale for display (SCAMIN) */
|
|
2945
|
-
scamin?: number;
|
|
2946
|
-
/**
|
|
2947
|
-
* Mark this class as deliberately invisible (label-only or metadata-only)
|
|
2948
|
-
* so the layer-coverage audit doesn't flag its geometry-type gaps as bugs.
|
|
2949
|
-
*
|
|
2950
|
-
* Examples:
|
|
2951
|
-
* - SOUNDG: rendered as depth numbers via labels.ts, not as visible dots
|
|
2952
|
-
* - LNDRGN: region NAME labels only, no shape
|
|
2953
|
-
* - M_NPUB / M_NSYS / M_QUAL / M_SREL / DSID: S-57 metadata classes;
|
|
2954
|
-
* present for click-query attributes, never drawn
|
|
2955
|
-
*
|
|
2956
|
-
* Without this flag, `scripts/audit-layer-coverage.ts` reports the
|
|
2957
|
-
* thousands of features in these classes as "gaps" every week even
|
|
2958
|
-
* though the invisibility is intentional.
|
|
2959
|
-
*/
|
|
2960
|
-
auditIgnore?: boolean;
|
|
2961
|
-
}
|
|
2962
|
-
/** Resolved style ready for Mapbox GL (tokens → hex) */
|
|
2963
|
-
interface ResolvedStyle {
|
|
2964
|
-
type: GeomType;
|
|
2965
|
-
paint: Record<string, unknown>;
|
|
2966
|
-
layout?: Record<string, unknown>;
|
|
2967
|
-
minzoom?: number;
|
|
2968
|
-
maxzoom?: number;
|
|
2868
|
+
interface RasterDemSource {
|
|
2869
|
+
type: "raster-dem";
|
|
2870
|
+
tiles: string[];
|
|
2871
|
+
encoding: "terrarium";
|
|
2872
|
+
tileSize: number;
|
|
2873
|
+
minzoom: number;
|
|
2874
|
+
maxzoom: number;
|
|
2875
|
+
/** The credit a renderer shows for this source (MapLibre's attribution control). */
|
|
2876
|
+
attribution?: string;
|
|
2969
2877
|
}
|
|
2970
|
-
|
|
2878
|
+
type VectorSourceSpec = MapboxVectorSource | PmtilesVectorSource;
|
|
2879
|
+
type AnySourceSpec = VectorSourceSpec | RasterDemSource;
|
|
2880
|
+
/** CHRTland's vector land base. ADR 0023: its own archive, never chart data. */
|
|
2881
|
+
declare const LAND_REGION = "CHRT_LAND";
|
|
2882
|
+
/** CHRTland's terrarium relief. */
|
|
2883
|
+
declare const RELIEF_REGION = "CHRT_RELIEF";
|
|
2884
|
+
/** The world basemap under everything (completing-the-world-map, 2026-08-27). */
|
|
2885
|
+
declare const BASE_REGION = "CHRT_BASE";
|
|
2971
2886
|
/**
|
|
2972
|
-
*
|
|
2973
|
-
*
|
|
2974
|
-
*
|
|
2887
|
+
* CHRT_BASE's zoom range. 11 is the deepest zoom the archive's detail tier
|
|
2888
|
+
* carries honestly — the planet's inland water exists from z9 and is read at
|
|
2889
|
+
* z10 — and the world tier is tiled to the same depth so no layer vanishes
|
|
2890
|
+
* from a tile the detail tier creates. Above 11 the client overzooms, and
|
|
2891
|
+
* overzoomed inland water looks soft DELIBERATELY: it is "roughly where the
|
|
2892
|
+
* lakes are", not a surveyed shoreline. Must equal the builder's MAXZOOM
|
|
2893
|
+
* (tools/chrtbase-build/build.mjs).
|
|
2975
2894
|
*/
|
|
2976
|
-
declare const
|
|
2977
|
-
|
|
2895
|
+
declare const BASE_MINZOOM = 0;
|
|
2896
|
+
declare const BASE_MAXZOOM = 11;
|
|
2978
2897
|
/**
|
|
2979
|
-
*
|
|
2980
|
-
*
|
|
2898
|
+
* The credit the ONLINE CHRT_BASE source carries (owner wording, 2026-09-16).
|
|
2899
|
+
*
|
|
2900
|
+
* OpenStreetMap is named because the online archive's z9–11 detail tier IS
|
|
2901
|
+
* OSM-derived inland water (ODbL, `public/chrtbase-derivation.json`). The
|
|
2902
|
+
* app-embeddable offline bundle is a z0–6 cut that contains no OSM data and
|
|
2903
|
+
* carries `BASE_BUNDLE_ATTRIBUTION` instead (base-layers.ts) — one credit per
|
|
2904
|
+
* artefact, each naming exactly the data it holds.
|
|
2981
2905
|
*/
|
|
2982
|
-
declare const
|
|
2983
|
-
/** Get numeric draw priority for a layer (lower = drawn first / below) */
|
|
2984
|
-
declare function getDrawPriority(layerName: string): number;
|
|
2985
|
-
|
|
2986
|
-
/** S-52 display modes */
|
|
2987
|
-
type DisplayMode = "BASE" | "STANDARD" | "ALL";
|
|
2988
|
-
/** Check if a layer's display category is visible in the given mode */
|
|
2989
|
-
declare function isVisibleInMode(displayCategory: DisplayCategory, mode: DisplayMode): boolean;
|
|
2906
|
+
declare const BASE_ATTRIBUTION = "\u00A9 CHRT \u00B7 Made with Natural Earth \u00B7 \u00A9 OpenStreetMap contributors";
|
|
2990
2907
|
/**
|
|
2991
|
-
*
|
|
2908
|
+
* The credit the CHRT_LAND source carries. CHRTland's land, land use, roads,
|
|
2909
|
+
* places, peaks and marinas are OpenStreetMap via the Protomaps planet, and the
|
|
2910
|
+
* ODbL requires this notice wherever the map is shown (.chrt/legal.md
|
|
2911
|
+
* "Required notices"). Its other inputs — the ENC's charted land, USGS 3DEP
|
|
2912
|
+
* contours, GNIS names — are US federal public domain and owe none. Same
|
|
2913
|
+
* string as the offline land bundle's (offline-worker `LAND_PROVENANCE`).
|
|
2992
2914
|
*/
|
|
2993
|
-
declare
|
|
2994
|
-
declare function getCollisionSettings(viewingGroup?: number): {
|
|
2995
|
-
iconAllowOverlap: boolean;
|
|
2996
|
-
iconOptional: boolean;
|
|
2997
|
-
symbolSortKey?: number;
|
|
2998
|
-
};
|
|
2915
|
+
declare const LAND_ATTRIBUTION = "\u00A9 OpenStreetMap contributors";
|
|
2999
2916
|
/**
|
|
3000
|
-
*
|
|
2917
|
+
* The credit the CHRT_RELIEF source carries. USGS 3DEP elevation, public
|
|
2918
|
+
* domain (17 U.S.C. § 105) — no notice is required, so this is a courtesy that
|
|
2919
|
+
* names the source. There is no OpenStreetMap in it.
|
|
3001
2920
|
*/
|
|
3002
|
-
declare
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
declare function getLookupEntry(layerName: string): LookupEntry;
|
|
3006
|
-
|
|
2921
|
+
declare const RELIEF_ATTRIBUTION = "Elevation: USGS 3D Elevation Program";
|
|
2922
|
+
/** Terrarium tiles are 512 px; the default 256 would halve the apparent relief. */
|
|
2923
|
+
declare const RELIEF_TILE_SIZE = 512;
|
|
3007
2924
|
/**
|
|
3008
|
-
*
|
|
3009
|
-
*
|
|
3010
|
-
*
|
|
2925
|
+
* How `CHRT_RELIEF`'s PNGs encode elevation. MapLibre's raster-dem default is
|
|
2926
|
+
* `mapbox`, which decodes terrarium RGB into nonsense heights — so every
|
|
2927
|
+
* surface that describes this source (this registry, the tile-worker's
|
|
2928
|
+
* TileJSON) has to say it.
|
|
3011
2929
|
*/
|
|
2930
|
+
declare const RELIEF_ENCODING = "terrarium";
|
|
2931
|
+
type SourceMode = "mapbox" | "pmtiles";
|
|
3012
2932
|
/**
|
|
3013
|
-
*
|
|
3014
|
-
* "dangerous to my hull" for portrayal purposes.
|
|
2933
|
+
* Query parameter carrying the resolved build id on every tile URL.
|
|
3015
2934
|
*
|
|
3016
|
-
*
|
|
3017
|
-
* safety-contour-driven conditional symbology rule, so the rules can't
|
|
3018
|
-
* silently disagree with each other:
|
|
3019
|
-
*
|
|
3020
|
-
* - §SOUNDG02 — soundings shoaler than the contour get the
|
|
3021
|
-
* high-contrast shade (see `getLabelConfig` in labels.ts).
|
|
3022
|
-
* - §CSYM02 — isolated dangers shoaler than the contour get the
|
|
3023
|
-
* DNGCIR01 ring (see `buildLayersForClass` in layer-builder.ts).
|
|
3024
|
-
* - §DEPARE04 — the MS/MD shade boundary (owner decision 2026-08-21,
|
|
3025
|
-
* replacing a hardcoded 5 m middle cut; see the DEPARE block below
|
|
3026
|
-
* for the full IHO correspondence).
|
|
2935
|
+
* ── Why the build has to be IN THE URL ────────────────────────────────────
|
|
3027
2936
|
*
|
|
3028
|
-
*
|
|
3029
|
-
* `
|
|
3030
|
-
*
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
/**
|
|
3035
|
-
* The colour token of each `case` branch of `depareFillExpression`, in branch
|
|
3036
|
-
* order, then the fallback. `depth-area-opaque.ts` names the layers it splits
|
|
3037
|
-
* the expression into from this list, so the two read from one place.
|
|
3038
|
-
*/
|
|
3039
|
-
declare const DEPARE_FILL_BRANCH_TOKENS: readonly ["DEPIT", "DEPVS", "DEPMS", "DEPMD"];
|
|
3040
|
-
declare const DEPARE_FILL_FALLBACK_TOKEN = "DEPDW";
|
|
3041
|
-
declare function depareFillExpression(ct?: ColorTableName, safetyContourM?: number): unknown[];
|
|
3042
|
-
declare function lightColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3043
|
-
declare function lightFillExpression(ct?: ColorTableName): unknown[];
|
|
3044
|
-
declare function lateralColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3045
|
-
declare function lateralFillExpression(ct?: ColorTableName): unknown[];
|
|
3046
|
-
declare function hazardColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3047
|
-
declare function hazardFillExpression(ct?: ColorTableName): unknown[];
|
|
3048
|
-
declare function daymarkColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3049
|
-
|
|
3050
|
-
/**
|
|
3051
|
-
* Label configurations for S-57 layers.
|
|
3052
|
-
* Defines which layers get text labels and how to extract label text.
|
|
3053
|
-
*/
|
|
3054
|
-
|
|
3055
|
-
/**
|
|
3056
|
-
* Feature-class hierarchy for SEAARE labels. Returns a tier number 1-5 per
|
|
3057
|
-
* feature:
|
|
2937
|
+
* The Worker reports the build it served in the `X-Build-Id` RESPONSE HEADER
|
|
2938
|
+
* and sends `Cache-Control: private, max-age=3600`. A header is not part of a
|
|
2939
|
+
* cache key, so every build shares one URL: after a cutover, tiles the client
|
|
2940
|
+
* already fetched keep coming from its own HTTP cache — the old build — while
|
|
2941
|
+
* newly-panned-to tiles come from the new one, for up to the full hour. The
|
|
2942
|
+
* client renders TWO BUILDS AT ONCE.
|
|
3058
2943
|
*
|
|
3059
|
-
*
|
|
3060
|
-
*
|
|
3061
|
-
*
|
|
3062
|
-
*
|
|
3063
|
-
*
|
|
3064
|
-
*
|
|
2944
|
+
* On a nautical chart that is not a cosmetic seam. Measured live 2026-08-25,
|
|
2945
|
+
* cutting `CHRT_LAND` from `463b265e` to `dbb69074` (a build that deliberately
|
|
2946
|
+
* changes land extent): adjacent tiles disagreed about whether land was there,
|
|
2947
|
+
* at the seam between them. Putting the build in the key gives each build its
|
|
2948
|
+
* own cache namespace — old entries age out untouched, and the next style
|
|
2949
|
+
* build flips the whole viewport at once instead of tile by tile.
|
|
3065
2950
|
*
|
|
3066
|
-
*
|
|
3067
|
-
* ocean code; the attribute is 1/unset on oceans)
|
|
3068
|
-
* 2 — Sea / Gulf (OBJNAM "Gulf of …" / "… Sea")
|
|
3069
|
-
* 3 — Bay / Sound / (CATSEA in {5 bay, 12 narrows} OR OBJNAM
|
|
3070
|
-
* Strait / Narrows " Bay" / " Sound" / " Strait")
|
|
3071
|
-
* 4 — Anchorage detail (OBJNAM contains "Anchorage Area")
|
|
3072
|
-
* 5 — Relief + default (CATSEA relief codes — authoritative — or
|
|
3073
|
-
* relief-term names, or anything uncategorised;
|
|
3074
|
-
* suppressed below z9 by the size curve)
|
|
2951
|
+
* ── Why a QUERY PARAMETER and not a path segment ──────────────────────────
|
|
3075
2952
|
*
|
|
3076
|
-
*
|
|
3077
|
-
*
|
|
3078
|
-
* Area" compound names can't bubble up into headline tiers.
|
|
3079
|
-
* `coalesce(CATSEA, catsea)` handles post-tippecanoe case variation
|
|
3080
|
-
* (matches `s52-conditional.ts` precedent).
|
|
3081
|
-
*/
|
|
3082
|
-
declare function buildSeaAreaTierExpression(): ExpressionSpecification;
|
|
3083
|
-
/**
|
|
3084
|
-
* Built-up area tier (BUAARE): major city / town / neighborhood.
|
|
3085
|
-
* 1 — Major city (CATBUA=1 urban, or OBJNAM length <= 8)
|
|
3086
|
-
* 2 — Town (CATBUA=5 village, or OBJNAM length <= 14)
|
|
3087
|
-
* 3 — Neighborhood (longer compound names)
|
|
2953
|
+
* A path segment would be the tidier-looking URL and it is the wrong trade
|
|
2954
|
+
* here, for two reasons that are both about other people's code:
|
|
3088
2955
|
*
|
|
3089
|
-
*
|
|
3090
|
-
*
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
*
|
|
3095
|
-
*
|
|
3096
|
-
*
|
|
2956
|
+
* 1. COMPATIBILITY IS PERMANENT, NOT "one release". iOS and desktop are
|
|
2957
|
+
* prod-only clients that ship on their own cadence. The Worker routes on
|
|
2958
|
+
* `url.pathname` (`TILE_ROUTE_PATH`) and reads only `?build=`, so a URL
|
|
2959
|
+
* carrying this parameter routes BYTE-IDENTICALLY to one without it. A
|
|
2960
|
+
* new path segment would instead need a second route regex kept alive
|
|
2961
|
+
* indefinitely.
|
|
2962
|
+
* 2. FIVE SEPARATE PATTERNS ALREADY MATCH THIS URL, and every one of them
|
|
2963
|
+
* ends `(?:\?.*)?$` — `src/lib/map/tile-token-client.ts` TILE_URL_PATH
|
|
2964
|
+
* and `src/site/chart/sail-tile-token.ts` (which decide whether a tile
|
|
2965
|
+
* gets its Bearer), `packages/sdk/src/tile-auth.ts` TILE_URL_PATH,
|
|
2966
|
+
* `public/chrt-tile-sw.js` TILE_URL_RE (which also reads the region out of
|
|
2967
|
+
* the URL to pick its per-region cache), and
|
|
2968
|
+
* `src/site/offline/pack-protocol.ts` TILE_URL (which rewrites a tile to
|
|
2969
|
+
* a downloaded pack). Their optional PATH segment, by contrast, is
|
|
2970
|
+
* `[a-z][a-z0-9-]*` — letter-first so it cannot be confused with the
|
|
2971
|
+
* numeric `{z}` — and build ids are hex (`463b265e`, `4de67273`). A build
|
|
2972
|
+
* in the path would miss every one of them, and a tile those patterns
|
|
2973
|
+
* miss does not merely go uncached: it goes out with NO BEARER and comes
|
|
2974
|
+
* back 401, which MapLibre records as a permanently errored tile. That is
|
|
2975
|
+
* the exact failure the `.png` drift caused on staging-sail (see
|
|
2976
|
+
* `chrt-tile-sw.js`).
|
|
3097
2977
|
*
|
|
3098
|
-
*
|
|
3099
|
-
*
|
|
3100
|
-
*
|
|
3101
|
-
* zoom regardless of length.
|
|
3102
|
-
*/
|
|
3103
|
-
declare function buildLandRegionTierExpression(): ExpressionSpecification;
|
|
3104
|
-
/**
|
|
3105
|
-
* Land area tier (LNDARE): major vs. local.
|
|
3106
|
-
* 1 — Major (OBJNAM length <= 12)
|
|
3107
|
-
* 2 — Local
|
|
2978
|
+
* The query string is also what the caches this fix targets actually key on:
|
|
2979
|
+
* the browser HTTP cache, MapLibre's own tile cache, and the Service Worker's
|
|
2980
|
+
* `new Request(req.url)` entry key all include it.
|
|
3108
2981
|
*
|
|
3109
|
-
*
|
|
3110
|
-
|
|
3111
|
-
declare function buildLandAreaTierExpression(): ExpressionSpecification;
|
|
3112
|
-
/**
|
|
3113
|
-
* Lake tier (LAKARE): lake vs. reservoir/pond.
|
|
3114
|
-
* 1 — Lake (CATLAK=1, or OBJNAM length <= 12)
|
|
3115
|
-
* 2 — Reservoir/pond (CATLAK in {2,3}, or longer name)
|
|
3116
|
-
*/
|
|
3117
|
-
declare function buildLakeTierExpression(): ExpressionSpecification;
|
|
3118
|
-
/**
|
|
3119
|
-
* River tier (RIVERS): major vs. local.
|
|
3120
|
-
* 1 — Major river (OBJNAM length <= 15 AND no comma)
|
|
3121
|
-
* 2 — Local creek (else)
|
|
3122
|
-
*/
|
|
3123
|
-
declare function buildRiverTierExpression(): ExpressionSpecification;
|
|
3124
|
-
/**
|
|
3125
|
-
* Airport tier (AIRARE): major airport vs. small airstrip.
|
|
3126
|
-
* 1 — Major (OBJNAM length <= 25 — e.g. "Logan International Airport")
|
|
3127
|
-
* 2 — Airstrip
|
|
2982
|
+
* `v` rather than `build`: `?build=` is a taken name with a strict meaning on
|
|
2983
|
+
* the Worker (`?build=candidate`, employee-only, 400 on any other value).
|
|
3128
2984
|
*/
|
|
3129
|
-
declare
|
|
3130
|
-
interface LabelLayerConfig {
|
|
3131
|
-
/** Mapbox source layer type */
|
|
3132
|
-
type: "symbol";
|
|
3133
|
-
/** Text field expression or string */
|
|
3134
|
-
textField: ExpressionSpecification | string;
|
|
3135
|
-
/** Text size in pixels */
|
|
3136
|
-
textSize: number | ExpressionSpecification;
|
|
3137
|
-
/** Text color (hex) or data-driven expression */
|
|
3138
|
-
textColor: string | ExpressionSpecification;
|
|
3139
|
-
/** Halo color for contrast */
|
|
3140
|
-
textHaloColor: string;
|
|
3141
|
-
/** Halo width — pixels or zoom-interpolation expression */
|
|
3142
|
-
textHaloWidth: number | ExpressionSpecification;
|
|
3143
|
-
/** Text offset [x, y] in ems */
|
|
3144
|
-
textOffset: [number, number];
|
|
3145
|
-
/** Font stack */
|
|
3146
|
-
textFont?: string[];
|
|
3147
|
-
/** Additional layout properties */
|
|
3148
|
-
layout?: Record<string, unknown>;
|
|
3149
|
-
/** Minimum zoom level for this label */
|
|
3150
|
-
minzoom?: number;
|
|
3151
|
-
}
|
|
2985
|
+
declare const BUILD_PARAM = "v";
|
|
3152
2986
|
/**
|
|
3153
|
-
*
|
|
2987
|
+
* One tile-URL template — the single place a CHRT tile URL is spelled.
|
|
3154
2988
|
*
|
|
3155
|
-
*
|
|
3156
|
-
*
|
|
3157
|
-
*
|
|
2989
|
+
* `buildId` is encoded rather than interpolated raw: MapLibre substitutes
|
|
2990
|
+
* `{z}`/`{x}`/`{y}` by brace-matching the template, so an id containing a
|
|
2991
|
+
* brace would corrupt every tile request. Empty / whitespace-only ids emit no
|
|
2992
|
+
* parameter at all instead of a bare `?v=` that would key its own useless
|
|
2993
|
+
* cache namespace.
|
|
3158
2994
|
*/
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
2995
|
+
declare function tileTemplate(base: string, region: string, extension: "mvt" | "png", buildId?: string): string;
|
|
2996
|
+
/** Canonical source id used in `generateStyle()` — matches the region name
|
|
2997
|
+
* of the one consolidated PMTiles served by the tile-worker for this region. */
|
|
2998
|
+
declare const DEFAULT_REGION = "NOAA_ENC";
|
|
2999
|
+
interface BuildSourcesOptions {
|
|
3000
|
+
/** Which tile path to emit. Default: "pmtiles" (the supported path post-Mapbox). */
|
|
3001
|
+
mode?: SourceMode;
|
|
3002
|
+
/** Chart region. Default: "NOAA_ENC". */
|
|
3003
|
+
region?: string;
|
|
3162
3004
|
/**
|
|
3163
|
-
*
|
|
3164
|
-
* `
|
|
3165
|
-
*
|
|
3005
|
+
* Build id of the CHART region (`region`) — the `build_tag` a
|
|
3006
|
+
* `mint-tile-token` response hands back.
|
|
3007
|
+
*
|
|
3008
|
+
* Emitted as the {@link BUILD_PARAM} query parameter on that region's tile
|
|
3009
|
+
* template. See {@link tileTemplate} for why a build discriminator has to be
|
|
3010
|
+
* in the URL at all.
|
|
3011
|
+
*
|
|
3012
|
+
* ⚠ THIS COVERS THE CHART REGION ONLY. A token is minted for one chart
|
|
3013
|
+
* region and `CHRT_LAND` / `CHRT_RELIEF` ride it, so the JWT's `build_tag`
|
|
3014
|
+
* says nothing about a land cutover — the same blind spot that made the
|
|
3015
|
+
* Worker's edge-cache key wrong until `TILE_CACHE_VERSION` v3
|
|
3016
|
+
* (cloudflare/tile-worker/src/cache-encoding.ts). Pass {@link buildTags} to
|
|
3017
|
+
* discriminate the basemap sources too.
|
|
3166
3018
|
*/
|
|
3167
|
-
|
|
3019
|
+
buildTag?: string;
|
|
3168
3020
|
/**
|
|
3169
|
-
*
|
|
3170
|
-
*
|
|
3021
|
+
* Resolved build id per region — `{ NOAA_ENC: "…", CHRT_LAND: "…" }`.
|
|
3022
|
+
*
|
|
3023
|
+
* The complete form of {@link buildTag}: every source this style declares
|
|
3024
|
+
* gets its own discriminator, so a `CHRT_LAND` promotion turns over the land
|
|
3025
|
+
* URLs without touching the chart's (and vice versa). An entry here wins
|
|
3026
|
+
* over `buildTag` for the same region.
|
|
3027
|
+
*
|
|
3028
|
+
* This is the mint response's `build_tags` map verbatim (claim contract
|
|
3029
|
+
* v1.7) — `TileTokenResponse.buildTags` in both `lib/map/tile-token-client.ts`
|
|
3030
|
+
* and the SDK's `tile-auth.ts`. The same map already keys the tile Service
|
|
3031
|
+
* Worker's per-region caches; passing it here puts the same identity in the
|
|
3032
|
+
* URL, so the layer above the Service Worker stops mixing builds too.
|
|
3033
|
+
*
|
|
3034
|
+
* A region absent from the map simply gets no discriminator — the URL it
|
|
3035
|
+
* has always had. That is a deliberate soft edge: an older mint response, or
|
|
3036
|
+
* a region with no servable build, must degrade to today's behaviour rather
|
|
3037
|
+
* than emit a URL pinned to a build nobody resolved.
|
|
3171
3038
|
*/
|
|
3172
|
-
|
|
3039
|
+
buildTags?: Readonly<Record<string, string>>;
|
|
3040
|
+
/** Override tile-worker origin (e.g. staging). Default: DEFAULT_TILE_BASE_URL. */
|
|
3041
|
+
tileBaseUrl?: string;
|
|
3173
3042
|
/**
|
|
3174
|
-
*
|
|
3175
|
-
*
|
|
3043
|
+
* Emit the CHRTland vector land base as a second source (ADR 0023). Off by
|
|
3044
|
+
* default: it costs a source, and the region must be granted on the token.
|
|
3176
3045
|
*/
|
|
3177
|
-
|
|
3046
|
+
land?: boolean;
|
|
3047
|
+
/**
|
|
3048
|
+
* Emit CHRTland's terrarium relief as a raster-dem source. Separate from
|
|
3049
|
+
* `land` because relief needs a raster-capable worker AND a grant that
|
|
3050
|
+
* `land-regions.ts` still withholds.
|
|
3051
|
+
*/
|
|
3052
|
+
relief?: boolean;
|
|
3053
|
+
/**
|
|
3054
|
+
* Emit the CHRT_BASE world basemap as a third vector source — the dark
|
|
3055
|
+
* geography under everything, the tan jurisdiction fill, and the rough
|
|
3056
|
+
* inland water inside countries CHRT carries. Its layers sit UNDER the
|
|
3057
|
+
* no-coverage hatch's companions and everything else; see baseLayers().
|
|
3058
|
+
*/
|
|
3059
|
+
base?: boolean;
|
|
3178
3060
|
}
|
|
3179
3061
|
/**
|
|
3180
|
-
*
|
|
3062
|
+
* Build the "sources" block for a CHRT style.
|
|
3181
3063
|
*
|
|
3182
|
-
*
|
|
3183
|
-
*
|
|
3184
|
-
*
|
|
3185
|
-
*
|
|
3064
|
+
* - `mode: "mapbox"`: one mapbox:// url (kept for external style export only).
|
|
3065
|
+
* - `mode: "pmtiles"` (default): one vector tile endpoint for the region,
|
|
3066
|
+
* routed by the Worker to the one consolidated PMTiles:
|
|
3067
|
+
* `${tileBaseUrl}/v1/tiles/{region}/{z}/{x}/{y}.mvt`
|
|
3186
3068
|
*
|
|
3187
|
-
* `
|
|
3188
|
-
*
|
|
3189
|
-
*
|
|
3190
|
-
* must persist as the user zooms in, even if the broader-scope cell
|
|
3191
|
-
* carrying the OBJNAM is from a coarser band than the one rendering
|
|
3192
|
-
* features at the current zoom. Collision arbitration via
|
|
3193
|
-
* `ORIENTATION_BAND_SORT_KEY` gives the broader-scope (lower-band) copy
|
|
3194
|
-
* priority where the same OBJNAM exists in multiple bands.
|
|
3069
|
+
* Pass `buildTag` / `buildTags` to pin each source's URL to the build it is
|
|
3070
|
+
* serving — without that, one URL is shared by every build and a cutover
|
|
3071
|
+
* leaves the client rendering two of them at once. See {@link BUILD_PARAM}.
|
|
3195
3072
|
*/
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
/** Returns the rendering strategy for an S-57 class. Unknown classes default to band-gated. */
|
|
3199
|
-
declare function getLabelBehavior(layerName: string): LabelBehavior;
|
|
3073
|
+
declare function buildSources(opts?: BuildSourcesOptions): Record<string, AnySourceSpec>;
|
|
3074
|
+
|
|
3200
3075
|
/**
|
|
3201
|
-
*
|
|
3202
|
-
* for feature labels (portrayal-excellence P4). Converges the previous
|
|
3203
|
-
* per-mechanism patches (SAFETY_CRITICAL_LABELS allow-overlap, the
|
|
3204
|
-
* band-5/6-only Harbor collision discipline) into one explicit ranking.
|
|
3076
|
+
* DEPTH NUMBERS — how big the chart draws its depth figures.
|
|
3205
3077
|
*
|
|
3206
|
-
*
|
|
3207
|
-
*
|
|
3078
|
+
* Asked for from the helm (chip 68, 2026-10-05), by a captain running CHRTsail
|
|
3079
|
+
* desktop on a Raspberry Pi: *"I still need the depth numbers to be bolder
|
|
3080
|
+
* which may be a setting. I just can't sail the boat and adjust all that stuff
|
|
3081
|
+
* at the same time."* A set-and-forget choice, then, not a slider.
|
|
3208
3082
|
*
|
|
3209
|
-
*
|
|
3210
|
-
*
|
|
3211
|
-
*
|
|
3212
|
-
* merge unchanged.
|
|
3213
|
-
* 2. Label LAYER ORDER — MapLibre places symbols topmost-layer-first, so
|
|
3214
|
-
* `style-generator.ts` emits feature-label layers lowest-priority
|
|
3215
|
-
* first: safety-critical classes end up topmost and claim collision
|
|
3216
|
-
* space before anything else. (`symbol-sort-key` alone cannot do
|
|
3217
|
-
* this — it only orders placement WITHIN a layer.)
|
|
3083
|
+
* ===========================================================================
|
|
3084
|
+
* WHAT "LARGE" CHANGES, AND WHAT IT IS NOT ALLOWED TO TOUCH
|
|
3085
|
+
* ===========================================================================
|
|
3218
3086
|
*
|
|
3219
|
-
*
|
|
3220
|
-
*
|
|
3087
|
+
* It changes the SIZE of the glyphs (and, where a class was Regular, the
|
|
3088
|
+
* WEIGHT, to the Semibold soundings already use), the halo a little — see
|
|
3089
|
+
* `LARGE` for why less than the glyph — and the sounding collision padding —
|
|
3090
|
+
* see `LARGE_SOUNDING_PADDING_PX` for why that one moves.
|
|
3221
3091
|
*
|
|
3222
|
-
*
|
|
3223
|
-
*
|
|
3224
|
-
* (CBLOHD/PIPOHD VERCLR). Irreducible mariner-safety text.
|
|
3225
|
-
* 200 — Nav-aid designations: buoy / beacon `R "4"` labels.
|
|
3226
|
-
* 250 — Auxiliary nav-aid info: fog signal type (FOGSIG).
|
|
3227
|
-
* 300 — Depth field: soundings, contour values. Individually droppable —
|
|
3228
|
-
* a hidden sounding has visible neighbors.
|
|
3229
|
-
* 400 — Structures: bridges, landmarks, piers, moorings, buildings.
|
|
3230
|
-
* 500 — Ambient annotation: seabed nature, magnetic variation, kelp.
|
|
3231
|
-
* 900 — Orientation names (SEAARE etc.) — not part of this ladder;
|
|
3232
|
-
* they keep their settled watermark model (cell-band fan +
|
|
3233
|
-
* dominance composition + `orientationLabelLayout`) and always
|
|
3234
|
-
* paint underneath feature labels.
|
|
3092
|
+
* It does not touch, and `depth-label-size.test.ts` holds every one of these
|
|
3093
|
+
* equal to the Standard style in every palette and every symbol family:
|
|
3235
3094
|
*
|
|
3236
|
-
*
|
|
3237
|
-
*
|
|
3238
|
-
*
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
*
|
|
3243
|
-
*
|
|
3244
|
-
* layer
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
*
|
|
3249
|
-
* within-class key expression. The within-class key is clamped to
|
|
3250
|
-
* [0, 999] so it can never bleed into a neighboring rank's band.
|
|
3251
|
-
*/
|
|
3252
|
-
declare function labelSortKey(rank: number, within?: unknown): ExpressionSpecification | number;
|
|
3253
|
-
/**
|
|
3254
|
-
* Extract the trailing designation token from a nav-aid OBJNAM.
|
|
3095
|
+
* - `text-field` — the number itself, its unit conversion, its rounding.
|
|
3096
|
+
* ENC content is never altered; a bigger "4" is still the cell's "4".
|
|
3097
|
+
* - `text-color` / `text-halo-color` — §SOUNDG02's two shades against the
|
|
3098
|
+
* safety contour, and the palette that draws them (red night included:
|
|
3099
|
+
* it IS the NIGHT chart). A depth number shoaler than the contour stays
|
|
3100
|
+
* the loud one.
|
|
3101
|
+
* - `symbol-sort-key` — shallowest wins a collision, at any size.
|
|
3102
|
+
* - `filter`, `minzoom`, `maxzoom`, layer ids and layer order — so the
|
|
3103
|
+
* resident layer set the desktop builds at boot is the same set, and a
|
|
3104
|
+
* switch is `setLayoutProperty` / `setPaintProperty` on layers already
|
|
3105
|
+
* there. No layer and no draw call is added; what costs more is GPU fill,
|
|
3106
|
+
* because a bigger glyph covers more pixels (about 6–7 % more blended
|
|
3107
|
+
* fragments per pixel on the chart bench — the PR has the numbers).
|
|
3255
3108
|
*
|
|
3256
|
-
*
|
|
3257
|
-
*
|
|
3258
|
-
*
|
|
3259
|
-
* stopword type-name, or longer than 4 chars).
|
|
3109
|
+
* ===========================================================================
|
|
3110
|
+
* WHICH LABELS ARE "DEPTH NUMBERS"
|
|
3111
|
+
* ===========================================================================
|
|
3260
3112
|
*
|
|
3261
|
-
*
|
|
3262
|
-
*
|
|
3263
|
-
*
|
|
3113
|
+
* Exactly the ones the depth-unit switch converts (`buildLabelLayer` in
|
|
3114
|
+
* `layer-builder.ts`): soundings, contour values, and the depth printed beside
|
|
3115
|
+
* a rock, wreck or obstruction. The unit switch already treats those three as
|
|
3116
|
+
* one claim — its own note says a rock's figure "is the SAME depth claim as a
|
|
3117
|
+
* sounding" — and a size switch that enlarged the soundings around a rock but
|
|
3118
|
+
* left the rock's own depth small would make the hazard the quietest number
|
|
3119
|
+
* on that part of the chart.
|
|
3120
|
+
*
|
|
3121
|
+
* Not the dredged-channel note (`DRGNOTE`): it is a sentence fitted inside
|
|
3122
|
+
* its own channel polygon at a computed size, and scaling it would stop it
|
|
3123
|
+
* fitting. Not the bridge note: a clearance is a height, not a depth.
|
|
3124
|
+
*
|
|
3125
|
+
* ===========================================================================
|
|
3126
|
+
* WHY NOT A BOLD FACE
|
|
3127
|
+
* ===========================================================================
|
|
3128
|
+
*
|
|
3129
|
+
* The chart's glyph sets are Open Sans Regular, Semibold and Italic — the tile
|
|
3130
|
+
* worker's `/v1/glyphs` (`cloudflare/tile-worker/glyphs/GLYPHS.json`) and the
|
|
3131
|
+
* offline chart-assets pack serve those three and nothing else, and a
|
|
3132
|
+
* fontstack no glyph host serves is the failure `labels.ts`'s SOUNDG note
|
|
3133
|
+
* describes (Native lost every sounding). Soundings are already Semibold. So "bolder" here is
|
|
3134
|
+
* size: stroke width scales with the glyph, and at 1x device pixels (a Pi's
|
|
3135
|
+
* panel) a 14 px Semibold numeral is both heavier and crisper than a 10 px one.
|
|
3264
3136
|
*/
|
|
3265
|
-
|
|
3266
|
-
/**
|
|
3267
|
-
declare
|
|
3137
|
+
|
|
3138
|
+
/** The two choices, in presentation order. */
|
|
3139
|
+
declare const DEPTH_LABEL_SIZES: readonly ["standard", "large"];
|
|
3140
|
+
type DepthLabelSize = (typeof DEPTH_LABEL_SIZES)[number];
|
|
3268
3141
|
/**
|
|
3269
|
-
*
|
|
3142
|
+
* Standard is the chart as it has always been drawn, and it is what a style
|
|
3143
|
+
* generated without the option gets: byte-identical, so the served style, the
|
|
3144
|
+
* native-render goldens and every client that never asks are unchanged.
|
|
3270
3145
|
*/
|
|
3271
|
-
declare
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3146
|
+
declare const DEFAULT_DEPTH_LABEL_SIZE: DepthLabelSize;
|
|
3147
|
+
/** Case-insensitive; anything unrecognised is `null`, never a throw. */
|
|
3148
|
+
declare function parseDepthLabelSize(raw: string | null | undefined): DepthLabelSize | null;
|
|
3149
|
+
/** The S-57 classes whose label is a depth figure. See the header. */
|
|
3150
|
+
declare const DEPTH_LABEL_CLASSES: ReadonlySet<string>;
|
|
3276
3151
|
/**
|
|
3277
|
-
*
|
|
3278
|
-
*
|
|
3279
|
-
*
|
|
3152
|
+
* Sounding collision padding at Large, px. Standard is 6.
|
|
3153
|
+
*
|
|
3154
|
+
* ⚠ THIS IS THE ONE THAT DECIDES HOW MANY SOUNDINGS SURVIVE. MapLibre drops a
|
|
3155
|
+
* sounding whose box (glyphs + padding) overlaps one already placed — the
|
|
3156
|
+
* shallowest places first, so what drops is the deeper figure. A 1.4x numeral
|
|
3157
|
+
* inside Standard's 6 px padding lost a quarter of the soundings: bigger
|
|
3158
|
+
* numbers, fewer of them, which is not what was asked for. Trimming the
|
|
3159
|
+
* padding gives the box back.
|
|
3160
|
+
*
|
|
3161
|
+
* Measured 2026-10-05 on the chart bench (`scripts/chart-bench`, Boston, DAY,
|
|
3162
|
+
* 1280x800 at 1x), soundings placed, Standard → Large at this padding:
|
|
3163
|
+
*
|
|
3164
|
+
* z11.5 515 → 539 (+5%) z12.3 434 → 415 (−4%)
|
|
3165
|
+
* z13 374 → 366 (−2%) z14 326 → 311 (−5%)
|
|
3166
|
+
*
|
|
3167
|
+
* and at Standard's 6 px: 391 / 246 at z11.5 / z14 (−24% / −25%). 3 px kept
|
|
3168
|
+
* z14 level but put 17% MORE figures on the coastal view, which reads as
|
|
3169
|
+
* clutter rather than as the same chart drawn bigger.
|
|
3280
3170
|
*/
|
|
3281
|
-
declare
|
|
3171
|
+
declare const LARGE_SOUNDING_PADDING_PX = 3.5;
|
|
3282
3172
|
/**
|
|
3283
|
-
*
|
|
3284
|
-
* Adds `_lightLabel` property (e.g., "Fl(2) WR 4s 5M").
|
|
3173
|
+
* Apply a depth-label size to one generated label layer.
|
|
3285
3174
|
*
|
|
3286
|
-
*
|
|
3287
|
-
*
|
|
3288
|
-
*
|
|
3289
|
-
* on real tile features; if you change one, change both.
|
|
3175
|
+
* Standard — and any class that is not a depth figure — returns the SAME
|
|
3176
|
+
* object, untouched. Large returns a copy with only the properties listed in
|
|
3177
|
+
* the header changed.
|
|
3290
3178
|
*/
|
|
3291
|
-
declare function
|
|
3292
|
-
|
|
3293
|
-
declare const LABELED_LAYERS: Set<string>;
|
|
3179
|
+
declare function applyDepthLabelSize(objectClass: string, layer: StyleLayer, size: DepthLabelSize | undefined): StyleLayer;
|
|
3180
|
+
|
|
3294
3181
|
/**
|
|
3295
|
-
*
|
|
3296
|
-
*
|
|
3182
|
+
* Builds Mapbox GL Style layer specs from S-52 lookup entries.
|
|
3183
|
+
* Wraps the existing atlas resolveStyle() and adds source/source-layer/filter.
|
|
3297
3184
|
*/
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3185
|
+
|
|
3186
|
+
interface StyleLayer {
|
|
3187
|
+
id: string;
|
|
3188
|
+
type: string;
|
|
3189
|
+
source: string;
|
|
3190
|
+
"source-layer": string;
|
|
3191
|
+
filter?: unknown[];
|
|
3192
|
+
paint: Record<string, unknown>;
|
|
3193
|
+
layout?: Record<string, unknown>;
|
|
3194
|
+
minzoom?: number;
|
|
3195
|
+
maxzoom?: number;
|
|
3196
|
+
metadata?: Record<string, unknown>;
|
|
3197
|
+
}
|
|
3301
3198
|
/**
|
|
3302
|
-
*
|
|
3303
|
-
*
|
|
3199
|
+
* Build all Mapbox GL layers for a given S-57 object class.
|
|
3200
|
+
* Returns multiple layers (fill, outline, symbol, label, etc.).
|
|
3201
|
+
*
|
|
3202
|
+
* Post-consolidation: all S-57 classes live as MVT layers inside one
|
|
3203
|
+
* consolidated PMTiles per region; `source` is always the region name.
|
|
3204
|
+
*
|
|
3205
|
+
* `opts.safetyContour` is the mariner's safety depth in metres — it drives
|
|
3206
|
+
* the §CSYM02 isolated-danger ring on hazard classes. Defaults to
|
|
3207
|
+
* `DEFAULT_SAFETY_CONTOUR_M`, the same default the SOUNDG two-shade rule
|
|
3208
|
+
* uses, so the ring and the sounding colour always agree.
|
|
3304
3209
|
*/
|
|
3305
|
-
declare function
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
/** Orientation classes whose names render italic (water voice). */
|
|
3309
|
-
declare const PLACENAME_WATER_CLASSES: readonly string[];
|
|
3310
|
-
/** Orientation classes whose names render upright (land voice). */
|
|
3311
|
-
declare const PLACENAME_LAND_CLASSES: readonly string[];
|
|
3210
|
+
declare function buildLayersForClass(objectClass: string, ct: ColorTableName, sourceId?: string, opts?: {
|
|
3211
|
+
safetyContour?: number;
|
|
3212
|
+
}): StyleLayer[];
|
|
3312
3213
|
/**
|
|
3313
|
-
*
|
|
3314
|
-
*
|
|
3315
|
-
*
|
|
3316
|
-
*
|
|
3317
|
-
* LOWER sort keys first, and rank is minted lower-is-more-important
|
|
3318
|
-
* (tier major, bbox area minor), so when space runs out the biggest names
|
|
3319
|
-
* survive. That ranking is the per-zoom density governor P4 asked for.
|
|
3214
|
+
* Get the full ordered list of object classes for style generation.
|
|
3215
|
+
* Uses S52_DRAW_ORDER as base, then adds any missing classes from the
|
|
3216
|
+
* S-52 lookup table so a newly-ingested class automatically gets styled
|
|
3217
|
+
* without touching this file.
|
|
3320
3218
|
*/
|
|
3321
|
-
declare function
|
|
3219
|
+
declare function getOrderedClasses(): string[];
|
|
3322
3220
|
|
|
3323
3221
|
/**
|
|
3324
|
-
*
|
|
3325
|
-
* Thins dense GeoJSON feature sets by keeping only one representative
|
|
3326
|
-
* feature per grid cell per layer.
|
|
3327
|
-
*/
|
|
3328
|
-
interface DecimationOptions {
|
|
3329
|
-
/** Grid resolution (cells per axis). Default 80. */
|
|
3330
|
-
gridSize?: number;
|
|
3331
|
-
/** Zoom level below which decimation kicks in. Default 12. */
|
|
3332
|
-
zoomThreshold?: number;
|
|
3333
|
-
}
|
|
3334
|
-
/**
|
|
3335
|
-
* Zoom-adaptive grid resolution for decimation.
|
|
3336
|
-
*/
|
|
3337
|
-
declare function getGridSizeForZoom(zoom: number): number;
|
|
3338
|
-
/**
|
|
3339
|
-
* Decimate a GeoJSON FeatureCollection using spatial grid thinning.
|
|
3340
|
-
* Only runs when zoom < zoomThreshold. Returns the original FC otherwise.
|
|
3222
|
+
* Dominance fan-out collapse (P8 Phase 3.3 / D4 "axis 1").
|
|
3341
3223
|
*
|
|
3342
|
-
*
|
|
3343
|
-
*
|
|
3344
|
-
*
|
|
3345
|
-
*
|
|
3346
|
-
*
|
|
3224
|
+
* `makeBandVariants()` historically emitted, per (class, band): one
|
|
3225
|
+
* "not-dominated" layer plus up to five `-domBy{D}` copies that differ ONLY
|
|
3226
|
+
* in their dominance filter and a `maxzoom` of `dominatedVariantMaxzoom(D)`.
|
|
3227
|
+
* That fan existed because MapLibre filters could not read `["zoom"]`. They
|
|
3228
|
+
* can now (style-spec 24.8.5; buckets evaluate at the tile's `overscaledZ`),
|
|
3229
|
+
* so the whole fan folds into ONE layer per (class, band) whose filter
|
|
3230
|
+
* carries the zoom gate.
|
|
3231
|
+
*
|
|
3232
|
+
* **Construction principle — read before changing anything here.** The
|
|
3233
|
+
* collapsed filter is the literal `["any"]` UNION of the clauses the fan
|
|
3234
|
+
* already encoded: every variant the legacy emitter would have produced
|
|
3235
|
+
* contributes exactly one `["all", <its dominance filter>, ["<", ["zoom"],
|
|
3236
|
+
* <its maxzoom>]]` clause, and the dead-variant skip is mirrored too.
|
|
3237
|
+
* Equivalence is therefore *structural*, not re-derived — which matters,
|
|
3238
|
+
* because the two "obvious" hand-written forms are both wrong:
|
|
3239
|
+
*
|
|
3240
|
+
* 1. A `["match", ["get","_dominated_by_min"], 2,5, 3,7, 4,9, 5,11, 6,11, 24]`
|
|
3241
|
+
* threshold (the form the design doc proposed) uses band 6's *eligibility*
|
|
3242
|
+
* zoom 11. The real ceiling is `dominatedVariantMaxzoom("6") = 13` — band
|
|
3243
|
+
* 6's DATA floor. Using 11 reopens the z11–z12 void window that
|
|
3244
|
+
* `band-priority.ts` documents closing.
|
|
3245
|
+
* 2. That same form silently drops the legacy `_dominated: true` boolean,
|
|
3246
|
+
* which `dominatedByMinFilter("6")` still honours. A legacy-tagged feature
|
|
3247
|
+
* has no `_dominated_by_min`, so `match` falls to its default and the
|
|
3248
|
+
* feature renders FOREVER instead of dropping at z13.
|
|
3249
|
+
*
|
|
3250
|
+
* Deriving the gate from the emitter's own clauses avoids both by construction.
|
|
3251
|
+
* `band-collapse.test.ts` re-proves it on every CI run by differentially
|
|
3252
|
+
* evaluating legacy-vs-collapsed through MapLibre's real three gates.
|
|
3253
|
+
*
|
|
3254
|
+
* **Scope.** For FEATURE layers (fills, lines, feature symbols) this is
|
|
3255
|
+
* axis 1 ONLY: the per-band layers survive, with identical ids and identical
|
|
3256
|
+
* positions, so the band-major draw order is untouched. "Axis 2" (collapsing
|
|
3257
|
+
* the per-band copies into one layer per class) was evaluated and **KILLED**
|
|
3258
|
+
* for feature layers — it is unsound for the opaque-fill classes
|
|
3259
|
+
* (`DOMINANCE_EXEMPT_FILL_CLASSES` ≡ `OPAQUE_FILL_LAYERS`), where band-major
|
|
3260
|
+
* order is the ONLY thing separating the bands, and 15/15 class pairs are
|
|
3261
|
+
* provably unsatisfiable with one layer each. Do not reintroduce it there.
|
|
3262
|
+
* Evidence: `.chrt/perf/2026-07-14-p8-d4-spike.md`.
|
|
3263
|
+
*
|
|
3264
|
+
* LABEL layers are different (CHRTsail #121 — MapLibre Native iOS silently
|
|
3265
|
+
* collapses its whole render pass above 482 symbol layers, and the served
|
|
3266
|
+
* style carried 575): `makeCollapsedCrossBandLabel` folds a label's ×6 band
|
|
3267
|
+
* fan into ONE layer per class, and `collapsedOrientationGate` folds the
|
|
3268
|
+
* orientation fan's per-dominator variants into its per-cell layers. That is
|
|
3269
|
+
* NOT the killed axis 2, because what the fill argument protects — paint
|
|
3270
|
+
* order as the sole band separator — does not apply to labels: their
|
|
3271
|
+
* load-bearing order is the cross-class P4 priority ladder (each class keeps
|
|
3272
|
+
* exactly one layer in its ladder slot), and within-class placement priority
|
|
3273
|
+
* rides the `rank*1000 + within-key` symbol-sort-key that labels.ts
|
|
3274
|
+
* documents as designed to survive precisely this merge.
|
|
3275
|
+
*
|
|
3276
|
+
* **Load-bearing invariant.** A collapsed per-band FEATURE layer MUST keep
|
|
3277
|
+
* the `-band{B}` id segment: `custom-style.ts` `bandFloor()` parses
|
|
3278
|
+
* `/-band(\d)/` to clamp customer minzoom/scamin overrides to the band's
|
|
3279
|
+
* data floor, on the live public Style API path. Renaming the id silently
|
|
3280
|
+
* unclamps those overrides. Cross-band LABEL layers are the deliberate
|
|
3281
|
+
* exception: they carry every band floor INSIDE the filter (tile-zoom
|
|
3282
|
+
* clauses a customer override cannot touch), which supersedes the clamp —
|
|
3283
|
+
* `bandFloor()` returning 0 for a bare label id is correct, not a gap.
|
|
3284
|
+
* Both halves asserted in `band-collapse.test.ts`.
|
|
3347
3285
|
*/
|
|
3348
|
-
|
|
3349
|
-
west: number;
|
|
3350
|
-
south: number;
|
|
3351
|
-
east: number;
|
|
3352
|
-
north: number;
|
|
3353
|
-
}, opts?: DecimationOptions): GeoJSON.FeatureCollection;
|
|
3286
|
+
|
|
3354
3287
|
/**
|
|
3355
|
-
*
|
|
3288
|
+
* Which emitter the style generator uses for the dominance fan.
|
|
3289
|
+
* `"legacy"` exists so CI can differentially prove the two equivalent (it is
|
|
3290
|
+
* the oracle in `band-collapse.test.ts`) and as a one-line rollback. It is an
|
|
3291
|
+
* internal knob — deliberately NOT on the exported `StyleGeneratorOptions`,
|
|
3292
|
+
* so it cannot reach `@chrtco/sdk` consumers via `ChrtStyleOptions`.
|
|
3356
3293
|
*/
|
|
3357
|
-
|
|
3294
|
+
type BandFanMode = "collapsed" | "legacy";
|
|
3358
3295
|
|
|
3359
3296
|
/**
|
|
3360
|
-
*
|
|
3361
|
-
*
|
|
3362
|
-
* Complete symbology suite following:
|
|
3363
|
-
* - IHO S-52 Presentation Library (Ed 4.0)
|
|
3364
|
-
* - IALA Maritime Buoyage System R1001 (Region B for US waters)
|
|
3365
|
-
* - NOAA Chart No. 1 (Ed 13) / INT1
|
|
3366
|
-
*
|
|
3367
|
-
* Buoy shape terminology (US / Chart No. 1):
|
|
3368
|
-
* - CAN (Q20): Flat-top cylindrical buoy — Port mark in IALA-B (red)
|
|
3369
|
-
* - NUN (Q21): Conical/pointed-top buoy — Starboard mark in IALA-B (green)
|
|
3370
|
-
* - PILLAR: Tall narrow buoy — used for cardinal, isolated danger, etc.
|
|
3371
|
-
* - SPAR: Tall thin pole buoy
|
|
3372
|
-
* - SPHERICAL: Round buoy — safe water marks
|
|
3373
|
-
* - BARREL: Barrel/tun shaped buoy
|
|
3374
|
-
* - SUPER: Large navigation buoy / LANBY
|
|
3375
|
-
*
|
|
3376
|
-
* Cardinal mark topmark orientations (IALA):
|
|
3377
|
-
* - North: both cones point UP ▲▲
|
|
3378
|
-
* - South: both cones point DOWN ▼▼
|
|
3379
|
-
* - East: cones base-to-base (diamond) ◆
|
|
3380
|
-
* - West: cones point-to-point (hourglass) ⊗
|
|
3381
|
-
*
|
|
3382
|
-
* Each symbol is a compact SVG at 32×32 for Mapbox GL `map.addImage()`.
|
|
3297
|
+
* Generates a complete Mapbox GL Style Specification v8 JSON
|
|
3298
|
+
* from the S-52 atlas definitions.
|
|
3383
3299
|
*/
|
|
3384
|
-
|
|
3385
|
-
interface
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
width: number;
|
|
3394
|
-
pattern?: string;
|
|
3395
|
-
color: string;
|
|
3396
|
-
}
|
|
3397
|
-
/** Fill element used in the SVG */
|
|
3398
|
-
interface SymbolFillElement {
|
|
3399
|
-
element: string;
|
|
3400
|
-
color: string;
|
|
3401
|
-
opacity?: number;
|
|
3402
|
-
}
|
|
3403
|
-
interface NauticalSymbol {
|
|
3404
|
-
id: string;
|
|
3405
|
-
label: string;
|
|
3406
|
-
/** INT1 / Chart No. 1 reference */
|
|
3407
|
-
int1Ref: string;
|
|
3408
|
-
/** Chart No. 1 section letter */
|
|
3409
|
-
section: string;
|
|
3410
|
-
getSvg: () => string;
|
|
3411
|
-
/** Generate SVG with theme-specific colors (for bridge icons etc.) */
|
|
3412
|
-
getThemedSvg?: (chblk: string, movable: string) => string;
|
|
3413
|
-
/** What this symbol represents on a chart */
|
|
3414
|
-
description?: string;
|
|
3415
|
-
/** S-52 Presentation Library symbol name */
|
|
3416
|
-
s52PlRef?: string;
|
|
3417
|
-
/** S-57 object class (e.g. "LNDMRK") when it can't be derived from s52PlRef's prefix */
|
|
3418
|
-
s57Class?: string;
|
|
3419
|
-
/** Grouping key for family clustering */
|
|
3420
|
-
group?: string;
|
|
3421
|
-
/** IDs of related variant symbols */
|
|
3422
|
-
variants?: string[];
|
|
3423
|
-
/** S-57 attribute that selects this variant */
|
|
3424
|
-
attributeKey?: string;
|
|
3425
|
-
/** Value of that attribute for this variant */
|
|
3426
|
-
attributeValue?: number;
|
|
3427
|
-
/** Example label strings seen on charts */
|
|
3428
|
-
labelExamples?: string[];
|
|
3429
|
-
/** What the color represents */
|
|
3430
|
-
colorMeaning?: string;
|
|
3431
|
-
/** Colors used in the SVG */
|
|
3432
|
-
colors?: SymbolColor[];
|
|
3433
|
-
/** Line/stroke styles used in the SVG */
|
|
3434
|
-
lineStyles?: SymbolLineStyle[];
|
|
3435
|
-
/** Fill regions in the SVG */
|
|
3436
|
-
fillElements?: SymbolFillElement[];
|
|
3437
|
-
/** Expanded navigational usage context (2-4 sentences) */
|
|
3438
|
-
usageContext?: string;
|
|
3439
|
-
/** Render size for documentation */
|
|
3440
|
-
renderSize?: string;
|
|
3441
|
-
}
|
|
3442
|
-
/** A logical grouping of related symbols */
|
|
3443
|
-
interface SymbolGroup {
|
|
3444
|
-
id: string;
|
|
3445
|
-
label: string;
|
|
3446
|
-
section: string;
|
|
3447
|
-
description: string;
|
|
3448
|
-
symbolIds: string[];
|
|
3300
|
+
|
|
3301
|
+
interface MapboxStyle {
|
|
3302
|
+
version: 8;
|
|
3303
|
+
name: string;
|
|
3304
|
+
metadata: Record<string, unknown>;
|
|
3305
|
+
sources: Record<string, unknown>;
|
|
3306
|
+
sprite?: string;
|
|
3307
|
+
glyphs: string;
|
|
3308
|
+
layers: StyleLayer[];
|
|
3449
3309
|
}
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3310
|
+
interface StyleGeneratorOptions extends BuildSourcesOptions {
|
|
3311
|
+
/**
|
|
3312
|
+
* When set, emit a "paper chart" style centered on the selected scale
|
|
3313
|
+
* band, with graceful coverage fallback: the requested band's layers
|
|
3314
|
+
* draw on top where its cells have data; coarser bands (driven by
|
|
3315
|
+
* `CHART_CASCADE_CODES`) fill gaps where the requested band has no
|
|
3316
|
+
* cells. Per-feature SCAMIN minzooms are preserved on every cascade
|
|
3317
|
+
* variant; `maxzoom` is dropped so the user can zoom in indefinitely.
|
|
3318
|
+
*
|
|
3319
|
+
* When omitted (default), continuous mode emits one layer copy per
|
|
3320
|
+
* source band with strict per-band zoom windows so exactly one band
|
|
3321
|
+
* renders at any given continuous zoom.
|
|
3322
|
+
*
|
|
3323
|
+
* `lockedBounds` (optional) restricts chart-mode rendering to a
|
|
3324
|
+
* specific bbox via a `["within"]` filter — applied ONLY to the
|
|
3325
|
+
* requested band's variants. Cascade fallback bands render across the
|
|
3326
|
+
* full viewport so a chart-Harbor user panning offshore still sees
|
|
3327
|
+
* Approach/Coastal data. The frontend pairs this with a translucent
|
|
3328
|
+
* grey overlay outside the bbox so the lock boundary is still visible
|
|
3329
|
+
* to the user (the fallback data is dimmed by the overlay but not
|
|
3330
|
+
* filtered out).
|
|
3331
|
+
*/
|
|
3332
|
+
chartMode?: {
|
|
3333
|
+
band: ScaleBand$1;
|
|
3334
|
+
lockedBounds?: BBox;
|
|
3335
|
+
};
|
|
3336
|
+
/**
|
|
3337
|
+
* Display unit for depth labels (SOUNDG soundings, DEPCNT contour
|
|
3338
|
+
* values). Source data is always meters (S-57 / VALSOU / VALDCO);
|
|
3339
|
+
* "feet" wraps the text-field expression with a unit conversion +
|
|
3340
|
+
* round so the rendered numbers match. Default "meters".
|
|
3341
|
+
*/
|
|
3342
|
+
depthUnits?: "meters" | "feet";
|
|
3343
|
+
/**
|
|
3344
|
+
* Which symbol artwork the style references. "s52" (default) uses the
|
|
3345
|
+
* PresLib-derived S-52 set; "s101" rewrites icon references to the
|
|
3346
|
+
* official S-101 Portrayal Catalogue symbols (s101: image namespace)
|
|
3347
|
+
* where a counterpart exists — see s101-style.ts. "chrt" applies the
|
|
3348
|
+
* CHRT house ATON/LIGHTS glyphs with colour-true tinting — see
|
|
3349
|
+
* chrt-style.ts. Selection logic differences are documented per module.
|
|
3350
|
+
*/
|
|
3351
|
+
symbolSet?: "s52" | "s101" | "chrt" | "raster";
|
|
3352
|
+
/**
|
|
3353
|
+
* The mariner's safety contour in metres — the depth below which a
|
|
3354
|
+
* feature is "dangerous to my hull". Drives both safety-contour
|
|
3355
|
+
* conditional symbology rules:
|
|
3356
|
+
*
|
|
3357
|
+
* - §SOUNDG02 — soundings shoaler than this render in the
|
|
3358
|
+
* high-contrast color; deeper soundings render in the muted color.
|
|
3359
|
+
* - §CSYM02 — isolated dangers (rocks / wrecks / obstructions)
|
|
3360
|
+
* shoaler than this get the DNGCIR01 danger ring.
|
|
3361
|
+
*
|
|
3362
|
+
* Default `DEFAULT_SAFETY_CONTOUR_M` (10 m).
|
|
3363
|
+
*
|
|
3364
|
+
* Does not affect the DEPARE depth-area shading, whose 2/5/10 m bands
|
|
3365
|
+
* are a separate S-52 concept.
|
|
3366
|
+
*/
|
|
3367
|
+
safetyContour?: number;
|
|
3368
|
+
/**
|
|
3369
|
+
* When false, all soundings render in a single shade. Default true.
|
|
3370
|
+
*/
|
|
3371
|
+
twoShadeSoundings?: boolean;
|
|
3372
|
+
/**
|
|
3373
|
+
* Label model for the 9 orientation place-name classes (SEAARE, LNDRGN,
|
|
3374
|
+
* LAKARE, RIVERS, CANALS, BUAARE, AIRARE, LNDARE, PRDARE).
|
|
3375
|
+
*
|
|
3376
|
+
* "legacy" (default) — the per-cell-band orientation fan
|
|
3377
|
+
* (fanOrientationLabelByCellBand): one label per feature per band,
|
|
3378
|
+
* deconflicted only by `_label_anchor` tags and watermark opacity.
|
|
3379
|
+
*
|
|
3380
|
+
* "placename" — 2 PLACENAME symbol layers over the build-side
|
|
3381
|
+
* place-name index (CHRTbaremetal placeNameIndex.ts): one collision-
|
|
3382
|
+
* managed label per named place with a per-feature zoom window; the
|
|
3383
|
+
* orientation fan for those classes is NOT emitted. Requires tiles
|
|
3384
|
+
* built with the PLACENAME side index — on older tiles the layers
|
|
3385
|
+
* simply draw nothing (soft-fail is index-side), which is why the
|
|
3386
|
+
* default stays "legacy" until L2c's rebuild + Maine-coast visual
|
|
3387
|
+
* verification flips it (docs/design/chart-label-deconfliction.md
|
|
3388
|
+
* §2.3). Feature-label classes are untouched either way.
|
|
3389
|
+
*/
|
|
3390
|
+
labels?: "legacy" | "placename";
|
|
3391
|
+
/**
|
|
3392
|
+
* Font weight for SOUNDG labels. Default "semibold" — crisper numerals
|
|
3393
|
+
* at small sizes on screen.
|
|
3394
|
+
*/
|
|
3395
|
+
soundingFontWeight?: "regular" | "semibold";
|
|
3396
|
+
/**
|
|
3397
|
+
* How big the depth figures are drawn — soundings, contour values and the
|
|
3398
|
+
* depth beside a rock, wreck or obstruction. "standard" (default) is
|
|
3399
|
+
* byte-identical to omitting it; "large" enlarges those labels only, and
|
|
3400
|
+
* never their text, colours, sort keys, filters or layer set. See
|
|
3401
|
+
* depth-label-size.ts.
|
|
3402
|
+
*/
|
|
3403
|
+
depthLabelSize?: DepthLabelSize;
|
|
3455
3404
|
}
|
|
3456
|
-
declare
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3405
|
+
declare function generateStyle(palette?: ColorTableName, opts?: StyleGeneratorOptions & {
|
|
3406
|
+
bandFan?: BandFanMode;
|
|
3407
|
+
}): MapboxStyle;
|
|
3408
|
+
declare function generateStyleJSON(palette?: ColorTableName, opts?: StyleGeneratorOptions): string;
|
|
3409
|
+
/** Get summary stats about the generated style */
|
|
3410
|
+
declare function getStyleStats(style: MapboxStyle): {
|
|
3411
|
+
totalLayers: number;
|
|
3412
|
+
fillLayers: number;
|
|
3413
|
+
lineLayers: number;
|
|
3414
|
+
symbolLayers: number;
|
|
3415
|
+
circleLayers: number;
|
|
3416
|
+
sources: number;
|
|
3417
|
+
objectClasses: Set<string>;
|
|
3418
|
+
};
|
|
3419
|
+
|
|
3420
|
+
/**
|
|
3421
|
+
* The e-ink portrayal pass — what `EINK_COLOR`, `EINK_MONO` and `EINK_NIGHT`
|
|
3422
|
+
* change beyond their colour tables. Night is mono inverted: everything below
|
|
3423
|
+
* applies, the patterns and safety contour are drawn LIGHT (the patterns are
|
|
3424
|
+
* themed per palette, the contour takes the table's DEPSC), and the chart
|
|
3425
|
+
* background gets the no-coverage crosshatch, because a black no-data hole
|
|
3426
|
+
* on a black-water page would read as deep water.
|
|
3427
|
+
*
|
|
3428
|
+
* A colour table can only move colours. E-paper needs more than that (owner
|
|
3429
|
+
* decision 2026-10-05: CHRT serves the e-ink chart, clients never recolour it;
|
|
3430
|
+
* requirements in CHRTsail's e-ink product spec §3c):
|
|
3431
|
+
*
|
|
3432
|
+
* 1. MEANING UNCHANGED. Nothing here adds, removes or reorders a feature
|
|
3433
|
+
* class or changes a filter that decides WHICH features draw. It changes
|
|
3434
|
+
* how they look, and adds two kinds of OVERLAY layer (depth patterns,
|
|
3435
|
+
* the safety contour) that draw features the chart already draws.
|
|
3436
|
+
* 2. MONO STANDS ON ITS OWN. Depth steps become fill PATTERNS (mono only);
|
|
3437
|
+
* danger areas get a cross-hatch; the safety contour gets its own heavy
|
|
3438
|
+
* line; restricted/caution areas keep their dashes, now heavier.
|
|
3439
|
+
* 3. DEPTH IN AT MOST FOUR STEPS. The tables do the colour side (DEPMD ==
|
|
3440
|
+
* DEPDW). Mono shows three: drying (hatch), shallower than the safety
|
|
3441
|
+
* contour (stipple), safe (paper).
|
|
3442
|
+
* 4. SAFETY CONTOUR AND DANGERS EMPHASISED: a heavy black safety-contour
|
|
3443
|
+
* line; danger symbols drawn larger; danger areas cross-hatched.
|
|
3444
|
+
* 5. COVERAGE PORTRAYAL SURVIVES: the no-coverage crosshatch goes to full
|
|
3445
|
+
* strength rather than being dropped with the other translucency.
|
|
3446
|
+
* 6. ATTRIBUTION/CURRENCY METADATA: untouched — this pass never edits
|
|
3447
|
+
* `sources` or the metadata other than adding `chrt:eink`.
|
|
3448
|
+
* 7. SIZES FOR 150 ppi COLOUR / 300 ppi MONO: every line ×1.5 (min 1 px),
|
|
3449
|
+
* text ×1.15 with a solid paper halo, no translucency, no blur, no fades.
|
|
3450
|
+
*
|
|
3451
|
+
* Translucency is the thing e-paper cannot draw: a 10% magenta wash over pale
|
|
3452
|
+
* blue is a fifth grey in mono and nothing at all on Kaleido 3. So faint washes
|
|
3453
|
+
* (< 0.3) are dropped — every one of them is a CHRT addition over a feature
|
|
3454
|
+
* whose boundary and symbol S-52 already draws — and stronger ones are made
|
|
3455
|
+
* solid.
|
|
3456
|
+
*
|
|
3457
|
+
* Pure: takes a generated style, returns a new one. `generateStyle` applies it
|
|
3458
|
+
* for the e-ink tables, so the served style, the offline style and the SDK's
|
|
3459
|
+
* local `generateStyle` all carry the same portrayal.
|
|
3465
3460
|
*/
|
|
3466
|
-
|
|
3461
|
+
|
|
3462
|
+
/** The three e-ink fill patterns (house glyphs, registered with the world hatches). */
|
|
3463
|
+
declare const EINK_DOTS_PATTERN = "chrt:eink-dots";
|
|
3464
|
+
declare const EINK_HATCH_PATTERN = "chrt:eink-hatch";
|
|
3465
|
+
declare const EINK_DANGER_PATTERN = "chrt:eink-danger";
|
|
3466
|
+
/** The VALDCO values that ARE the safety contour, one per ladder. */
|
|
3467
|
+
declare function safetyContourValues(safetyContourM: number): number[];
|
|
3468
|
+
interface EinkPortrayalOptions {
|
|
3469
|
+
/** The mariner's safety contour, metres — the same value the generator used. */
|
|
3470
|
+
safetyContour?: number;
|
|
3471
|
+
}
|
|
3467
3472
|
/**
|
|
3468
|
-
*
|
|
3469
|
-
*
|
|
3470
|
-
* they require a DOM (use `new Image()` + `map.addImage()`).
|
|
3473
|
+
* Apply the e-ink portrayal for `palette`. Returns the style unchanged for a
|
|
3474
|
+
* non-e-ink palette, so a caller may apply it unconditionally.
|
|
3471
3475
|
*/
|
|
3472
|
-
|
|
3473
|
-
declare function getSymbolSvgString(symbolId: string): string | null;
|
|
3474
|
-
declare const CHART_SECTIONS: ChartSection[];
|
|
3475
|
-
declare const SYMBOL_GROUPS: SymbolGroup[];
|
|
3476
|
-
/** Generate a single SVG sprite sheet containing all symbols as <symbol> elements */
|
|
3477
|
-
declare function generateSpriteSheet(): string;
|
|
3478
|
-
/** Generate a JSON manifest mapping symbol IDs to metadata */
|
|
3479
|
-
declare function generateSpriteManifest(): Record<string, {
|
|
3480
|
-
label: string;
|
|
3481
|
-
int1Ref: string;
|
|
3482
|
-
section: string;
|
|
3483
|
-
group?: string;
|
|
3484
|
-
s52PlRef?: string;
|
|
3485
|
-
description?: string;
|
|
3486
|
-
attributeKey?: string;
|
|
3487
|
-
attributeValue?: number;
|
|
3488
|
-
}>;
|
|
3476
|
+
declare function applyEinkPortrayal(style: MapboxStyle, palette: ColorTableName, opts?: EinkPortrayalOptions): MapboxStyle;
|
|
3489
3477
|
|
|
3490
3478
|
/**
|
|
3491
|
-
*
|
|
3479
|
+
* Light arithmetic for the chart palettes: how much light a colour emits, and
|
|
3480
|
+
* how to dim a colour without changing its hue.
|
|
3492
3481
|
*
|
|
3493
|
-
*
|
|
3494
|
-
*
|
|
3495
|
-
*
|
|
3496
|
-
*
|
|
3497
|
-
*
|
|
3482
|
+
* Everything here works in LINEAR light (WCAG 2.x relative luminance, sRGB
|
|
3483
|
+
* primaries). That is the quantity a dark-adapted eye responds to, and it is
|
|
3484
|
+
* the one `sounding-legibility.test.ts` already measures soundings in. Scaling
|
|
3485
|
+
* the sRGB-ENCODED channels instead would dim dark colours far more than
|
|
3486
|
+
* bright ones and shift every hue it touched.
|
|
3498
3487
|
*
|
|
3499
|
-
*
|
|
3500
|
-
*
|
|
3501
|
-
*
|
|
3502
|
-
*
|
|
3503
|
-
*
|
|
3488
|
+
* The one derivation the palettes rely on, and the reason this file exists:
|
|
3489
|
+
* NIGHT's deeper sounding SNDG1 (#897350) is SNDG2 (#c8aa78) at 43% of its
|
|
3490
|
+
* linear light. `labels.ts` builds its NIGHT secondary text the same way, so
|
|
3491
|
+
* the two stay one family by construction rather than by two hand-typed hexes
|
|
3492
|
+
* that happen to agree.
|
|
3493
|
+
*/
|
|
3494
|
+
/** WCAG 2.x relative luminance of a `#rrggbb` colour, 0 (black) to 1 (white). */
|
|
3495
|
+
declare function relativeLuminance(hex: string): number;
|
|
3496
|
+
/** WCAG 2.x contrast ratio between two `#rrggbb` colours, 1 to 21. */
|
|
3497
|
+
declare function contrastRatio(a: string, b: string): number;
|
|
3498
|
+
/**
|
|
3499
|
+
* The same hue at `factor` times its linear light. `factor` above 1 can clip a
|
|
3500
|
+
* channel, which shifts the hue; nothing in the palettes brightens, so callers
|
|
3501
|
+
* pass 0–1.
|
|
3502
|
+
*/
|
|
3503
|
+
declare function scaleLinearLight(hex: string, factor: number): string;
|
|
3504
|
+
/**
|
|
3505
|
+
* `hex` dimmed, hue kept, until its luminance is at most `ceiling`. A colour
|
|
3506
|
+
* already at or under the ceiling comes back unchanged (lower-cased).
|
|
3507
|
+
*/
|
|
3508
|
+
declare function capLuminance(hex: string, ceiling: number): string;
|
|
3509
|
+
/**
|
|
3510
|
+
* NIGHT's two ink levels, shared by every family's text and marks.
|
|
3504
3511
|
*
|
|
3505
|
-
*
|
|
3506
|
-
*
|
|
3512
|
+
* `NIGHT_INK` S52_NIGHT.CHBLK — the palette's linework and navigation
|
|
3513
|
+
* text. The brightest thing NIGHT draws on purpose.
|
|
3514
|
+
* `NIGHT_MUTED_INK` that ink at 43% of its linear light, which is how
|
|
3515
|
+
* S52_NIGHT.SNDG1 (the deeper soundings) was derived.
|
|
3516
|
+
* Everything that orients rather than navigates is drawn
|
|
3517
|
+
* at or under this, and `night-luminance.test.ts` holds
|
|
3518
|
+
* every visible NIGHT colour to it unless an exemption
|
|
3519
|
+
* names a reason.
|
|
3507
3520
|
*/
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
featureClass: string;
|
|
3511
|
-
/** Human-readable name */
|
|
3512
|
-
name: string;
|
|
3513
|
-
/** S-57 6-char equivalent acronym, if any */
|
|
3514
|
-
s57Equivalent?: string;
|
|
3515
|
-
/** Chart No. 1 section letter */
|
|
3516
|
-
section: string;
|
|
3517
|
-
/** Group key for clustering */
|
|
3518
|
-
group: string;
|
|
3519
|
-
/** Feature category */
|
|
3520
|
-
category: "geo" | "meta" | "info";
|
|
3521
|
-
/** Description of the feature */
|
|
3522
|
-
description: string;
|
|
3523
|
-
/** S-100 Portrayal Catalogue reference */
|
|
3524
|
-
portrayalRef?: string;
|
|
3525
|
-
/** True if this feature has no S-57 equivalent */
|
|
3526
|
-
isNewInS101: boolean;
|
|
3527
|
-
/** Key attributes specific to this feature */
|
|
3528
|
-
attributes?: string[];
|
|
3529
|
-
}
|
|
3530
|
-
declare const S101_FEATURES: S101Feature[];
|
|
3531
|
-
declare const S101_CHART_SECTIONS: {
|
|
3532
|
-
id: string;
|
|
3533
|
-
label: string;
|
|
3534
|
-
description: string;
|
|
3535
|
-
}[];
|
|
3536
|
-
declare const S101_SYMBOL_GROUPS: {
|
|
3537
|
-
id: string;
|
|
3538
|
-
label: string;
|
|
3539
|
-
section: string;
|
|
3540
|
-
description: string;
|
|
3541
|
-
}[];
|
|
3521
|
+
declare const NIGHT_INK: string;
|
|
3522
|
+
declare const NIGHT_MUTED_INK: string;
|
|
3542
3523
|
|
|
3543
3524
|
/**
|
|
3544
|
-
*
|
|
3525
|
+
* Is this MapLibre map still there to be written to?
|
|
3545
3526
|
*
|
|
3546
|
-
*
|
|
3547
|
-
*
|
|
3548
|
-
*
|
|
3527
|
+
* ===========================================================================
|
|
3528
|
+
* ⚠ ASK AFTER EVERY AWAIT. A MAP CAN BE REMOVED WHILE YOU WERE WAITING.
|
|
3529
|
+
* ===========================================================================
|
|
3549
3530
|
*
|
|
3550
|
-
*
|
|
3531
|
+
* `map.remove()` deletes `map.style`, and after that nearly every method that
|
|
3532
|
+
* touches the style throws rather than returning: `hasImage`, `addImage`,
|
|
3533
|
+
* `updateImage`, `getSource`, `addLayer` all fail with "Cannot read properties
|
|
3534
|
+
* of undefined (reading 'getImage')" and its siblings. Code that was handed a
|
|
3535
|
+
* map, awaited a decode, an IndexedDB read or a fetch, and then wrote to the
|
|
3536
|
+
* map, throws from wherever it resumed — usually a promise nobody is awaiting,
|
|
3537
|
+
* so the throw is an uncaught error with no caller to explain it.
|
|
3538
|
+
*
|
|
3539
|
+
* Measured in CHRTdesktop (chip 63, 2026-10-04): with the page's main thread
|
|
3540
|
+
* held at 6× CPU, the chart removed its map in the middle of a pan, and the
|
|
3541
|
+
* S-52 image loader resumed onto it:
|
|
3542
|
+
*
|
|
3543
|
+
* TypeError: Cannot read properties of undefined (reading 'getImage')
|
|
3544
|
+
* at Map.hasImage
|
|
3545
|
+
* at addImageToMap (s52-image-cache.ts)
|
|
3546
|
+
*
|
|
3547
|
+
* The rule, for anything in this package or the app that takes a map: after
|
|
3548
|
+
* an `await` (or in a `.then`, a frame callback, an `onload`), check this
|
|
3549
|
+
* before the first call on the map, and stop quietly if it says no. A removed
|
|
3550
|
+
* map is not an error to report — whoever removed it is building the next one.
|
|
3551
|
+
*
|
|
3552
|
+
* ⚠ `_removed`, NOT `style`. maplibre sets `_removed = true` as the last step
|
|
3553
|
+
* of `remove()` (typed on `Map` in maplibre-gl 4 and 5), so it is the fact,
|
|
3554
|
+
* where `style === undefined` is a consequence. Test doubles that never had a
|
|
3555
|
+
* `style` read as live, which is what they are. The app pins the maplibre side
|
|
3556
|
+
* of this (`map-live.test.ts`), so an upgrade that renames the field fails a
|
|
3557
|
+
* test rather than silently making every check say yes.
|
|
3558
|
+
*
|
|
3559
|
+
* Typed `object` so the structural map shapes the app passes around (a tile
|
|
3560
|
+
* census, an errored-tile tracker) can be asked too, not only `maplibregl.Map`.
|
|
3551
3561
|
*/
|
|
3562
|
+
declare function isMapLive(map: object): boolean;
|
|
3552
3563
|
|
|
3553
|
-
|
|
3564
|
+
/** S-52 display categories – controls default visibility */
|
|
3565
|
+
type DisplayCategory = "BASE" | "STANDARD" | "OTHER" | "MARINERS" | "META";
|
|
3566
|
+
/** Mapbox GL layer type we'll use for this entry */
|
|
3567
|
+
type GeomType = "fill" | "line" | "circle" | "symbol";
|
|
3568
|
+
/** Nautical groupings (loosely follows Chart No. 1 sections) */
|
|
3569
|
+
type NauticalCategory = "Depths" | "Land" | "Navigation Aids" | "Hazards" | "Regulated Areas" | "Infrastructure" | "Meta";
|
|
3570
|
+
/** Paint properties – a subset we actually use */
|
|
3571
|
+
interface AtlasStyle {
|
|
3572
|
+
type: GeomType;
|
|
3573
|
+
paint: Record<string, unknown>;
|
|
3574
|
+
layout?: Record<string, unknown>;
|
|
3575
|
+
/** Nautical symbol ID for symbol-type layers */
|
|
3576
|
+
iconImage?: string;
|
|
3577
|
+
}
|
|
3578
|
+
/** One row in the S-52 lookup table */
|
|
3579
|
+
interface LookupEntry {
|
|
3580
|
+
/** S-57 object class acronym */
|
|
3581
|
+
objectClass: string;
|
|
3582
|
+
/** Human-readable name */
|
|
3583
|
+
name: string;
|
|
3584
|
+
/** Chart No. 1 section */
|
|
3585
|
+
category: NauticalCategory;
|
|
3586
|
+
/** S-52 display category */
|
|
3587
|
+
displayCategory: DisplayCategory;
|
|
3588
|
+
/** Default style using S-52 color tokens (resolved later) */
|
|
3589
|
+
style: AtlasStyle;
|
|
3590
|
+
/** Whether conditional symbology may override the style */
|
|
3591
|
+
hasConditional?: boolean;
|
|
3592
|
+
/** Attributes that affect styling */
|
|
3593
|
+
conditionalAttributes?: string[];
|
|
3594
|
+
/** INT1 / Chart No. 1 reference (e.g. "Q130.1") */
|
|
3595
|
+
int1Ref?: string;
|
|
3596
|
+
/** S-52 viewing group number */
|
|
3597
|
+
viewingGroup?: number;
|
|
3598
|
+
/** Minimum compilation scale for display (SCAMIN) */
|
|
3599
|
+
scamin?: number;
|
|
3600
|
+
/**
|
|
3601
|
+
* Mark this class as deliberately invisible (label-only or metadata-only)
|
|
3602
|
+
* so the layer-coverage audit doesn't flag its geometry-type gaps as bugs.
|
|
3603
|
+
*
|
|
3604
|
+
* Examples:
|
|
3605
|
+
* - SOUNDG: rendered as depth numbers via labels.ts, not as visible dots
|
|
3606
|
+
* - LNDRGN: region NAME labels only, no shape
|
|
3607
|
+
* - M_NPUB / M_NSYS / M_QUAL / M_SREL / DSID: S-57 metadata classes;
|
|
3608
|
+
* present for click-query attributes, never drawn
|
|
3609
|
+
*
|
|
3610
|
+
* Without this flag, `scripts/audit-layer-coverage.ts` reports the
|
|
3611
|
+
* thousands of features in these classes as "gaps" every week even
|
|
3612
|
+
* though the invisibility is intentional.
|
|
3613
|
+
*/
|
|
3614
|
+
auditIgnore?: boolean;
|
|
3615
|
+
}
|
|
3616
|
+
/** Resolved style ready for Mapbox GL (tokens → hex) */
|
|
3617
|
+
interface ResolvedStyle {
|
|
3618
|
+
type: GeomType;
|
|
3619
|
+
paint: Record<string, unknown>;
|
|
3620
|
+
layout?: Record<string, unknown>;
|
|
3621
|
+
minzoom?: number;
|
|
3622
|
+
maxzoom?: number;
|
|
3623
|
+
}
|
|
3554
3624
|
|
|
3555
3625
|
/**
|
|
3556
|
-
*
|
|
3557
|
-
* S-
|
|
3558
|
-
*
|
|
3559
|
-
* `source-layer` = S-57 class name.
|
|
3560
|
-
*
|
|
3561
|
-
* `buildSources()` returns either the legacy Mapbox MTS shape (preserved for
|
|
3562
|
-
* demos / external style export — see generateStyle comments) or the PMTiles
|
|
3563
|
-
* shape pointing at a single tile URL per region.
|
|
3626
|
+
* S-52 lookup table covering all S-57 object classes found in NOAA ENCs.
|
|
3627
|
+
* Colours reference S-52 tokens (resolved at render time).
|
|
3628
|
+
* INT1 references per NOAA Chart No. 1 (Ed 13).
|
|
3564
3629
|
*/
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
type: "vector";
|
|
3568
|
-
url: string;
|
|
3569
|
-
}
|
|
3630
|
+
declare const S52_LOOKUP: Record<string, LookupEntry>;
|
|
3631
|
+
|
|
3570
3632
|
/**
|
|
3571
|
-
*
|
|
3572
|
-
*
|
|
3573
|
-
* bytes without a TileJSON descriptor.
|
|
3633
|
+
* S-52 draw order: layers listed bottom → top.
|
|
3634
|
+
* Layers not in this list are inserted before point features.
|
|
3574
3635
|
*/
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3636
|
+
declare const S52_DRAW_ORDER: string[];
|
|
3637
|
+
/** Get numeric draw priority for a layer (lower = drawn first / below) */
|
|
3638
|
+
declare function getDrawPriority(layerName: string): number;
|
|
3639
|
+
|
|
3640
|
+
/** S-52 display modes */
|
|
3641
|
+
type DisplayMode = "BASE" | "STANDARD" | "ALL";
|
|
3642
|
+
/** Check if a layer's display category is visible in the given mode */
|
|
3643
|
+
declare function isVisibleInMode(displayCategory: DisplayCategory, mode: DisplayMode): boolean;
|
|
3583
3644
|
/**
|
|
3584
|
-
*
|
|
3585
|
-
* vector shapes because MapLibre needs `type: "raster-dem"` and an explicit
|
|
3586
|
-
* `encoding` — a raster-dem source read as a plain raster renders the encoded
|
|
3587
|
-
* RGB as a garish false-colour image rather than as elevation.
|
|
3645
|
+
* Convert S-52 SCAMIN (scale minimum) to Mapbox GL minzoom.
|
|
3588
3646
|
*/
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
maxzoom: number;
|
|
3596
|
-
/** The credit a renderer shows for this source (MapLibre's attribution control). */
|
|
3597
|
-
attribution?: string;
|
|
3598
|
-
}
|
|
3599
|
-
type VectorSourceSpec = MapboxVectorSource | PmtilesVectorSource;
|
|
3600
|
-
type AnySourceSpec = VectorSourceSpec | RasterDemSource;
|
|
3601
|
-
/** CHRTland's vector land base. ADR 0023: its own archive, never chart data. */
|
|
3602
|
-
declare const LAND_REGION = "CHRT_LAND";
|
|
3603
|
-
/** CHRTland's terrarium relief. */
|
|
3604
|
-
declare const RELIEF_REGION = "CHRT_RELIEF";
|
|
3605
|
-
/** The world basemap under everything (completing-the-world-map, 2026-08-27). */
|
|
3606
|
-
declare const BASE_REGION = "CHRT_BASE";
|
|
3647
|
+
declare function scaminToMinZoom(scamin?: number): number | undefined;
|
|
3648
|
+
declare function getCollisionSettings(viewingGroup?: number): {
|
|
3649
|
+
iconAllowOverlap: boolean;
|
|
3650
|
+
iconOptional: boolean;
|
|
3651
|
+
symbolSortKey?: number;
|
|
3652
|
+
};
|
|
3607
3653
|
/**
|
|
3608
|
-
*
|
|
3609
|
-
* carries honestly — the planet's inland water exists from z9 and is read at
|
|
3610
|
-
* z10 — and the world tier is tiled to the same depth so no layer vanishes
|
|
3611
|
-
* from a tile the detail tier creates. Above 11 the client overzooms, and
|
|
3612
|
-
* overzoomed inland water looks soft DELIBERATELY: it is "roughly where the
|
|
3613
|
-
* lakes are", not a surveyed shoreline. Must equal the builder's MAXZOOM
|
|
3614
|
-
* (tools/chrtbase-build/build.mjs).
|
|
3654
|
+
* Get the resolved Mapbox GL style for a given S-57 layer.
|
|
3615
3655
|
*/
|
|
3616
|
-
declare
|
|
3617
|
-
|
|
3656
|
+
declare function resolveStyle(layerName: string, geomKind?: GeomType, ct?: ColorTableName, opts?: {
|
|
3657
|
+
safetyContour?: number;
|
|
3658
|
+
}): ResolvedStyle;
|
|
3659
|
+
declare function getLookupEntry(layerName: string): LookupEntry;
|
|
3660
|
+
|
|
3618
3661
|
/**
|
|
3619
|
-
*
|
|
3620
|
-
*
|
|
3621
|
-
*
|
|
3622
|
-
* OSM-derived inland water (ODbL, `public/chrtbase-derivation.json`). The
|
|
3623
|
-
* app-embeddable offline bundle is a z0–6 cut that contains no OSM data and
|
|
3624
|
-
* carries `BASE_BUNDLE_ATTRIBUTION` instead (base-layers.ts) — one credit per
|
|
3625
|
-
* artefact, each naming exactly the data it holds.
|
|
3662
|
+
* S-52 Conditional Symbology Procedures.
|
|
3663
|
+
* Each function takes feature properties and returns paint overrides (hex colours).
|
|
3664
|
+
* All expression builders accept an optional colorTable parameter.
|
|
3626
3665
|
*/
|
|
3627
|
-
declare const BASE_ATTRIBUTION = "\u00A9 CHRT \u00B7 Made with Natural Earth \u00B7 \u00A9 OpenStreetMap contributors";
|
|
3628
3666
|
/**
|
|
3629
|
-
*
|
|
3630
|
-
*
|
|
3631
|
-
*
|
|
3632
|
-
*
|
|
3633
|
-
*
|
|
3634
|
-
*
|
|
3667
|
+
* Default safety contour in metres — the depth below which a feature is
|
|
3668
|
+
* "dangerous to my hull" for portrayal purposes.
|
|
3669
|
+
*
|
|
3670
|
+
* This is the single source of truth for the *default* used by every
|
|
3671
|
+
* safety-contour-driven conditional symbology rule, so the rules can't
|
|
3672
|
+
* silently disagree with each other:
|
|
3673
|
+
*
|
|
3674
|
+
* - §SOUNDG02 — soundings shoaler than the contour get the
|
|
3675
|
+
* high-contrast shade (see `getLabelConfig` in labels.ts).
|
|
3676
|
+
* - §CSYM02 — isolated dangers shoaler than the contour get the
|
|
3677
|
+
* DNGCIR01 ring (see `buildLayersForClass` in layer-builder.ts).
|
|
3678
|
+
* - §DEPARE04 — the MS/MD shade boundary (owner decision 2026-08-21,
|
|
3679
|
+
* replacing a hardcoded 5 m middle cut; see the DEPARE block below
|
|
3680
|
+
* for the full IHO correspondence).
|
|
3681
|
+
*
|
|
3682
|
+
* All are overridden by the user's setting (sounding panel slider,
|
|
3683
|
+
* `safetyContour` in the style options); this is only the fallback when
|
|
3684
|
+
* none is supplied. It matches `custom-style.ts`'s config default.
|
|
3635
3685
|
*/
|
|
3636
|
-
declare const
|
|
3686
|
+
declare const DEFAULT_SAFETY_CONTOUR_M = 10;
|
|
3687
|
+
declare function depareColor(props: Record<string, unknown>, ct?: ColorTableName, safetyContourM?: number): string;
|
|
3637
3688
|
/**
|
|
3638
|
-
* The
|
|
3639
|
-
*
|
|
3640
|
-
*
|
|
3689
|
+
* The colour token of each `case` branch of `depareFillExpression`, in branch
|
|
3690
|
+
* order, then the fallback. `depth-area-opaque.ts` names the layers it splits
|
|
3691
|
+
* the expression into from this list, so the two read from one place.
|
|
3641
3692
|
*/
|
|
3642
|
-
declare const
|
|
3643
|
-
|
|
3644
|
-
declare
|
|
3693
|
+
declare const DEPARE_FILL_BRANCH_TOKENS: readonly ["DEPIT", "DEPVS", "DEPMS", "DEPMD"];
|
|
3694
|
+
declare const DEPARE_FILL_FALLBACK_TOKEN = "DEPDW";
|
|
3695
|
+
declare function depareFillExpression(ct?: ColorTableName, safetyContourM?: number): unknown[];
|
|
3696
|
+
declare function lightColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3697
|
+
declare function lightFillExpression(ct?: ColorTableName): unknown[];
|
|
3698
|
+
declare function lateralColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3699
|
+
declare function lateralFillExpression(ct?: ColorTableName): unknown[];
|
|
3700
|
+
declare function hazardColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3701
|
+
declare function hazardFillExpression(ct?: ColorTableName): unknown[];
|
|
3702
|
+
declare function daymarkColor(props: Record<string, unknown>, ct?: ColorTableName): string;
|
|
3703
|
+
|
|
3645
3704
|
/**
|
|
3646
|
-
*
|
|
3647
|
-
*
|
|
3648
|
-
* surface that describes this source (this registry, the tile-worker's
|
|
3649
|
-
* TileJSON) has to say it.
|
|
3705
|
+
* Label configurations for S-57 layers.
|
|
3706
|
+
* Defines which layers get text labels and how to extract label text.
|
|
3650
3707
|
*/
|
|
3651
|
-
|
|
3652
|
-
type SourceMode = "mapbox" | "pmtiles";
|
|
3708
|
+
|
|
3653
3709
|
/**
|
|
3654
|
-
*
|
|
3655
|
-
*
|
|
3656
|
-
* ── Why the build has to be IN THE URL ────────────────────────────────────
|
|
3657
|
-
*
|
|
3658
|
-
* The Worker reports the build it served in the `X-Build-Id` RESPONSE HEADER
|
|
3659
|
-
* and sends `Cache-Control: private, max-age=3600`. A header is not part of a
|
|
3660
|
-
* cache key, so every build shares one URL: after a cutover, tiles the client
|
|
3661
|
-
* already fetched keep coming from its own HTTP cache — the old build — while
|
|
3662
|
-
* newly-panned-to tiles come from the new one, for up to the full hour. The
|
|
3663
|
-
* client renders TWO BUILDS AT ONCE.
|
|
3710
|
+
* Feature-class hierarchy for SEAARE labels. Returns a tier number 1-5 per
|
|
3711
|
+
* feature:
|
|
3664
3712
|
*
|
|
3665
|
-
*
|
|
3666
|
-
*
|
|
3667
|
-
*
|
|
3668
|
-
*
|
|
3669
|
-
*
|
|
3670
|
-
*
|
|
3713
|
+
* Exported (with the other tier builders below) for the build-side parity
|
|
3714
|
+
* test: CHRTbaremetal replicates these taxonomies as data in
|
|
3715
|
+
* tools/chrt-baremetal/server/src/tilebuild/placeNameTiers.ts to stamp
|
|
3716
|
+
* `tier` onto PLACENAME index features, and
|
|
3717
|
+
* placename-tier-parity.test.ts evaluates the two against shared
|
|
3718
|
+
* fixtures. Change a branch here and that test names the drift.
|
|
3671
3719
|
*
|
|
3672
|
-
*
|
|
3720
|
+
* 1 — Ocean (OBJNAM contains "<X> Ocean" — CATSEA has no
|
|
3721
|
+
* ocean code; the attribute is 1/unset on oceans)
|
|
3722
|
+
* 2 — Sea / Gulf (OBJNAM "Gulf of …" / "… Sea")
|
|
3723
|
+
* 3 — Bay / Sound / (CATSEA in {5 bay, 12 narrows} OR OBJNAM
|
|
3724
|
+
* Strait / Narrows " Bay" / " Sound" / " Strait")
|
|
3725
|
+
* 4 — Anchorage detail (OBJNAM contains "Anchorage Area")
|
|
3726
|
+
* 5 — Relief + default (CATSEA relief codes — authoritative — or
|
|
3727
|
+
* relief-term names, or anything uncategorised;
|
|
3728
|
+
* suppressed below z9 by the size curve)
|
|
3673
3729
|
*
|
|
3674
|
-
*
|
|
3675
|
-
*
|
|
3730
|
+
* Order matters: tier-4/5 demotions (anchorages, relief) run BEFORE the
|
|
3731
|
+
* promotion shims so "Bear Seamount" (contains " Sea") and "…Anchorage
|
|
3732
|
+
* Area" compound names can't bubble up into headline tiers.
|
|
3733
|
+
* `coalesce(CATSEA, catsea)` handles post-tippecanoe case variation
|
|
3734
|
+
* (matches `s52-conditional.ts` precedent).
|
|
3735
|
+
*/
|
|
3736
|
+
declare function buildSeaAreaTierExpression(): ExpressionSpecification;
|
|
3737
|
+
/**
|
|
3738
|
+
* Built-up area tier (BUAARE): major city / town / neighborhood.
|
|
3739
|
+
* 1 — Major city (CATBUA=1 urban, or OBJNAM length <= 8)
|
|
3740
|
+
* 2 — Town (CATBUA=5 village, or OBJNAM length <= 14)
|
|
3741
|
+
* 3 — Neighborhood (longer compound names)
|
|
3676
3742
|
*
|
|
3677
|
-
*
|
|
3678
|
-
*
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
*
|
|
3683
|
-
*
|
|
3684
|
-
*
|
|
3685
|
-
* and `src/site/chart/sail-tile-token.ts` (which decide whether a tile
|
|
3686
|
-
* gets its Bearer), `packages/sdk/src/tile-auth.ts` TILE_URL_PATH,
|
|
3687
|
-
* `public/chrt-tile-sw.js` TILE_URL_RE (which also reads the region out of
|
|
3688
|
-
* the URL to pick its per-region cache), and
|
|
3689
|
-
* `src/site/offline/pack-protocol.ts` TILE_URL (which rewrites a tile to
|
|
3690
|
-
* a downloaded pack). Their optional PATH segment, by contrast, is
|
|
3691
|
-
* `[a-z][a-z0-9-]*` — letter-first so it cannot be confused with the
|
|
3692
|
-
* numeric `{z}` — and build ids are hex (`463b265e`, `4de67273`). A build
|
|
3693
|
-
* in the path would miss every one of them, and a tile those patterns
|
|
3694
|
-
* miss does not merely go uncached: it goes out with NO BEARER and comes
|
|
3695
|
-
* back 401, which MapLibre records as a permanently errored tile. That is
|
|
3696
|
-
* the exact failure the `.png` drift caused on staging-sail (see
|
|
3697
|
-
* `chrt-tile-sw.js`).
|
|
3743
|
+
* Tier 1/2 may fire via CATBUA when populated; OBJNAM length is the
|
|
3744
|
+
* fallback so unpopulated CATBUA still produces a usable hierarchy.
|
|
3745
|
+
*/
|
|
3746
|
+
declare function buildBuiltUpAreaTierExpression(): ExpressionSpecification;
|
|
3747
|
+
/**
|
|
3748
|
+
* Land region tier (LNDRGN): major region vs. local point.
|
|
3749
|
+
* 1 — Major region (OBJNAM length <= 12 AND no comma — "Long Island", "Cape Cod")
|
|
3750
|
+
* 2 — Local point (else — "Bird Island", "Cottage Park")
|
|
3698
3751
|
*
|
|
3699
|
-
*
|
|
3700
|
-
*
|
|
3701
|
-
*
|
|
3752
|
+
* No CATLND analog for region scope, so OBJNAM is the only signal.
|
|
3753
|
+
* The comma-absence test is a heuristic: NOAA compound names like
|
|
3754
|
+
* "Boston Harbor, MA Castle Island" carry a comma and belong at deeper
|
|
3755
|
+
* zoom regardless of length.
|
|
3756
|
+
*/
|
|
3757
|
+
declare function buildLandRegionTierExpression(): ExpressionSpecification;
|
|
3758
|
+
/**
|
|
3759
|
+
* Land area tier (LNDARE): major vs. local.
|
|
3760
|
+
* 1 — Major (OBJNAM length <= 12)
|
|
3761
|
+
* 2 — Local
|
|
3702
3762
|
*
|
|
3703
|
-
*
|
|
3704
|
-
|
|
3763
|
+
* No category attribute. OBJNAM length is the only signal.
|
|
3764
|
+
*/
|
|
3765
|
+
declare function buildLandAreaTierExpression(): ExpressionSpecification;
|
|
3766
|
+
/**
|
|
3767
|
+
* Lake tier (LAKARE): lake vs. reservoir/pond.
|
|
3768
|
+
* 1 — Lake (CATLAK=1, or OBJNAM length <= 12)
|
|
3769
|
+
* 2 — Reservoir/pond (CATLAK in {2,3}, or longer name)
|
|
3770
|
+
*/
|
|
3771
|
+
declare function buildLakeTierExpression(): ExpressionSpecification;
|
|
3772
|
+
/**
|
|
3773
|
+
* River tier (RIVERS): major vs. local.
|
|
3774
|
+
* 1 — Major river (OBJNAM length <= 15 AND no comma)
|
|
3775
|
+
* 2 — Local creek (else)
|
|
3705
3776
|
*/
|
|
3706
|
-
declare
|
|
3777
|
+
declare function buildRiverTierExpression(): ExpressionSpecification;
|
|
3707
3778
|
/**
|
|
3708
|
-
*
|
|
3779
|
+
* Airport tier (AIRARE): major airport vs. small airstrip.
|
|
3780
|
+
* 1 — Major (OBJNAM length <= 25 — e.g. "Logan International Airport")
|
|
3781
|
+
* 2 — Airstrip
|
|
3782
|
+
*/
|
|
3783
|
+
declare function buildAirportTierExpression(): ExpressionSpecification;
|
|
3784
|
+
interface LabelLayerConfig {
|
|
3785
|
+
/** Mapbox source layer type */
|
|
3786
|
+
type: "symbol";
|
|
3787
|
+
/** Text field expression or string */
|
|
3788
|
+
textField: ExpressionSpecification | string;
|
|
3789
|
+
/** Text size in pixels */
|
|
3790
|
+
textSize: number | ExpressionSpecification;
|
|
3791
|
+
/** Text color (hex) or data-driven expression */
|
|
3792
|
+
textColor: string | ExpressionSpecification;
|
|
3793
|
+
/** Halo color for contrast */
|
|
3794
|
+
textHaloColor: string;
|
|
3795
|
+
/** Halo width — pixels or zoom-interpolation expression */
|
|
3796
|
+
textHaloWidth: number | ExpressionSpecification;
|
|
3797
|
+
/** Text offset [x, y] in ems */
|
|
3798
|
+
textOffset: [number, number];
|
|
3799
|
+
/** Font stack */
|
|
3800
|
+
textFont?: string[];
|
|
3801
|
+
/** Additional layout properties */
|
|
3802
|
+
layout?: Record<string, unknown>;
|
|
3803
|
+
/** Minimum zoom level for this label */
|
|
3804
|
+
minzoom?: number;
|
|
3805
|
+
}
|
|
3806
|
+
/**
|
|
3807
|
+
* Optional palette-and-data-driven options for label config.
|
|
3709
3808
|
*
|
|
3710
|
-
*
|
|
3711
|
-
*
|
|
3712
|
-
*
|
|
3713
|
-
* parameter at all instead of a bare `?v=` that would key its own useless
|
|
3714
|
-
* cache namespace.
|
|
3809
|
+
* Currently used by SOUNDG to pick palette-aware text/halo colors and to
|
|
3810
|
+
* drive the S-52 safety-contour two-shade rule. Other classes ignore
|
|
3811
|
+
* these options.
|
|
3715
3812
|
*/
|
|
3716
|
-
|
|
3717
|
-
/**
|
|
3718
|
-
|
|
3719
|
-
declare const DEFAULT_REGION = "NOAA_ENC";
|
|
3720
|
-
interface BuildSourcesOptions {
|
|
3721
|
-
/** Which tile path to emit. Default: "pmtiles" (the supported path post-Mapbox). */
|
|
3722
|
-
mode?: SourceMode;
|
|
3723
|
-
/** Chart region. Default: "NOAA_ENC". */
|
|
3724
|
-
region?: string;
|
|
3725
|
-
/**
|
|
3726
|
-
* Build id of the CHART region (`region`) — the `build_tag` a
|
|
3727
|
-
* `mint-tile-token` response hands back.
|
|
3728
|
-
*
|
|
3729
|
-
* Emitted as the {@link BUILD_PARAM} query parameter on that region's tile
|
|
3730
|
-
* template. See {@link tileTemplate} for why a build discriminator has to be
|
|
3731
|
-
* in the URL at all.
|
|
3732
|
-
*
|
|
3733
|
-
* ⚠ THIS COVERS THE CHART REGION ONLY. A token is minted for one chart
|
|
3734
|
-
* region and `CHRT_LAND` / `CHRT_RELIEF` ride it, so the JWT's `build_tag`
|
|
3735
|
-
* says nothing about a land cutover — the same blind spot that made the
|
|
3736
|
-
* Worker's edge-cache key wrong until `TILE_CACHE_VERSION` v3
|
|
3737
|
-
* (cloudflare/tile-worker/src/cache-encoding.ts). Pass {@link buildTags} to
|
|
3738
|
-
* discriminate the basemap sources too.
|
|
3739
|
-
*/
|
|
3740
|
-
buildTag?: string;
|
|
3741
|
-
/**
|
|
3742
|
-
* Resolved build id per region — `{ NOAA_ENC: "…", CHRT_LAND: "…" }`.
|
|
3743
|
-
*
|
|
3744
|
-
* The complete form of {@link buildTag}: every source this style declares
|
|
3745
|
-
* gets its own discriminator, so a `CHRT_LAND` promotion turns over the land
|
|
3746
|
-
* URLs without touching the chart's (and vice versa). An entry here wins
|
|
3747
|
-
* over `buildTag` for the same region.
|
|
3748
|
-
*
|
|
3749
|
-
* This is the mint response's `build_tags` map verbatim (claim contract
|
|
3750
|
-
* v1.7) — `TileTokenResponse.buildTags` in both `lib/map/tile-token-client.ts`
|
|
3751
|
-
* and the SDK's `tile-auth.ts`. The same map already keys the tile Service
|
|
3752
|
-
* Worker's per-region caches; passing it here puts the same identity in the
|
|
3753
|
-
* URL, so the layer above the Service Worker stops mixing builds too.
|
|
3754
|
-
*
|
|
3755
|
-
* A region absent from the map simply gets no discriminator — the URL it
|
|
3756
|
-
* has always had. That is a deliberate soft edge: an older mint response, or
|
|
3757
|
-
* a region with no servable build, must degrade to today's behaviour rather
|
|
3758
|
-
* than emit a URL pinned to a build nobody resolved.
|
|
3759
|
-
*/
|
|
3760
|
-
buildTags?: Readonly<Record<string, string>>;
|
|
3761
|
-
/** Override tile-worker origin (e.g. staging). Default: DEFAULT_TILE_BASE_URL. */
|
|
3762
|
-
tileBaseUrl?: string;
|
|
3813
|
+
interface LabelConfigOptions {
|
|
3814
|
+
/** S-52 colour table — drives palette-aware text and halo colors. */
|
|
3815
|
+
colorTable?: ColorTableName;
|
|
3763
3816
|
/**
|
|
3764
|
-
*
|
|
3765
|
-
*
|
|
3817
|
+
* Safety contour depth in metres. Soundings shoaler than this render in
|
|
3818
|
+
* `SNDG2` (high-contrast); deeper soundings render in `SNDG1` (muted).
|
|
3819
|
+
* S-52 §SOUNDG02 conditional symbology.
|
|
3766
3820
|
*/
|
|
3767
|
-
|
|
3821
|
+
safetyContour?: number;
|
|
3768
3822
|
/**
|
|
3769
|
-
*
|
|
3770
|
-
*
|
|
3771
|
-
* `land-regions.ts` still withholds.
|
|
3823
|
+
* When false, all soundings render in `SNDG2` (single-shade). Default
|
|
3824
|
+
* true — emit the safety-contour case expression.
|
|
3772
3825
|
*/
|
|
3773
|
-
|
|
3826
|
+
twoShadeSoundings?: boolean;
|
|
3774
3827
|
/**
|
|
3775
|
-
*
|
|
3776
|
-
*
|
|
3777
|
-
* inland water inside countries CHRT carries. Its layers sit UNDER the
|
|
3778
|
-
* no-coverage hatch's companions and everything else; see baseLayers().
|
|
3828
|
+
* When "semibold", SOUNDG labels use Open Sans Semibold for crisper
|
|
3829
|
+
* numerals at small sizes. Default "semibold".
|
|
3779
3830
|
*/
|
|
3780
|
-
|
|
3831
|
+
soundingFontWeight?: "regular" | "semibold";
|
|
3781
3832
|
}
|
|
3782
3833
|
/**
|
|
3783
|
-
*
|
|
3834
|
+
* Two-tier label rendering strategy for the band-priority style.
|
|
3784
3835
|
*
|
|
3785
|
-
* -
|
|
3786
|
-
*
|
|
3787
|
-
*
|
|
3788
|
-
*
|
|
3836
|
+
* `feature-band-gated` — emit one variant per source band, each gated to
|
|
3837
|
+
* its band's zoom window (the existing `makeBandVariants` behaviour). Right
|
|
3838
|
+
* for dense feature labels where seeing the same buoy designation or
|
|
3839
|
+
* sounding twice across overlapping bands is visual noise.
|
|
3789
3840
|
*
|
|
3790
|
-
*
|
|
3791
|
-
*
|
|
3792
|
-
*
|
|
3841
|
+
* `orientation-cross-band` — emit a SINGLE label layer with no band
|
|
3842
|
+
* filter. The per-class `minzoom` is honoured. Right for orientation
|
|
3843
|
+
* "where am I" labels (sea-area names, land regions, cities) — these
|
|
3844
|
+
* must persist as the user zooms in, even if the broader-scope cell
|
|
3845
|
+
* carrying the OBJNAM is from a coarser band than the one rendering
|
|
3846
|
+
* features at the current zoom. Collision arbitration via
|
|
3847
|
+
* `ORIENTATION_BAND_SORT_KEY` gives the broader-scope (lower-band) copy
|
|
3848
|
+
* priority where the same OBJNAM exists in multiple bands.
|
|
3793
3849
|
*/
|
|
3794
|
-
|
|
3795
|
-
|
|
3850
|
+
type LabelBehavior = "feature-band-gated" | "orientation-cross-band";
|
|
3851
|
+
declare const LABEL_BEHAVIOR: Record<string, LabelBehavior>;
|
|
3852
|
+
/** Returns the rendering strategy for an S-57 class. Unknown classes default to band-gated. */
|
|
3853
|
+
declare function getLabelBehavior(layerName: string): LabelBehavior;
|
|
3796
3854
|
/**
|
|
3797
|
-
*
|
|
3798
|
-
*
|
|
3799
|
-
*
|
|
3800
|
-
*
|
|
3801
|
-
* which may be a setting. I just can't sail the boat and adjust all that stuff
|
|
3802
|
-
* at the same time."* A set-and-forget choice, then, not a slider.
|
|
3803
|
-
*
|
|
3804
|
-
* ===========================================================================
|
|
3805
|
-
* WHAT "LARGE" CHANGES, AND WHAT IT IS NOT ALLOWED TO TOUCH
|
|
3806
|
-
* ===========================================================================
|
|
3855
|
+
* Class-based label priority ladder — THE single collision-priority model
|
|
3856
|
+
* for feature labels (portrayal-excellence P4). Converges the previous
|
|
3857
|
+
* per-mechanism patches (SAFETY_CRITICAL_LABELS allow-overlap, the
|
|
3858
|
+
* band-5/6-only Harbor collision discipline) into one explicit ranking.
|
|
3807
3859
|
*
|
|
3808
|
-
*
|
|
3809
|
-
*
|
|
3810
|
-
* `LARGE` for why less than the glyph — and the sounding collision padding —
|
|
3811
|
-
* see `LARGE_SOUNDING_PADDING_PX` for why that one moves.
|
|
3860
|
+
* Rank semantics: LOWER rank = higher priority. The rank drives two
|
|
3861
|
+
* mechanisms that must stay in agreement:
|
|
3812
3862
|
*
|
|
3813
|
-
*
|
|
3814
|
-
*
|
|
3863
|
+
* 1. `symbol-sort-key` — every feature label carries
|
|
3864
|
+
* `rank*1000 + within-class-key`, so if label layers are ever merged
|
|
3865
|
+
* (the P8 style fan-out reduction), placement priority survives the
|
|
3866
|
+
* merge unchanged.
|
|
3867
|
+
* 2. Label LAYER ORDER — MapLibre places symbols topmost-layer-first, so
|
|
3868
|
+
* `style-generator.ts` emits feature-label layers lowest-priority
|
|
3869
|
+
* first: safety-critical classes end up topmost and claim collision
|
|
3870
|
+
* space before anything else. (`symbol-sort-key` alone cannot do
|
|
3871
|
+
* this — it only orders placement WITHIN a layer.)
|
|
3815
3872
|
*
|
|
3816
|
-
*
|
|
3817
|
-
*
|
|
3818
|
-
* - `text-color` / `text-halo-color` — §SOUNDG02's two shades against the
|
|
3819
|
-
* safety contour, and the palette that draws them (red night included:
|
|
3820
|
-
* it IS the NIGHT chart). A depth number shoaler than the contour stays
|
|
3821
|
-
* the loud one.
|
|
3822
|
-
* - `symbol-sort-key` — shallowest wins a collision, at any size.
|
|
3823
|
-
* - `filter`, `minzoom`, `maxzoom`, layer ids and layer order — so the
|
|
3824
|
-
* resident layer set the desktop builds at boot is the same set, and a
|
|
3825
|
-
* switch is `setLayoutProperty` / `setPaintProperty` on layers already
|
|
3826
|
-
* there. No layer and no draw call is added; what costs more is GPU fill,
|
|
3827
|
-
* because a bigger glyph covers more pixels (about 6–7 % more blended
|
|
3828
|
-
* fragments per pixel on the chart bench — the PR has the numbers).
|
|
3873
|
+
* The ladder (safety-critical > nav-aids > depth field > structures >
|
|
3874
|
+
* ambient notes):
|
|
3829
3875
|
*
|
|
3830
|
-
*
|
|
3831
|
-
*
|
|
3832
|
-
*
|
|
3876
|
+
* 100 — Safety-critical: light characteristics (LIGHTS), hazard depth
|
|
3877
|
+
* callouts (UWTROC/OBSTRN/WRECKS VALSOU), overhead clearances
|
|
3878
|
+
* (CBLOHD/PIPOHD VERCLR). Irreducible mariner-safety text.
|
|
3879
|
+
* 200 — Nav-aid designations: buoy / beacon `R "4"` labels.
|
|
3880
|
+
* 250 — Auxiliary nav-aid info: fog signal type (FOGSIG).
|
|
3881
|
+
* 300 — Depth field: soundings, contour values. Individually droppable —
|
|
3882
|
+
* a hidden sounding has visible neighbors.
|
|
3883
|
+
* 400 — Structures: bridges, landmarks, piers, moorings, buildings.
|
|
3884
|
+
* 500 — Ambient annotation: seabed nature, magnetic variation, kelp.
|
|
3885
|
+
* 900 — Orientation names (SEAARE etc.) — not part of this ladder;
|
|
3886
|
+
* they keep their settled watermark model (cell-band fan +
|
|
3887
|
+
* dominance composition + `orientationLabelLayout`) and always
|
|
3888
|
+
* paint underneath feature labels.
|
|
3833
3889
|
*
|
|
3834
|
-
*
|
|
3835
|
-
*
|
|
3836
|
-
*
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
*
|
|
3890
|
+
* Safety guardrail: a lower rung never blocks a higher rung — placement
|
|
3891
|
+
* order guarantees the safety-critical label got the space first. Density
|
|
3892
|
+
* relief comes from dropping the LOWEST rung in a pile-up, never the top.
|
|
3893
|
+
*/
|
|
3894
|
+
declare const LABEL_PRIORITY: Record<string, number>;
|
|
3895
|
+
/**
|
|
3896
|
+
* Resolve the priority rank for an S-57 class's label. Orientation classes
|
|
3897
|
+
* report 900 regardless of ladder membership (PRDARE etc.) so the
|
|
3898
|
+
* layer-order sort in style-generator.ts can treat priority uniformly.
|
|
3899
|
+
*/
|
|
3900
|
+
declare function getLabelPriority(layerName: string): number;
|
|
3901
|
+
/**
|
|
3902
|
+
* Compose a `symbol-sort-key` from a class rank and an optional
|
|
3903
|
+
* within-class key expression. The within-class key is clamped to
|
|
3904
|
+
* [0, 999] so it can never bleed into a neighboring rank's band.
|
|
3905
|
+
*/
|
|
3906
|
+
declare function labelSortKey(rank: number, within?: unknown): ExpressionSpecification | number;
|
|
3907
|
+
/**
|
|
3908
|
+
* Extract the trailing designation token from a nav-aid OBJNAM.
|
|
3841
3909
|
*
|
|
3842
|
-
*
|
|
3843
|
-
*
|
|
3844
|
-
*
|
|
3910
|
+
* NOAA names channel aids "<waterway> <type> Buoy|Beacon <designation>"
|
|
3911
|
+
* where the designation is 1-4 alphanumerics: "4", "18A", "B", "BG".
|
|
3912
|
+
* Returns null when the name has no designation (trailing token is a
|
|
3913
|
+
* stopword type-name, or longer than 4 chars).
|
|
3845
3914
|
*
|
|
3846
|
-
*
|
|
3847
|
-
*
|
|
3848
|
-
*
|
|
3915
|
+
* This is the TS twin of `navAidDesignationTextExpression` — the GeoJSON
|
|
3916
|
+
* preprocessing path uses this function, the PMTiles path uses the GL
|
|
3917
|
+
* expression. Keep the two in agreement (see label-priority.test.ts).
|
|
3918
|
+
*/
|
|
3919
|
+
declare function extractNavAidDesignation(objnam: string): string | null;
|
|
3920
|
+
/** Get label config for a given S-57 layer, or null if no labels */
|
|
3921
|
+
declare function getLabelConfig(layerName: string, opts?: LabelConfigOptions): LabelLayerConfig | null;
|
|
3922
|
+
/**
|
|
3923
|
+
* Build a Mapbox symbol layer spec from a label config.
|
|
3924
|
+
*/
|
|
3925
|
+
declare function buildLabelLayer(layerId: string, sourceId: string, config: LabelLayerConfig, visible: boolean, overrides?: {
|
|
3926
|
+
textScale?: number;
|
|
3927
|
+
minzoom?: number | null;
|
|
3928
|
+
allowOverlap?: boolean;
|
|
3929
|
+
}): maplibregl.LayerSpecification;
|
|
3930
|
+
/**
|
|
3931
|
+
* Pre-process SOUNDG GeoJSON to extract Z coordinates as `depth` properties.
|
|
3932
|
+
* Soundings are MultiPoint with Z values in geometry.coordinates[][2].
|
|
3933
|
+
* This explodes MultiPoints into individual Points with a `depth` property.
|
|
3934
|
+
*/
|
|
3935
|
+
declare function preprocessSoundings(fc: GeoJSON.FeatureCollection): GeoJSON.FeatureCollection;
|
|
3936
|
+
/**
|
|
3937
|
+
* Pre-process LIGHTS GeoJSON to derive compact light characteristic labels.
|
|
3938
|
+
* Adds `_lightLabel` property (e.g., "Fl(2) WR 4s 5M").
|
|
3849
3939
|
*
|
|
3850
|
-
*
|
|
3851
|
-
*
|
|
3852
|
-
*
|
|
3853
|
-
*
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3940
|
+
* KEEP IN STEP WITH `buildLightLabelExpression()` in layer-builder.ts — that
|
|
3941
|
+
* is the same label built as a GL expression for the tile path, which has no
|
|
3942
|
+
* JS preprocessing step. `light-label-parity.test.ts` asserts the two agree
|
|
3943
|
+
* on real tile features; if you change one, change both.
|
|
3944
|
+
*/
|
|
3945
|
+
declare function preprocessLights(fc: GeoJSON.FeatureCollection): GeoJSON.FeatureCollection;
|
|
3946
|
+
/** List of layers that have labels */
|
|
3947
|
+
declare const LABELED_LAYERS: Set<string>;
|
|
3948
|
+
/**
|
|
3949
|
+
* Pre-process buoy/beacon GeoJSON to derive concise mariner-style labels.
|
|
3950
|
+
* Adds `_navAidLabel` property (e.g., 'R "8"', 'G "5"').
|
|
3951
|
+
*/
|
|
3952
|
+
declare function preprocessNavAids(fc: GeoJSON.FeatureCollection): GeoJSON.FeatureCollection;
|
|
3953
|
+
/** Check if a layer name needs nav aid preprocessing */
|
|
3954
|
+
declare function isNavAidLayer(layerName: string): boolean;
|
|
3955
|
+
/**
|
|
3956
|
+
* Pre-process water body polygon GeoJSON into centroid points for label placement.
|
|
3957
|
+
* Computes a simple average-coordinate centroid for each polygon feature that has OBJNAM.
|
|
3958
|
+
*/
|
|
3959
|
+
declare function preprocessWaterBodies(fc: GeoJSON.FeatureCollection): GeoJSON.FeatureCollection;
|
|
3960
|
+
/** MVT layer the build-side place-name index emits. */
|
|
3961
|
+
declare const PLACENAME_SOURCE_LAYER = "PLACENAME";
|
|
3962
|
+
/** Orientation classes whose names render italic (water voice). */
|
|
3963
|
+
declare const PLACENAME_WATER_CLASSES: readonly string[];
|
|
3964
|
+
/** Orientation classes whose names render upright (land voice). */
|
|
3965
|
+
declare const PLACENAME_LAND_CLASSES: readonly string[];
|
|
3966
|
+
/**
|
|
3967
|
+
* The 2 PLACENAME symbol layers. Layout contract (design §2.2): collision
|
|
3968
|
+
* ON (`allow-overlap: false`, `ignore-placement: false`,
|
|
3969
|
+
* `optional: true`), padding 4, `text-variable-anchor`, and
|
|
3970
|
+
* `symbol-sort-key` straight from the build-side `rank` — MapLibre places
|
|
3971
|
+
* LOWER sort keys first, and rank is minted lower-is-more-important
|
|
3972
|
+
* (tier major, bbox area minor), so when space runs out the biggest names
|
|
3973
|
+
* survive. That ranking is the per-zoom density governor P4 asked for.
|
|
3857
3974
|
*/
|
|
3975
|
+
declare function buildPlaceNameLayers(sourceId: string, ct?: ColorTableName): maplibregl.LayerSpecification[];
|
|
3858
3976
|
|
|
3859
|
-
/** The two choices, in presentation order. */
|
|
3860
|
-
declare const DEPTH_LABEL_SIZES: readonly ["standard", "large"];
|
|
3861
|
-
type DepthLabelSize = (typeof DEPTH_LABEL_SIZES)[number];
|
|
3862
3977
|
/**
|
|
3863
|
-
*
|
|
3864
|
-
*
|
|
3865
|
-
*
|
|
3978
|
+
* Spatial grid-based feature decimation for performance at low zoom levels.
|
|
3979
|
+
* Thins dense GeoJSON feature sets by keeping only one representative
|
|
3980
|
+
* feature per grid cell per layer.
|
|
3866
3981
|
*/
|
|
3867
|
-
|
|
3868
|
-
/**
|
|
3869
|
-
|
|
3870
|
-
/**
|
|
3871
|
-
|
|
3982
|
+
interface DecimationOptions {
|
|
3983
|
+
/** Grid resolution (cells per axis). Default 80. */
|
|
3984
|
+
gridSize?: number;
|
|
3985
|
+
/** Zoom level below which decimation kicks in. Default 12. */
|
|
3986
|
+
zoomThreshold?: number;
|
|
3987
|
+
}
|
|
3872
3988
|
/**
|
|
3873
|
-
*
|
|
3874
|
-
*
|
|
3875
|
-
* ⚠ THIS IS THE ONE THAT DECIDES HOW MANY SOUNDINGS SURVIVE. MapLibre drops a
|
|
3876
|
-
* sounding whose box (glyphs + padding) overlaps one already placed — the
|
|
3877
|
-
* shallowest places first, so what drops is the deeper figure. A 1.4x numeral
|
|
3878
|
-
* inside Standard's 6 px padding lost a quarter of the soundings: bigger
|
|
3879
|
-
* numbers, fewer of them, which is not what was asked for. Trimming the
|
|
3880
|
-
* padding gives the box back.
|
|
3881
|
-
*
|
|
3882
|
-
* Measured 2026-10-05 on the chart bench (`scripts/chart-bench`, Boston, DAY,
|
|
3883
|
-
* 1280x800 at 1x), soundings placed, Standard → Large at this padding:
|
|
3884
|
-
*
|
|
3885
|
-
* z11.5 515 → 539 (+5%) z12.3 434 → 415 (−4%)
|
|
3886
|
-
* z13 374 → 366 (−2%) z14 326 → 311 (−5%)
|
|
3887
|
-
*
|
|
3888
|
-
* and at Standard's 6 px: 391 / 246 at z11.5 / z14 (−24% / −25%). 3 px kept
|
|
3889
|
-
* z14 level but put 17% MORE figures on the coastal view, which reads as
|
|
3890
|
-
* clutter rather than as the same chart drawn bigger.
|
|
3989
|
+
* Zoom-adaptive grid resolution for decimation.
|
|
3891
3990
|
*/
|
|
3892
|
-
declare
|
|
3991
|
+
declare function getGridSizeForZoom(zoom: number): number;
|
|
3893
3992
|
/**
|
|
3894
|
-
*
|
|
3993
|
+
* Decimate a GeoJSON FeatureCollection using spatial grid thinning.
|
|
3994
|
+
* Only runs when zoom < zoomThreshold. Returns the original FC otherwise.
|
|
3895
3995
|
*
|
|
3896
|
-
*
|
|
3897
|
-
*
|
|
3898
|
-
*
|
|
3996
|
+
* @param fc - Input FeatureCollection
|
|
3997
|
+
* @param layerName - S-57 layer name (affects priority logic)
|
|
3998
|
+
* @param currentZoom - Current map zoom level
|
|
3999
|
+
* @param bounds - Current viewport bounds
|
|
4000
|
+
* @param opts - Decimation options
|
|
3899
4001
|
*/
|
|
3900
|
-
declare function
|
|
3901
|
-
|
|
4002
|
+
declare function decimateFeatures(fc: GeoJSON.FeatureCollection, layerName: string, currentZoom: number, bounds: {
|
|
4003
|
+
west: number;
|
|
4004
|
+
south: number;
|
|
4005
|
+
east: number;
|
|
4006
|
+
north: number;
|
|
4007
|
+
}, opts?: DecimationOptions): GeoJSON.FeatureCollection;
|
|
3902
4008
|
/**
|
|
3903
|
-
*
|
|
3904
|
-
* Wraps the existing atlas resolveStyle() and adds source/source-layer/filter.
|
|
4009
|
+
* Get the max number of cells to load based on zoom level.
|
|
3905
4010
|
*/
|
|
4011
|
+
declare function getMaxCellsForZoom(zoom: number): number;
|
|
3906
4012
|
|
|
3907
|
-
interface StyleLayer {
|
|
3908
|
-
id: string;
|
|
3909
|
-
type: string;
|
|
3910
|
-
source: string;
|
|
3911
|
-
"source-layer": string;
|
|
3912
|
-
filter?: unknown[];
|
|
3913
|
-
paint: Record<string, unknown>;
|
|
3914
|
-
layout?: Record<string, unknown>;
|
|
3915
|
-
minzoom?: number;
|
|
3916
|
-
maxzoom?: number;
|
|
3917
|
-
metadata?: Record<string, unknown>;
|
|
3918
|
-
}
|
|
3919
4013
|
/**
|
|
3920
|
-
*
|
|
3921
|
-
* Returns multiple layers (fill, outline, symbol, label, etc.).
|
|
4014
|
+
* IHO S-52 / NOAA Chart No. 1 / INT1 nautical symbol SVGs.
|
|
3922
4015
|
*
|
|
3923
|
-
*
|
|
3924
|
-
*
|
|
4016
|
+
* Complete symbology suite following:
|
|
4017
|
+
* - IHO S-52 Presentation Library (Ed 4.0)
|
|
4018
|
+
* - IALA Maritime Buoyage System R1001 (Region B for US waters)
|
|
4019
|
+
* - NOAA Chart No. 1 (Ed 13) / INT1
|
|
3925
4020
|
*
|
|
3926
|
-
*
|
|
3927
|
-
*
|
|
3928
|
-
*
|
|
3929
|
-
*
|
|
4021
|
+
* Buoy shape terminology (US / Chart No. 1):
|
|
4022
|
+
* - CAN (Q20): Flat-top cylindrical buoy — Port mark in IALA-B (red)
|
|
4023
|
+
* - NUN (Q21): Conical/pointed-top buoy — Starboard mark in IALA-B (green)
|
|
4024
|
+
* - PILLAR: Tall narrow buoy — used for cardinal, isolated danger, etc.
|
|
4025
|
+
* - SPAR: Tall thin pole buoy
|
|
4026
|
+
* - SPHERICAL: Round buoy — safe water marks
|
|
4027
|
+
* - BARREL: Barrel/tun shaped buoy
|
|
4028
|
+
* - SUPER: Large navigation buoy / LANBY
|
|
4029
|
+
*
|
|
4030
|
+
* Cardinal mark topmark orientations (IALA):
|
|
4031
|
+
* - North: both cones point UP ▲▲
|
|
4032
|
+
* - South: both cones point DOWN ▼▼
|
|
4033
|
+
* - East: cones base-to-base (diamond) ◆
|
|
4034
|
+
* - West: cones point-to-point (hourglass) ⊗
|
|
4035
|
+
*
|
|
4036
|
+
* Each symbol is a compact SVG at 32×32 for Mapbox GL `map.addImage()`.
|
|
3930
4037
|
*/
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
4038
|
+
/** Color used in the SVG with its S-52 token name, hex, and usage */
|
|
4039
|
+
interface SymbolColor {
|
|
4040
|
+
token: string;
|
|
4041
|
+
hex: string;
|
|
4042
|
+
usage: string;
|
|
4043
|
+
}
|
|
4044
|
+
/** Line style used in the SVG */
|
|
4045
|
+
interface SymbolLineStyle {
|
|
4046
|
+
element: string;
|
|
4047
|
+
width: number;
|
|
4048
|
+
pattern?: string;
|
|
4049
|
+
color: string;
|
|
4050
|
+
}
|
|
4051
|
+
/** Fill element used in the SVG */
|
|
4052
|
+
interface SymbolFillElement {
|
|
4053
|
+
element: string;
|
|
4054
|
+
color: string;
|
|
4055
|
+
opacity?: number;
|
|
4056
|
+
}
|
|
4057
|
+
interface NauticalSymbol {
|
|
4058
|
+
id: string;
|
|
4059
|
+
label: string;
|
|
4060
|
+
/** INT1 / Chart No. 1 reference */
|
|
4061
|
+
int1Ref: string;
|
|
4062
|
+
/** Chart No. 1 section letter */
|
|
4063
|
+
section: string;
|
|
4064
|
+
getSvg: () => string;
|
|
4065
|
+
/** Generate SVG with theme-specific colors (for bridge icons etc.) */
|
|
4066
|
+
getThemedSvg?: (chblk: string, movable: string) => string;
|
|
4067
|
+
/** What this symbol represents on a chart */
|
|
4068
|
+
description?: string;
|
|
4069
|
+
/** S-52 Presentation Library symbol name */
|
|
4070
|
+
s52PlRef?: string;
|
|
4071
|
+
/** S-57 object class (e.g. "LNDMRK") when it can't be derived from s52PlRef's prefix */
|
|
4072
|
+
s57Class?: string;
|
|
4073
|
+
/** Grouping key for family clustering */
|
|
4074
|
+
group?: string;
|
|
4075
|
+
/** IDs of related variant symbols */
|
|
4076
|
+
variants?: string[];
|
|
4077
|
+
/** S-57 attribute that selects this variant */
|
|
4078
|
+
attributeKey?: string;
|
|
4079
|
+
/** Value of that attribute for this variant */
|
|
4080
|
+
attributeValue?: number;
|
|
4081
|
+
/** Example label strings seen on charts */
|
|
4082
|
+
labelExamples?: string[];
|
|
4083
|
+
/** What the color represents */
|
|
4084
|
+
colorMeaning?: string;
|
|
4085
|
+
/** Colors used in the SVG */
|
|
4086
|
+
colors?: SymbolColor[];
|
|
4087
|
+
/** Line/stroke styles used in the SVG */
|
|
4088
|
+
lineStyles?: SymbolLineStyle[];
|
|
4089
|
+
/** Fill regions in the SVG */
|
|
4090
|
+
fillElements?: SymbolFillElement[];
|
|
4091
|
+
/** Expanded navigational usage context (2-4 sentences) */
|
|
4092
|
+
usageContext?: string;
|
|
4093
|
+
/** Render size for documentation */
|
|
4094
|
+
renderSize?: string;
|
|
4095
|
+
}
|
|
4096
|
+
/** A logical grouping of related symbols */
|
|
4097
|
+
interface SymbolGroup {
|
|
4098
|
+
id: string;
|
|
4099
|
+
label: string;
|
|
4100
|
+
section: string;
|
|
4101
|
+
description: string;
|
|
4102
|
+
symbolIds: string[];
|
|
4103
|
+
}
|
|
4104
|
+
/** Chart No. 1 section metadata */
|
|
4105
|
+
interface ChartSection {
|
|
4106
|
+
id: string;
|
|
4107
|
+
label: string;
|
|
4108
|
+
description: string;
|
|
4109
|
+
}
|
|
4110
|
+
declare const NAUTICAL_SYMBOLS: NauticalSymbol[];
|
|
4111
|
+
/** S-57 object class → default symbol ID mapping.
|
|
4112
|
+
* Values are S-52 PL symbol names (matching SVG filenames in s52/point/).
|
|
4113
|
+
* Conditional expressions in getIconExpression() override these for classes
|
|
4114
|
+
* with attribute-dependent variants.
|
|
4115
|
+
*/
|
|
4116
|
+
declare const SYMBOL_MAP: Record<string, string>;
|
|
4117
|
+
/** Get the Mapbox icon-image expression for data-driven symbol selection.
|
|
4118
|
+
* Returns S-52 PL symbol names that correspond to SVG files in s52/point/.
|
|
4119
|
+
*/
|
|
4120
|
+
declare function getIconExpression(layerName: string): string | unknown[];
|
|
3934
4121
|
/**
|
|
3935
|
-
*
|
|
3936
|
-
*
|
|
3937
|
-
*
|
|
3938
|
-
* without touching this file.
|
|
4122
|
+
* Browser-only image loaders (`loadSymbolImages`, `loadThemedBridgeImages`)
|
|
4123
|
+
* live in `./symbols-browser.ts` (sub-export `@chrtco/sdk/atlas/browser`) —
|
|
4124
|
+
* they require a DOM (use `new Image()` + `map.addImage()`).
|
|
3939
4125
|
*/
|
|
3940
|
-
|
|
4126
|
+
/** Get inline SVG string for a symbol by ID (for the Atlas legend) */
|
|
4127
|
+
declare function getSymbolSvgString(symbolId: string): string | null;
|
|
4128
|
+
declare const CHART_SECTIONS: ChartSection[];
|
|
4129
|
+
declare const SYMBOL_GROUPS: SymbolGroup[];
|
|
4130
|
+
/** Generate a single SVG sprite sheet containing all symbols as <symbol> elements */
|
|
4131
|
+
declare function generateSpriteSheet(): string;
|
|
4132
|
+
/** Generate a JSON manifest mapping symbol IDs to metadata */
|
|
4133
|
+
declare function generateSpriteManifest(): Record<string, {
|
|
4134
|
+
label: string;
|
|
4135
|
+
int1Ref: string;
|
|
4136
|
+
section: string;
|
|
4137
|
+
group?: string;
|
|
4138
|
+
s52PlRef?: string;
|
|
4139
|
+
description?: string;
|
|
4140
|
+
attributeKey?: string;
|
|
4141
|
+
attributeValue?: number;
|
|
4142
|
+
}>;
|
|
3941
4143
|
|
|
3942
4144
|
/**
|
|
3943
|
-
*
|
|
3944
|
-
*
|
|
3945
|
-
* `makeBandVariants()` historically emitted, per (class, band): one
|
|
3946
|
-
* "not-dominated" layer plus up to five `-domBy{D}` copies that differ ONLY
|
|
3947
|
-
* in their dominance filter and a `maxzoom` of `dominatedVariantMaxzoom(D)`.
|
|
3948
|
-
* That fan existed because MapLibre filters could not read `["zoom"]`. They
|
|
3949
|
-
* can now (style-spec 24.8.5; buckets evaluate at the tile's `overscaledZ`),
|
|
3950
|
-
* so the whole fan folds into ONE layer per (class, band) whose filter
|
|
3951
|
-
* carries the zoom gate.
|
|
3952
|
-
*
|
|
3953
|
-
* **Construction principle — read before changing anything here.** The
|
|
3954
|
-
* collapsed filter is the literal `["any"]` UNION of the clauses the fan
|
|
3955
|
-
* already encoded: every variant the legacy emitter would have produced
|
|
3956
|
-
* contributes exactly one `["all", <its dominance filter>, ["<", ["zoom"],
|
|
3957
|
-
* <its maxzoom>]]` clause, and the dead-variant skip is mirrored too.
|
|
3958
|
-
* Equivalence is therefore *structural*, not re-derived — which matters,
|
|
3959
|
-
* because the two "obvious" hand-written forms are both wrong:
|
|
3960
|
-
*
|
|
3961
|
-
* 1. A `["match", ["get","_dominated_by_min"], 2,5, 3,7, 4,9, 5,11, 6,11, 24]`
|
|
3962
|
-
* threshold (the form the design doc proposed) uses band 6's *eligibility*
|
|
3963
|
-
* zoom 11. The real ceiling is `dominatedVariantMaxzoom("6") = 13` — band
|
|
3964
|
-
* 6's DATA floor. Using 11 reopens the z11–z12 void window that
|
|
3965
|
-
* `band-priority.ts` documents closing.
|
|
3966
|
-
* 2. That same form silently drops the legacy `_dominated: true` boolean,
|
|
3967
|
-
* which `dominatedByMinFilter("6")` still honours. A legacy-tagged feature
|
|
3968
|
-
* has no `_dominated_by_min`, so `match` falls to its default and the
|
|
3969
|
-
* feature renders FOREVER instead of dropping at z13.
|
|
3970
|
-
*
|
|
3971
|
-
* Deriving the gate from the emitter's own clauses avoids both by construction.
|
|
3972
|
-
* `band-collapse.test.ts` re-proves it on every CI run by differentially
|
|
3973
|
-
* evaluating legacy-vs-collapsed through MapLibre's real three gates.
|
|
4145
|
+
* IHO S-101 ENC Product Specification — Feature Catalogue
|
|
3974
4146
|
*
|
|
3975
|
-
*
|
|
3976
|
-
*
|
|
3977
|
-
*
|
|
3978
|
-
*
|
|
3979
|
-
*
|
|
3980
|
-
* (`DOMINANCE_EXEMPT_FILL_CLASSES` ≡ `OPAQUE_FILL_LAYERS`), where band-major
|
|
3981
|
-
* order is the ONLY thing separating the bands, and 15/15 class pairs are
|
|
3982
|
-
* provably unsatisfiable with one layer each. Do not reintroduce it there.
|
|
3983
|
-
* Evidence: `.chrt/perf/2026-07-14-p8-d4-spike.md`.
|
|
4147
|
+
* S-101 replaces S-57 as the data model for Electronic Navigational Charts.
|
|
4148
|
+
* This catalogue maps S-101 feature classes to:
|
|
4149
|
+
* - S-57 equivalents (where they exist)
|
|
4150
|
+
* - Chart No. 1 sections (same organizational structure)
|
|
4151
|
+
* - Portrayal catalogue references (S-100 Portrayal Model)
|
|
3984
4152
|
*
|
|
3985
|
-
*
|
|
3986
|
-
*
|
|
3987
|
-
*
|
|
3988
|
-
*
|
|
3989
|
-
*
|
|
3990
|
-
* NOT the killed axis 2, because what the fill argument protects — paint
|
|
3991
|
-
* order as the sole band separator — does not apply to labels: their
|
|
3992
|
-
* load-bearing order is the cross-class P4 priority ladder (each class keeps
|
|
3993
|
-
* exactly one layer in its ladder slot), and within-class placement priority
|
|
3994
|
-
* rides the `rank*1000 + within-key` symbol-sort-key that labels.ts
|
|
3995
|
-
* documents as designed to survive precisely this merge.
|
|
4153
|
+
* Key S-101 changes from S-57:
|
|
4154
|
+
* - CamelCase feature class names (DepthArea vs DEPARE)
|
|
4155
|
+
* - Complex/structured attributes (nested objects vs flat)
|
|
4156
|
+
* - New feature types for AIS, quality, under-keel clearance
|
|
4157
|
+
* - Removed/merged features for simplification
|
|
3996
4158
|
*
|
|
3997
|
-
*
|
|
3998
|
-
*
|
|
3999
|
-
* `/-band(\d)/` to clamp customer minzoom/scamin overrides to the band's
|
|
4000
|
-
* data floor, on the live public Style API path. Renaming the id silently
|
|
4001
|
-
* unclamps those overrides. Cross-band LABEL layers are the deliberate
|
|
4002
|
-
* exception: they carry every band floor INSIDE the filter (tile-zoom
|
|
4003
|
-
* clauses a customer override cannot touch), which supersedes the clamp —
|
|
4004
|
-
* `bandFloor()` returning 0 for a bare label id is correct, not a gap.
|
|
4005
|
-
* Both halves asserted in `band-collapse.test.ts`.
|
|
4006
|
-
*/
|
|
4007
|
-
|
|
4008
|
-
/**
|
|
4009
|
-
* Which emitter the style generator uses for the dominance fan.
|
|
4010
|
-
* `"legacy"` exists so CI can differentially prove the two equivalent (it is
|
|
4011
|
-
* the oracle in `band-collapse.test.ts`) and as a one-line rollback. It is an
|
|
4012
|
-
* internal knob — deliberately NOT on the exported `StyleGeneratorOptions`,
|
|
4013
|
-
* so it cannot reach `@chrtco/sdk` consumers via `ChrtStyleOptions`.
|
|
4159
|
+
* Reference: IHO S-101 Product Specification (Ed 1.1.0)
|
|
4160
|
+
* IHO S-100 Universal Hydrographic Data Model
|
|
4014
4161
|
*/
|
|
4015
|
-
|
|
4162
|
+
interface S101Feature {
|
|
4163
|
+
/** S-101 camelCase feature class name */
|
|
4164
|
+
featureClass: string;
|
|
4165
|
+
/** Human-readable name */
|
|
4166
|
+
name: string;
|
|
4167
|
+
/** S-57 6-char equivalent acronym, if any */
|
|
4168
|
+
s57Equivalent?: string;
|
|
4169
|
+
/** Chart No. 1 section letter */
|
|
4170
|
+
section: string;
|
|
4171
|
+
/** Group key for clustering */
|
|
4172
|
+
group: string;
|
|
4173
|
+
/** Feature category */
|
|
4174
|
+
category: "geo" | "meta" | "info";
|
|
4175
|
+
/** Description of the feature */
|
|
4176
|
+
description: string;
|
|
4177
|
+
/** S-100 Portrayal Catalogue reference */
|
|
4178
|
+
portrayalRef?: string;
|
|
4179
|
+
/** True if this feature has no S-57 equivalent */
|
|
4180
|
+
isNewInS101: boolean;
|
|
4181
|
+
/** Key attributes specific to this feature */
|
|
4182
|
+
attributes?: string[];
|
|
4183
|
+
}
|
|
4184
|
+
declare const S101_FEATURES: S101Feature[];
|
|
4185
|
+
declare const S101_CHART_SECTIONS: {
|
|
4186
|
+
id: string;
|
|
4187
|
+
label: string;
|
|
4188
|
+
description: string;
|
|
4189
|
+
}[];
|
|
4190
|
+
declare const S101_SYMBOL_GROUPS: {
|
|
4191
|
+
id: string;
|
|
4192
|
+
label: string;
|
|
4193
|
+
section: string;
|
|
4194
|
+
description: string;
|
|
4195
|
+
}[];
|
|
4016
4196
|
|
|
4017
4197
|
/**
|
|
4018
|
-
*
|
|
4019
|
-
*
|
|
4198
|
+
* S-101 Portrayal Catalogue — New Symbol SVGs
|
|
4199
|
+
*
|
|
4200
|
+
* These symbols represent features introduced in S-101 that have no
|
|
4201
|
+
* direct S-57/S-52 equivalent. The existing S-52 symbols are reused
|
|
4202
|
+
* where S-101 retains visual continuity with the S-57 portrayal.
|
|
4203
|
+
*
|
|
4204
|
+
* Reference: IHO S-101 Portrayal Catalogue (Ed 1.1.0)
|
|
4020
4205
|
*/
|
|
4021
4206
|
|
|
4022
|
-
|
|
4023
|
-
version: 8;
|
|
4024
|
-
name: string;
|
|
4025
|
-
metadata: Record<string, unknown>;
|
|
4026
|
-
sources: Record<string, unknown>;
|
|
4027
|
-
sprite?: string;
|
|
4028
|
-
glyphs: string;
|
|
4029
|
-
layers: StyleLayer[];
|
|
4030
|
-
}
|
|
4031
|
-
interface StyleGeneratorOptions extends BuildSourcesOptions {
|
|
4032
|
-
/**
|
|
4033
|
-
* When set, emit a "paper chart" style centered on the selected scale
|
|
4034
|
-
* band, with graceful coverage fallback: the requested band's layers
|
|
4035
|
-
* draw on top where its cells have data; coarser bands (driven by
|
|
4036
|
-
* `CHART_CASCADE_CODES`) fill gaps where the requested band has no
|
|
4037
|
-
* cells. Per-feature SCAMIN minzooms are preserved on every cascade
|
|
4038
|
-
* variant; `maxzoom` is dropped so the user can zoom in indefinitely.
|
|
4039
|
-
*
|
|
4040
|
-
* When omitted (default), continuous mode emits one layer copy per
|
|
4041
|
-
* source band with strict per-band zoom windows so exactly one band
|
|
4042
|
-
* renders at any given continuous zoom.
|
|
4043
|
-
*
|
|
4044
|
-
* `lockedBounds` (optional) restricts chart-mode rendering to a
|
|
4045
|
-
* specific bbox via a `["within"]` filter — applied ONLY to the
|
|
4046
|
-
* requested band's variants. Cascade fallback bands render across the
|
|
4047
|
-
* full viewport so a chart-Harbor user panning offshore still sees
|
|
4048
|
-
* Approach/Coastal data. The frontend pairs this with a translucent
|
|
4049
|
-
* grey overlay outside the bbox so the lock boundary is still visible
|
|
4050
|
-
* to the user (the fallback data is dimmed by the overlay but not
|
|
4051
|
-
* filtered out).
|
|
4052
|
-
*/
|
|
4053
|
-
chartMode?: {
|
|
4054
|
-
band: ScaleBand$1;
|
|
4055
|
-
lockedBounds?: BBox;
|
|
4056
|
-
};
|
|
4057
|
-
/**
|
|
4058
|
-
* Display unit for depth labels (SOUNDG soundings, DEPCNT contour
|
|
4059
|
-
* values). Source data is always meters (S-57 / VALSOU / VALDCO);
|
|
4060
|
-
* "feet" wraps the text-field expression with a unit conversion +
|
|
4061
|
-
* round so the rendered numbers match. Default "meters".
|
|
4062
|
-
*/
|
|
4063
|
-
depthUnits?: "meters" | "feet";
|
|
4064
|
-
/**
|
|
4065
|
-
* Which symbol artwork the style references. "s52" (default) uses the
|
|
4066
|
-
* PresLib-derived S-52 set; "s101" rewrites icon references to the
|
|
4067
|
-
* official S-101 Portrayal Catalogue symbols (s101: image namespace)
|
|
4068
|
-
* where a counterpart exists — see s101-style.ts. "chrt" applies the
|
|
4069
|
-
* CHRT house ATON/LIGHTS glyphs with colour-true tinting — see
|
|
4070
|
-
* chrt-style.ts. Selection logic differences are documented per module.
|
|
4071
|
-
*/
|
|
4072
|
-
symbolSet?: "s52" | "s101" | "chrt" | "raster";
|
|
4073
|
-
/**
|
|
4074
|
-
* The mariner's safety contour in metres — the depth below which a
|
|
4075
|
-
* feature is "dangerous to my hull". Drives both safety-contour
|
|
4076
|
-
* conditional symbology rules:
|
|
4077
|
-
*
|
|
4078
|
-
* - §SOUNDG02 — soundings shoaler than this render in the
|
|
4079
|
-
* high-contrast color; deeper soundings render in the muted color.
|
|
4080
|
-
* - §CSYM02 — isolated dangers (rocks / wrecks / obstructions)
|
|
4081
|
-
* shoaler than this get the DNGCIR01 danger ring.
|
|
4082
|
-
*
|
|
4083
|
-
* Default `DEFAULT_SAFETY_CONTOUR_M` (10 m).
|
|
4084
|
-
*
|
|
4085
|
-
* Does not affect the DEPARE depth-area shading, whose 2/5/10 m bands
|
|
4086
|
-
* are a separate S-52 concept.
|
|
4087
|
-
*/
|
|
4088
|
-
safetyContour?: number;
|
|
4089
|
-
/**
|
|
4090
|
-
* When false, all soundings render in a single shade. Default true.
|
|
4091
|
-
*/
|
|
4092
|
-
twoShadeSoundings?: boolean;
|
|
4093
|
-
/**
|
|
4094
|
-
* Label model for the 9 orientation place-name classes (SEAARE, LNDRGN,
|
|
4095
|
-
* LAKARE, RIVERS, CANALS, BUAARE, AIRARE, LNDARE, PRDARE).
|
|
4096
|
-
*
|
|
4097
|
-
* "legacy" (default) — the per-cell-band orientation fan
|
|
4098
|
-
* (fanOrientationLabelByCellBand): one label per feature per band,
|
|
4099
|
-
* deconflicted only by `_label_anchor` tags and watermark opacity.
|
|
4100
|
-
*
|
|
4101
|
-
* "placename" — 2 PLACENAME symbol layers over the build-side
|
|
4102
|
-
* place-name index (CHRTbaremetal placeNameIndex.ts): one collision-
|
|
4103
|
-
* managed label per named place with a per-feature zoom window; the
|
|
4104
|
-
* orientation fan for those classes is NOT emitted. Requires tiles
|
|
4105
|
-
* built with the PLACENAME side index — on older tiles the layers
|
|
4106
|
-
* simply draw nothing (soft-fail is index-side), which is why the
|
|
4107
|
-
* default stays "legacy" until L2c's rebuild + Maine-coast visual
|
|
4108
|
-
* verification flips it (docs/design/chart-label-deconfliction.md
|
|
4109
|
-
* §2.3). Feature-label classes are untouched either way.
|
|
4110
|
-
*/
|
|
4111
|
-
labels?: "legacy" | "placename";
|
|
4112
|
-
/**
|
|
4113
|
-
* Font weight for SOUNDG labels. Default "semibold" — crisper numerals
|
|
4114
|
-
* at small sizes on screen.
|
|
4115
|
-
*/
|
|
4116
|
-
soundingFontWeight?: "regular" | "semibold";
|
|
4117
|
-
/**
|
|
4118
|
-
* How big the depth figures are drawn — soundings, contour values and the
|
|
4119
|
-
* depth beside a rock, wreck or obstruction. "standard" (default) is
|
|
4120
|
-
* byte-identical to omitting it; "large" enlarges those labels only, and
|
|
4121
|
-
* never their text, colours, sort keys, filters or layer set. See
|
|
4122
|
-
* depth-label-size.ts.
|
|
4123
|
-
*/
|
|
4124
|
-
depthLabelSize?: DepthLabelSize;
|
|
4125
|
-
}
|
|
4126
|
-
declare function generateStyle(palette?: ColorTableName, opts?: StyleGeneratorOptions & {
|
|
4127
|
-
bandFan?: BandFanMode;
|
|
4128
|
-
}): MapboxStyle;
|
|
4129
|
-
declare function generateStyleJSON(palette?: ColorTableName, opts?: StyleGeneratorOptions): string;
|
|
4130
|
-
/** Get summary stats about the generated style */
|
|
4131
|
-
declare function getStyleStats(style: MapboxStyle): {
|
|
4132
|
-
totalLayers: number;
|
|
4133
|
-
fillLayers: number;
|
|
4134
|
-
lineLayers: number;
|
|
4135
|
-
symbolLayers: number;
|
|
4136
|
-
circleLayers: number;
|
|
4137
|
-
sources: number;
|
|
4138
|
-
objectClasses: Set<string>;
|
|
4139
|
-
};
|
|
4207
|
+
declare const S101_NEW_SYMBOLS: NauticalSymbol[];
|
|
4140
4208
|
|
|
4141
4209
|
declare const S101_SOURCE_COMMIT = "05063500e898544c90078ab78a61efc72b7e62f3";
|
|
4142
4210
|
|
|
@@ -4847,7 +4915,11 @@ declare const DEFAULT_CUSTOM_STYLE_CONFIG: CustomStyleConfig;
|
|
|
4847
4915
|
* fields fall back to the platform defaults. Never throws.
|
|
4848
4916
|
*/
|
|
4849
4917
|
declare function sanitizeCustomStyleConfig(raw: unknown): CustomStyleConfig;
|
|
4850
|
-
/**
|
|
4918
|
+
/**
|
|
4919
|
+
* Normalize a `?theme=` value to a colour table name; null for anything else.
|
|
4920
|
+
* Case-insensitive; `-` is accepted for `_` (`eink-mono` = `eink_mono`), so
|
|
4921
|
+
* the e-ink names survive either spelling a caller guesses.
|
|
4922
|
+
*/
|
|
4851
4923
|
declare function normalizeTheme(raw: string | null | undefined): ColorTableName | null;
|
|
4852
4924
|
interface ResolvedTheme {
|
|
4853
4925
|
palette: ColorTableName;
|
|
@@ -5215,7 +5287,8 @@ declare class OfflineError extends Error {
|
|
|
5215
5287
|
|
|
5216
5288
|
/** Options for `chrt.style()`. Extends the atlas style generator options. */
|
|
5217
5289
|
interface ChrtStyleOptions extends StyleGeneratorOptions {
|
|
5218
|
-
/**
|
|
5290
|
+
/** Colour palette: "DAY" (default), "DUSK", "NIGHT", or the e-paper
|
|
5291
|
+
* palettes "EINK_COLOR" / "EINK_MONO" / "EINK_NIGHT" (see `EINK_COLOR_TABLES`). */
|
|
5219
5292
|
palette?: ColorTableName;
|
|
5220
5293
|
}
|
|
5221
5294
|
declare class Chrt {
|
|
@@ -5504,4 +5577,4 @@ declare class Chrt {
|
|
|
5504
5577
|
warmTiles(region?: string): Promise<TileTokenResponse>;
|
|
5505
5578
|
}
|
|
5506
5579
|
|
|
5507
|
-
export { ALL_NAV_AID_LAYERS, ALL_WATER_BODY_LAYERS, AREA_QUERY_LAYERS, ATON_EXPRESSION_CLASSES, type AheadCoverageCell, type AheadFeatureProperties, type AheadOptions, type AheadResponse, type AlongRouteFeatureProperties, type AlongRouteOptions, type AlongRouteResponse, type AreaInspectResult, type AtlasStyle, type AttachOptions, BAND_CODE_ALIASES, BAND_DRAW_ORDER, BAND_PRIORITY_RANGES, BASE_ATTRIBUTION, BASE_BUNDLE_ATTRIBUTION, BASE_BUNDLE_ID, BASE_BUNDLE_MAXZOOM, BASE_BUNDLE_SCHEMA, BASE_BUNDLE_SOURCE_LAYERS, BASE_CLIENT_RASTER_BEFORE_ID, BASE_MAXZOOM, BASE_MINZOOM, BASE_REGION, type BBox, BRIDGE_QUERY_LAYERS, BUILD_MAXZOOM, BUILD_MINZOOM, BUILD_PARAM, type BandCode, type BandPriorityRange, type BridgeInspectResult, type BuildOfflineStyleOptions, type BuildSourcesOptions, CHART_BAND_CODES, CHART_CASCADE_CODES, CHART_SECTIONS, CHRTRASTER_REF_CROPS, CHRTRASTER_SVGS, CHRT_ATON_COLORS, CHRT_GLYPH_NAMES, CHRT_GLYPH_SVGS, CHRT_ICON_EXPRESSIONS, CHRT_ICON_PREFIX, CHRT_SDF_GLYPHS, CHRT_STYLE_MODES, type CandidateQueryOptions, type CandidatesEventContext, type CellDeletedEvent, type CellDetail, type CellEventData, type CellNewEvent, type CellUpdatedData, type CellUpdatedEvent, type CellsOptions, type CellsResponse, type ChartSection, Chrt, type ChrtConfig, ChrtError, type ChrtStyleMode, type ChrtStyleOptions, type ChrtStyleTheme, type ChrtSymbolSet, type ClickAnchor, ColorTableName, type CoverageOptions, type CoverageResponse, type CoverageRouteCell, type CoverageRouteOptions, type CoverageRouteResponse, type CoverageSource, type CustomStyleConfig, DEFAULT_CLICK_TOLERANCE, DEFAULT_CUSTOM_STYLE_CONFIG, DEFAULT_DEPTH_LABEL_SIZE, DEFAULT_INSPECT_CLASS_RANK, DEFAULT_LABEL_SETTINGS, DEFAULT_NAV_AID_SETTINGS, DEFAULT_REGION, DEFAULT_SAFETY_CONTOUR_M, DEFAULT_SOUNDING_SETTINGS, DEFAULT_TILE_BASE_URL, DEFAULT_TILE_REGION, DEFAULT_WATER_BODY_SETTINGS, DEPARE_FILL_BRANCH_TOKENS, DEPARE_FILL_FALLBACK_TOKEN, DEPTH_LABEL_CLASSES, DEPTH_LABEL_SIZES, DRAPEABLE_LAYER_TYPES, type DecodedAreaFeature, type DecodedBridge, type DecodedNavAid, type DecodedProperty, type DepthLabelSize, type DisplayCategory, type DisplayMode, type FeatureCollection, type FeaturesOptions, type FetchStyleOptions, FileSystemAdapter, type FlashPattern, type FlashPhase, type GenerateCustomStyleOptions, type GeneratedCustomStyle, type GeoJsonFeature, type GeoJsonGeometry, type GeomType, INSPECT_CLASS_RANK, INSPECT_RANK_DEVIATIONS, type InspectCandidate, type InspectCandidateSet, type InspectEnrichment, type InspectEventContext, type InspectNotice, type InspectOptions, type InspectResult, type InspectTargetClass, type InspectableFeature, InteractClient, type InteractEntitlement, InteractError, type InteractErrorCode, type InteractHandle, type InteractMapLike, type InteractMapMouseEvent, LABELED_LAYERS, LABEL_BEHAVIOR, LABEL_LAYER_GROUPS, LABEL_PRIORITY, LAMP_CORE_LAYER_ID, LAMP_GLOW_LAYER_ID, LAMP_LAYER_IDS, LAMP_TICK_MS, LAND_ATTRIBUTION, LAND_BUILD_MAXZOOM, LAND_REGION, LARGE_SOUNDING_PADDING_PX, type LabelBehavior, type LabelConfigOptions, type LabelLayerConfig, type LabelSettings, type LampLayer, type LookupEntry, type MapLibreStyle, type MapboxStyle, type MapboxVectorSource, type MarineAlert, type MarineAlertsOptions, type MarineAlertsResponse, type MarineConditionsObservation, type MarineConditionsOptions, type MarineConditionsResponse, type MarineConditionsSeries, type MarineForecastOptions, type MarineForecastPeriod, type MarineForecastResponse, type MarineSeas, type MarineStation, type MarineSwellTrain, type MarineWind, type MarineZoneRef, NAUTICAL_SYMBOLS, NAV_AID_LAYER_GROUPS, NAV_AID_QUERY_LAYERS, NIGHT_INK, NIGHT_MUTED_INK, NON_SOLAS_DISCLAIMER, NON_SOLAS_DISCLAIMER_SHORT, type NauticalCategory, type NauticalSymbol, type NavAidInspectResult, type NavAidSettings, type NearbyMarineStation, OPAQUE_SPLIT_OF, type OfflineBundleResponse, type OfflineDownloadOptions, type OfflineDownloadProgress, type OfflineDownloadResult, OfflineError, type OfflineErrorCode, type OfflineFetchStyleOptions, type OfflineHeartbeatOptions, type OfflineRegionSummary, type OfflineRemoveOptions, OfflineStyleError, type OfflineStylePlatform, type OfflineStyleResponse, PLACENAME_LAND_CLASSES, PLACENAME_SOURCE_LAYER, PLACENAME_WATER_CLASSES, type ParsedSigseqTerms, type PmtilesVectorSource, type Poi, type PoiCoverage, type PoiDataset, type PoiOptions, type PoiResponse, type QueryFeatureProperties, type QueryOptions, type QueryResponse, RASTER_ATON_CLASSES, RASTER_GLYPH_NAMES, RASTER_ICON_PREFIX, RELIEF_ATTRIBUTION, RELIEF_ENCODING, RELIEF_REGION, RELIEF_TILE_SIZE, type ResolvedStyle, type ResolvedTheme, type S101ArtworkProvenance, type S101Feature, S101_AREA_FILL_NAMES, S101_CHART_SECTIONS, S101_FEATURES, S101_ICON_PREFIX, S101_LINE_STYLE_NAMES, S101_NEW_SYMBOLS, S101_NO_OFFICIAL_COUNTERPART, S101_SOURCE_COMMIT, S101_SYMBOL_GROUPS, S101_SYMBOL_NAMES, S52_ATON_LOOKUPS, S52_ATON_LOOKUPS_PAPER, S52_DRAW_ORDER, S52_LOOKUP, S52_PATTERN_SPRITE_PREFIX, SIGPER_TOLERANCE_SECONDS, SIGSEQ_MAX_TERMS, SOUNDING_LAYERS, SYMBOL_GROUPS, SYMBOL_MAP, type ScaleBand, type SearchCoverageNotice, type SearchHit, type SearchOptions, type SearchResponse, type SectorArcFeature, type SectorArcFeatureCollection, type SectorInfo, type SigseqRefusal, type SigseqTerm, type SoundingSettings, type SourceMode, type StyleGeneratorOptions, type StyleLayer, type StyleUrlOptions, type SymbolGroup, TileAuth, type TileGroup, type TileGroupsResponse, TileTokenError, type TileTokenErrorCode, type TileTokenResponse, type TransformRequest, type TransformedRequest, type VectorSourceSpec, type VesselProfile, WATER_BODY_LAYER_GROUPS, type WaterBodySettings, WeatherEndpoint, type WeatherReading, type WebhookEvent, type WebhookEventType, type WebhookPayload, applyBaseBundle, applyChrtSymbolSet, applyColorTheme, applyCustomStyleSettings, applyDepthLabelSize, applyRasterSymbolSet, applyS101SymbolSet, atonIconExpression, bandFilterExpression, buildAirportTierExpression, buildBuiltUpAreaTierExpression, buildFlashPattern, buildLabelLayer, buildLakeTierExpression, buildLampLayers, buildLandAreaTierExpression, buildLandRegionTierExpression, buildLayersForClass, buildOfflineStyle, buildPlaceNameLayers, buildRiverTierExpression, buildSeaAreaTierExpression, buildSectorArcGeoJSON, buildSectorArcsFC, buildSectorsFromFeatures, buildSources, candidateRank, capLuminance, cellBandCharacters, cellBandMatch, chrtAtonTintExpression, chrtHouseColor, chrtLightTintExpression, collectCandidates, collectClickCandidates, combineWithBandFilter, contrastRatio, daymarkColor, decimateFeatures, decodeAreaFeatureProps, decodeBridgeProps, decodeCandidate, decodeNavAidProps, depareColor, depareFillExpression, depthAreaClassLayerId, depthAreaSplitIds, deriveMarinerName, drapeHalves, drapedFirst, extractNavAidDesignation, featureIdentity, generateCustomStyle, generateSpriteManifest, generateSpriteSheet, generateStyle, generateStyleJSON, getAvailableLineSymbols, getAvailablePatterns, getAvailablePointSymbols, getCollisionSettings, getDrawPriority, getGridSizeForZoom, getIconExpression, getLabelBehavior, getLabelConfig, getLabelPriority, getLookupEntry, getMaxCellsForZoom, getOrderedClasses, getRasterSvg, getS52SvgString, getS52SymbolStats, getStyleStats, getSymbolSvgString, getThemedS101Svg, getThemedS52Svg, getTopmarkMeaning, hazardColor, hazardFillExpression, isDepthAreaClassLayerId, isDrapeable, isLabelLayerVisible, isMapLive, isNavAidLayer, isNavAidLayerVisible, isSoundingLayerVisible, isVisibleInMode, isWaterBodyLayerVisible, labelSortKey, lampRhythmColour, lampRhythmOpacity, lateralColor, lateralFillExpression, lightColor, lightFillExpression, lightsIconExpression, normalizeStyleMode, normalizeTheme, opaqueSplitBaseOf, paginate, parseDepthLabelSize, parseListCodes, parseSigseqTerms, parseWebhook, patternSpriteId, preprocessLights, preprocessNavAids, preprocessSoundings, preprocessWaterBodies, rasterAtonIconExpression, relativeLuminance, resolveCustomTheme, resolveRasterImage, resolveS101Color, resolveStyle, resolveTargetClass, rhythmProperties, s101ArtworkProvenance, sanitizeCustomStyleConfig, scaleLinearLight, scaleSizeValue, scaminToMinZoom, sectorLimitToArcBearing, splitOpaqueDepthAreas, styleModeBand, terrainStackCount, themeChrtGlyph, tileTemplate, uncoveredSectorArcs, withinBboxFilter, worldMinusBboxPolygon };
|
|
5580
|
+
export { ALL_NAV_AID_LAYERS, ALL_WATER_BODY_LAYERS, AREA_QUERY_LAYERS, ATON_EXPRESSION_CLASSES, type AheadCoverageCell, type AheadFeatureProperties, type AheadOptions, type AheadResponse, type AlongRouteFeatureProperties, type AlongRouteOptions, type AlongRouteResponse, type AreaInspectResult, type AtlasStyle, type AttachOptions, BAND_CODE_ALIASES, BAND_DRAW_ORDER, BAND_PRIORITY_RANGES, BASE_ATTRIBUTION, BASE_BUNDLE_ATTRIBUTION, BASE_BUNDLE_ID, BASE_BUNDLE_MAXZOOM, BASE_BUNDLE_SCHEMA, BASE_BUNDLE_SOURCE_LAYERS, BASE_CLIENT_RASTER_BEFORE_ID, BASE_MAXZOOM, BASE_MINZOOM, BASE_REGION, type BBox, BRIDGE_QUERY_LAYERS, BUILD_MAXZOOM, BUILD_MINZOOM, BUILD_PARAM, type BandCode, type BandPriorityRange, type BridgeInspectResult, type BuildOfflineStyleOptions, type BuildSourcesOptions, CHART_BAND_CODES, CHART_CASCADE_CODES, CHART_SECTIONS, CHRTRASTER_REF_CROPS, CHRTRASTER_SVGS, CHRT_ATON_COLORS, CHRT_GLYPH_NAMES, CHRT_GLYPH_SVGS, CHRT_ICON_EXPRESSIONS, CHRT_ICON_PREFIX, CHRT_SDF_GLYPHS, CHRT_STYLE_MODES, type CandidateQueryOptions, type CandidatesEventContext, type CellDeletedEvent, type CellDetail, type CellEventData, type CellNewEvent, type CellUpdatedData, type CellUpdatedEvent, type CellsOptions, type CellsResponse, type ChartSection, Chrt, type ChrtConfig, ChrtError, type ChrtStyleMode, type ChrtStyleOptions, type ChrtStyleTheme, type ChrtSymbolSet, type ClickAnchor, ColorTableName, type CoverageOptions, type CoverageResponse, type CoverageRouteCell, type CoverageRouteOptions, type CoverageRouteResponse, type CoverageSource, type CustomStyleConfig, DEFAULT_CLICK_TOLERANCE, DEFAULT_CUSTOM_STYLE_CONFIG, DEFAULT_DEPTH_LABEL_SIZE, DEFAULT_INSPECT_CLASS_RANK, DEFAULT_LABEL_SETTINGS, DEFAULT_NAV_AID_SETTINGS, DEFAULT_REGION, DEFAULT_SAFETY_CONTOUR_M, DEFAULT_SOUNDING_SETTINGS, DEFAULT_TILE_BASE_URL, DEFAULT_TILE_REGION, DEFAULT_WATER_BODY_SETTINGS, DEPARE_FILL_BRANCH_TOKENS, DEPARE_FILL_FALLBACK_TOKEN, DEPTH_LABEL_CLASSES, DEPTH_LABEL_SIZES, DRAPEABLE_LAYER_TYPES, type DecodedAreaFeature, type DecodedBridge, type DecodedNavAid, type DecodedProperty, type DepthLabelSize, type DisplayCategory, type DisplayMode, EINK_DANGER_PATTERN, EINK_DOTS_PATTERN, EINK_HATCH_PATTERN, type FeatureCollection, type FeaturesOptions, type FetchStyleOptions, FileSystemAdapter, type FlashPattern, type FlashPhase, type GenerateCustomStyleOptions, type GeneratedCustomStyle, type GeoJsonFeature, type GeoJsonGeometry, type GeomType, INSPECT_CLASS_RANK, INSPECT_RANK_DEVIATIONS, type InspectCandidate, type InspectCandidateSet, type InspectEnrichment, type InspectEventContext, type InspectNotice, type InspectOptions, type InspectResult, type InspectTargetClass, type InspectableFeature, InteractClient, type InteractEntitlement, InteractError, type InteractErrorCode, type InteractHandle, type InteractMapLike, type InteractMapMouseEvent, LABELED_LAYERS, LABEL_BEHAVIOR, LABEL_LAYER_GROUPS, LABEL_PRIORITY, LAMP_CORE_LAYER_ID, LAMP_GLOW_LAYER_ID, LAMP_LAYER_IDS, LAMP_TICK_MS, LAND_ATTRIBUTION, LAND_BUILD_MAXZOOM, LAND_REGION, LARGE_SOUNDING_PADDING_PX, type LabelBehavior, type LabelConfigOptions, type LabelLayerConfig, type LabelSettings, type LampLayer, type LookupEntry, type MapLibreStyle, type MapboxStyle, type MapboxVectorSource, type MarineAlert, type MarineAlertsOptions, type MarineAlertsResponse, type MarineConditionsObservation, type MarineConditionsOptions, type MarineConditionsResponse, type MarineConditionsSeries, type MarineForecastOptions, type MarineForecastPeriod, type MarineForecastResponse, type MarineSeas, type MarineStation, type MarineSwellTrain, type MarineWind, type MarineZoneRef, NAUTICAL_SYMBOLS, NAV_AID_LAYER_GROUPS, NAV_AID_QUERY_LAYERS, NIGHT_INK, NIGHT_MUTED_INK, NON_SOLAS_DISCLAIMER, NON_SOLAS_DISCLAIMER_SHORT, type NauticalCategory, type NauticalSymbol, type NavAidInspectResult, type NavAidSettings, type NearbyMarineStation, OPAQUE_SPLIT_OF, type OfflineBundleResponse, type OfflineDownloadOptions, type OfflineDownloadProgress, type OfflineDownloadResult, OfflineError, type OfflineErrorCode, type OfflineFetchStyleOptions, type OfflineHeartbeatOptions, type OfflineRegionSummary, type OfflineRemoveOptions, OfflineStyleError, type OfflineStylePlatform, type OfflineStyleResponse, PLACENAME_LAND_CLASSES, PLACENAME_SOURCE_LAYER, PLACENAME_WATER_CLASSES, type ParsedSigseqTerms, type PmtilesVectorSource, type Poi, type PoiCoverage, type PoiDataset, type PoiOptions, type PoiResponse, type QueryFeatureProperties, type QueryOptions, type QueryResponse, RASTER_ATON_CLASSES, RASTER_GLYPH_NAMES, RASTER_ICON_PREFIX, RELIEF_ATTRIBUTION, RELIEF_ENCODING, RELIEF_REGION, RELIEF_TILE_SIZE, type ResolvedStyle, type ResolvedTheme, type S101ArtworkProvenance, type S101Feature, S101_AREA_FILL_NAMES, S101_CHART_SECTIONS, S101_FEATURES, S101_ICON_PREFIX, S101_LINE_STYLE_NAMES, S101_NEW_SYMBOLS, S101_NO_OFFICIAL_COUNTERPART, S101_SOURCE_COMMIT, S101_SYMBOL_GROUPS, S101_SYMBOL_NAMES, S52_ATON_LOOKUPS, S52_ATON_LOOKUPS_PAPER, S52_DRAW_ORDER, S52_LOOKUP, S52_PATTERN_SPRITE_PREFIX, SIGPER_TOLERANCE_SECONDS, SIGSEQ_MAX_TERMS, SOUNDING_LAYERS, SYMBOL_GROUPS, SYMBOL_MAP, type ScaleBand, type SearchCoverageNotice, type SearchHit, type SearchOptions, type SearchResponse, type SectorArcFeature, type SectorArcFeatureCollection, type SectorInfo, type SigseqRefusal, type SigseqTerm, type SoundingSettings, type SourceMode, type StyleGeneratorOptions, type StyleLayer, type StyleUrlOptions, type SymbolGroup, TileAuth, type TileGroup, type TileGroupsResponse, TileTokenError, type TileTokenErrorCode, type TileTokenResponse, type TransformRequest, type TransformedRequest, type VectorSourceSpec, type VesselProfile, WATER_BODY_LAYER_GROUPS, type WaterBodySettings, WeatherEndpoint, type WeatherReading, type WebhookEvent, type WebhookEventType, type WebhookPayload, applyBaseBundle, applyChrtSymbolSet, applyColorTheme, applyCustomStyleSettings, applyDepthLabelSize, applyEinkPortrayal, applyRasterSymbolSet, applyS101SymbolSet, atonIconExpression, bandFilterExpression, buildAirportTierExpression, buildBuiltUpAreaTierExpression, buildFlashPattern, buildLabelLayer, buildLakeTierExpression, buildLampLayers, buildLandAreaTierExpression, buildLandRegionTierExpression, buildLayersForClass, buildOfflineStyle, buildPlaceNameLayers, buildRiverTierExpression, buildSeaAreaTierExpression, buildSectorArcGeoJSON, buildSectorArcsFC, buildSectorsFromFeatures, buildSources, candidateRank, capLuminance, cellBandCharacters, cellBandMatch, chrtAtonTintExpression, chrtHouseColor, chrtLightTintExpression, collectCandidates, collectClickCandidates, combineWithBandFilter, contrastRatio, daymarkColor, decimateFeatures, decodeAreaFeatureProps, decodeBridgeProps, decodeCandidate, decodeNavAidProps, depareColor, depareFillExpression, depthAreaClassLayerId, depthAreaSplitIds, deriveMarinerName, drapeHalves, drapedFirst, extractNavAidDesignation, featureIdentity, generateCustomStyle, generateSpriteManifest, generateSpriteSheet, generateStyle, generateStyleJSON, getAvailableLineSymbols, getAvailablePatterns, getAvailablePointSymbols, getCollisionSettings, getDrawPriority, getGridSizeForZoom, getIconExpression, getLabelBehavior, getLabelConfig, getLabelPriority, getLookupEntry, getMaxCellsForZoom, getOrderedClasses, getRasterSvg, getS52SvgString, getS52SymbolStats, getStyleStats, getSymbolSvgString, getThemedS101Svg, getThemedS52Svg, getTopmarkMeaning, hazardColor, hazardFillExpression, isDepthAreaClassLayerId, isDrapeable, isLabelLayerVisible, isMapLive, isNavAidLayer, isNavAidLayerVisible, isSoundingLayerVisible, isVisibleInMode, isWaterBodyLayerVisible, labelSortKey, lampRhythmColour, lampRhythmOpacity, lateralColor, lateralFillExpression, lightColor, lightFillExpression, lightsIconExpression, normalizeStyleMode, normalizeTheme, opaqueSplitBaseOf, paginate, parseDepthLabelSize, parseListCodes, parseSigseqTerms, parseWebhook, patternSpriteId, preprocessLights, preprocessNavAids, preprocessSoundings, preprocessWaterBodies, rasterAtonIconExpression, relativeLuminance, resolveCustomTheme, resolveRasterImage, resolveS101Color, resolveStyle, resolveTargetClass, rhythmProperties, s101ArtworkProvenance, safetyContourValues, sanitizeCustomStyleConfig, scaleLinearLight, scaleSizeValue, scaminToMinZoom, sectorLimitToArcBearing, splitOpaqueDepthAreas, styleModeBand, terrainStackCount, themeChrtGlyph, tileTemplate, uncoveredSectorArcs, withinBboxFilter, worldMinusBboxPolygon };
|