isard 2.5.0 → 2.6.0

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 CHANGED
@@ -5,6 +5,25 @@ versions [Semantic Versioning](https://semver.org) (before 1.0.0, a minor versio
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [2.6.0] - 2026-11-02
9
+
10
+ With `isard-react-native` and `isard-map` (Python) 2.6.0.
11
+
12
+ ### Added
13
+
14
+ - The OGC APIs (#177): `ogcFeatures(url, collection, { bbox, filter, crs, properties, count })` gives the features of
15
+ an OGC API - Features collection as GeoJSON (a CQL2 filter, Part 3; another CRS, Part 2; the pages followed by their
16
+ `next` links); `ogcTiles`, `ogcMapTiles` and `ogcVectorSource` read an OGC API - Tiles tileset in Web Mercator (or
17
+ a list of them) into a raster layer's options or a vector style's source. `ogcFeatures` as a React source, and
18
+ `ogc_features` in Python (a GeoDataFrame). The guide's OGC APIs page; the examples OGC API - Features and OGC API -
19
+ Tiles, with Find a building, in a section of their own, Search and the OGC APIs.
20
+
21
+ ### Changed
22
+
23
+ - Find a building finds the building at an address typed (the Géoplateforme's completion), anywhere in France.
24
+ - The section box example no longer has a slider turning a box (it turned neither a cylinder nor a prism): the box is
25
+ turned by its handles.
26
+
8
27
  ## [2.5.0] - 2026-11-02
9
28
 
10
29
  With `isard-react-native` and `isard-map` (Python) 2.5.0.
@@ -20,6 +39,9 @@ With `isard-react-native` and `isard-map` (Python) 2.5.0.
20
39
 
21
40
  ### Fixed
22
41
 
42
+ - The basemap workers' tessellation holds a third less memory on a dense city's tile (Paris by night at a phone's
43
+ size: 35 MB a worker in place of 57): the raised sublayers extruded one after the other into the tile's arrays,
44
+ reserved at once and grown by a quarter at most, no longer copied from one to the next nor doubled.
23
45
  - The API page listed `map.camera`, `map.query` and `map.effects`, gone since the public API was made consistent.
24
46
 
25
47
  ## [2.4.2] - 2026-11-02
package/README.md CHANGED
@@ -187,8 +187,8 @@ More in [Develop and release](https://ideal-adventure-zqn6y6p.pages.github.io/gu
187
187
  By priority:
188
188
 
189
189
  - **P1**, next: the memory budget measured on a phone (a phone closes a page past about a gigabyte).
190
- - **P2**, then: OGC API - Features and Tiles (#177); virtual point clouds (#183); Cloud-Optimized GeoTIFF (#184);
191
- measured against iTowns on 3D data (#178); rasters draped within an area; a performance report.
190
+ - **P2**, then: virtual point clouds (#183); Cloud-Optimized GeoTIFF (#184); measured against iTowns on 3D data
191
+ (#178); rasters draped within an area; a performance report.
192
192
  - **P3**, later: several elevation sources (#179); a time for layers (#180); objects moving along paths (#181); photos
193
193
  projected onto the meshes (#187) and video in the scene; composable effects over the frame (#182).
194
194
  - **P4**, when time allows: Gaussian splats (#186), WebXR (#185), the whole MapLibre style drawn as vectors, a 3D
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The OGC APIs: features from OGC API - Features (by box and by a CQL2 filter, in another CRS, paged by their links)
3
+ * for the feature layers; tiles from OGC API - Tiles (a tileset's metadata: its URL template, its levels) for a raster
4
+ * layer or a vector style's source. The tilesets in Web Mercator (`WebMercatorQuad`), the engine's grid.
5
+ */
6
+ import type { FeatureCollection, Properties } from '../layers/features.ts';
7
+ import type { RasterOptions } from '../types.ts';
8
+ /** What `ogcFeatures` asks for */
9
+ export interface OgcFeaturesOptions {
10
+ /** The box the features meet: west, south, east, north (degrees) */
11
+ bbox?: [west: number, south: number, east: number, north: number];
12
+ /** A CQL2 filter (Part 3), as text by default: `"hauteur > 30"`, `"S_INTERSECTS(geometry, POINT(2.33 48.87))"` */
13
+ filter?: string;
14
+ /** The filter's language (default `'cql2-text'`) */
15
+ filterLang?: 'cql2-text' | 'cql2-json';
16
+ /** The CRS of the features' coordinates (Part 2), a URI (`'http://www.opengis.net/def/crs/EPSG/0/2154'`): the
17
+ * collection names it in its `crs` member, the feature layers reproject it. Default the server's, CRS84 */
18
+ crs?: string;
19
+ /** The properties kept (default all of them) */
20
+ properties?: string[];
21
+ /** At most this many features (default 10 000) */
22
+ count?: number;
23
+ /** Features a page (default 1000), the next pages followed by their `next` link */
24
+ pageSize?: number;
25
+ signal?: AbortSignal;
26
+ }
27
+ /**
28
+ * Features of a collection of an OGC API - Features service as GeoJSON: `await ogcFeatures(url, 'buildings', { bbox,
29
+ * filter: 'height > 30' })`, `url` the service's landing page. The pages followed by their `next` links until `count`
30
+ * features or the last page. With `crs`, the coordinates come in it, the collection naming it (`crs` member)
31
+ */
32
+ export declare const ogcFeatures: <P = Properties>(url: string | URL, collection: string, options?: OgcFeaturesOptions) => Promise<FeatureCollection<P>>;
33
+ /** A tileset of OGC API - Tiles as isard reads it: its tiles' URL template (`{z}`, `{x}`, `{y}`), its levels, whether
34
+ * its tiles are images (`'map'`) or vector tiles (`'vector'`), its credits */
35
+ export interface OgcTileset {
36
+ url: string;
37
+ minZoom: number;
38
+ maxZoom: number;
39
+ dataType: 'map' | 'vector';
40
+ attribution?: string;
41
+ }
42
+ /**
43
+ * A tileset of OGC API - Tiles read from its metadata (`…/tiles/WebMercatorQuad`, or the list of a collection's
44
+ * tilesets `…/tiles`, its Web Mercator one taken): its tiles' URL template, its levels, its kind. In Web Mercator only
45
+ * (`WebMercatorQuad`, the engine's grid)
46
+ */
47
+ export declare const ogcTiles: (url: string | URL, { signal }?: {
48
+ signal?: AbortSignal;
49
+ }) => Promise<OgcTileset>;
50
+ /** A raster layer's options from an OGC API - Tiles map tileset (`ogcTiles`): `map.addRaster(await ogcMapTiles(url))` */
51
+ export declare const ogcMapTiles: (url: string | URL, options?: Omit<RasterOptions, "url"> & {
52
+ signal?: AbortSignal;
53
+ }) => Promise<RasterOptions>;
54
+ /** A vector style's source from an OGC API - Tiles vector tileset (`ogcTiles`): `{ type: 'vector', tiles, minzoom,
55
+ * maxzoom }`, in a MapLibre style's `sources` given to `map.vectorTiles({ style })` */
56
+ export declare const ogcVectorSource: (url: string | URL, { signal }?: {
57
+ signal?: AbortSignal;
58
+ }) => Promise<{
59
+ type: "vector";
60
+ tiles: string[];
61
+ minzoom: number;
62
+ maxzoom: number;
63
+ attribution?: string;
64
+ }>;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The OGC APIs: features from OGC API - Features (by box and by a CQL2 filter, in another CRS, paged by their links)
3
+ * for the feature layers; tiles from OGC API - Tiles (a tileset's metadata: its URL template, its levels) for a raster
4
+ * layer or a vector style's source. The tilesets in Web Mercator (`WebMercatorQuad`), the engine's grid.
5
+ */
6
+ import { fetchOk } from "../util/fetch.js";
7
+ import { withHeaders } from "../util/requests.js";
8
+ const isRecord = (value) => typeof value === 'object' && value !== null;
9
+ const isLink = (value) => isRecord(value) && typeof value.href === 'string';
10
+ /** The links of an answer */
11
+ const linksOf = (value) => isRecord(value) && Array.isArray(value.links) ? value.links.filter(isLink) : [];
12
+ const isFeaturesPage = (value) => isRecord(value) && Array.isArray(value.features);
13
+ /** The JSON of a URL, the page's request headers on it */
14
+ const json = async (url, signal) => (await fetchOk(url, withHeaders(url, { ...(signal ? { signal } : {}), headers: { Accept: 'application/json' } }))).json();
15
+ /** A link's URL, relative to the answer it came in */
16
+ const resolve = (href, base) => new URL(href, base);
17
+ /**
18
+ * Features of a collection of an OGC API - Features service as GeoJSON: `await ogcFeatures(url, 'buildings', { bbox,
19
+ * filter: 'height > 30' })`, `url` the service's landing page. The pages followed by their `next` links until `count`
20
+ * features or the last page. With `crs`, the coordinates come in it, the collection naming it (`crs` member)
21
+ */
22
+ export const ogcFeatures = async (url, collection, options = {}) => {
23
+ const { bbox, filter, filterLang = 'cql2-text', crs, properties, count = 10_000, pageSize = 1000, signal } = options;
24
+ const items = new URL(`collections/${encodeURIComponent(collection)}/items`, `${String(url).replace(/\/?$/, '/')}`);
25
+ // Spaces as %20, not + (URLSearchParams): a server re-encodes a + in its next link (%2B), which breaks the filter
26
+ // past one page
27
+ items.search = Object.entries({
28
+ f: 'json',
29
+ limit: String(Math.max(1, Math.min(pageSize, count))),
30
+ ...(bbox ? { bbox: bbox.join(',') } : {}),
31
+ ...(filter ? { filter, 'filter-lang': filterLang } : {}),
32
+ ...(crs ? { crs } : {}),
33
+ ...(properties ? { properties: properties.join(',') } : {}),
34
+ })
35
+ .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
36
+ .join('&');
37
+ const features = [];
38
+ let next = items;
39
+ while (next && features.length < count) {
40
+ const page = await json(next, signal);
41
+ if (!isFeaturesPage(page))
42
+ throw new Error(`isard: ${String(next)}: not a GeoJSON feature collection`);
43
+ features.push(...page.features);
44
+ const link = linksOf(page).find((l) => l.rel === 'next');
45
+ // An empty page ends it whatever its links say (a server that always links further)
46
+ next = link && page.features.length > 0 ? resolve(link.href, next) : undefined;
47
+ }
48
+ return {
49
+ type: 'FeatureCollection',
50
+ features: features.slice(0, count),
51
+ ...(crs ? { crs: { type: 'name', properties: { name: crs } } } : {}),
52
+ };
53
+ };
54
+ /** The level numbers of a tileset's limits, if it has some */
55
+ const levelsOf = (tileset) => (Array.isArray(tileset.tileMatrixSetLimits) ? tileset.tileMatrixSetLimits : [])
56
+ .map((limit) => (isRecord(limit) ? Number(limit.tileMatrix) : Number.NaN))
57
+ .filter(Number.isInteger);
58
+ /** Whether a tileset's grid is Web Mercator's */
59
+ const isWebMercator = (tileset) => [tileset.tileMatrixSetURI, tileset.tileMatrixSetId, tileset.tileMatrixSet].some((id) => typeof id === 'string' && /WebMercatorQuad$/i.test(id));
60
+ /**
61
+ * A tileset of OGC API - Tiles read from its metadata (`…/tiles/WebMercatorQuad`, or the list of a collection's
62
+ * tilesets `…/tiles`, its Web Mercator one taken): its tiles' URL template, its levels, its kind. In Web Mercator only
63
+ * (`WebMercatorQuad`, the engine's grid)
64
+ */
65
+ export const ogcTiles = async (url, { signal } = {}) => {
66
+ const answer = await json(url, signal);
67
+ if (!isRecord(answer))
68
+ throw new Error(`isard: ${String(url)}: not a tileset`);
69
+ // A list of tilesets: its Web Mercator one
70
+ if (Array.isArray(answer.tilesets)) {
71
+ const listed = answer.tilesets.filter(isRecord).find(isWebMercator);
72
+ // Its own link (`self`), else the first that is not its tiling scheme's
73
+ const links = listed ? linksOf(listed) : [];
74
+ const link = links.find((l) => l.rel === 'self') ?? links.find((l) => !l.rel?.endsWith('tiling-scheme'));
75
+ if (!link)
76
+ throw new Error(`isard: ${String(url)}: no tileset in Web Mercator (WebMercatorQuad)`);
77
+ return ogcTiles(resolve(link.href, url), signal ? { signal } : {});
78
+ }
79
+ if (!isWebMercator(answer))
80
+ throw new Error(`isard: ${String(url)}: a tileset in Web Mercator (WebMercatorQuad) only`);
81
+ const tiles = linksOf(answer).filter((l) => l.rel === 'item' && l.href.includes('{tileMatrix}'));
82
+ const vector = tiles.find((l) => /mapbox-vector-tile|mvt|pbf/i.test(l.type ?? ''));
83
+ const image = tiles.find((l) => /^image\//.test(l.type ?? ''));
84
+ const dataType = answer.dataType === 'vector' || (vector && !image) ? 'vector' : 'map';
85
+ const link = (dataType === 'vector' ? vector : image) ?? tiles[0];
86
+ if (!link)
87
+ throw new Error(`isard: ${String(url)}: no URL template of its tiles`);
88
+ const template = resolve(link.href.replace(/\{(tileMatrix|tileRow|tileCol)\}/g, '_$1_'), url)
89
+ .toString()
90
+ .replace('_tileMatrix_', '{z}')
91
+ .replace('_tileRow_', '{y}')
92
+ .replace('_tileCol_', '{x}');
93
+ const levels = levelsOf(answer);
94
+ return {
95
+ url: template,
96
+ minZoom: levels.length > 0 ? Math.min(...levels) : 0,
97
+ maxZoom: levels.length > 0 ? Math.max(...levels) : 22,
98
+ dataType,
99
+ ...(typeof answer.attribution === 'string' ? { attribution: answer.attribution } : {}),
100
+ };
101
+ };
102
+ /** A raster layer's options from an OGC API - Tiles map tileset (`ogcTiles`): `map.addRaster(await ogcMapTiles(url))` */
103
+ export const ogcMapTiles = async (url, options = {}) => {
104
+ const { signal, ...raster } = options;
105
+ const tileset = await ogcTiles(url, signal ? { signal } : {});
106
+ if (tileset.dataType !== 'map')
107
+ throw new Error(`isard: ${String(url)}: vector tiles, a style's source`);
108
+ return {
109
+ url: tileset.url,
110
+ minZoom: tileset.minZoom,
111
+ maxZoom: tileset.maxZoom,
112
+ ...(tileset.attribution ? { attribution: tileset.attribution } : {}),
113
+ ...raster,
114
+ };
115
+ };
116
+ /** A vector style's source from an OGC API - Tiles vector tileset (`ogcTiles`): `{ type: 'vector', tiles, minzoom,
117
+ * maxzoom }`, in a MapLibre style's `sources` given to `map.vectorTiles({ style })` */
118
+ export const ogcVectorSource = async (url, { signal } = {}) => {
119
+ const tileset = await ogcTiles(url, signal ? { signal } : {});
120
+ if (tileset.dataType !== 'vector')
121
+ throw new Error(`isard: ${String(url)}: images, a raster layer's tiles`);
122
+ return {
123
+ type: 'vector',
124
+ tiles: [tileset.url],
125
+ minzoom: tileset.minZoom,
126
+ maxzoom: tileset.maxZoom,
127
+ ...(tileset.attribution ? { attribution: tileset.attribution } : {}),
128
+ };
129
+ };
130
+ //# sourceMappingURL=ogcapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ogcapi.js","sourceRoot":"","sources":["../../src/data/ogcapi.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The OGC APIs: features from OGC API - Features (by box and by a CQL2 filter, in another CRS, paged by their links)\n * for the feature layers; tiles from OGC API - Tiles (a tileset's metadata: its URL template, its levels) for a raster\n * layer or a vector style's source. The tilesets in Web Mercator (`WebMercatorQuad`), the engine's grid.\n */\n\nimport type { FeatureCollection, Properties } from '../layers/features.ts';\nimport type { RasterOptions } from '../types.ts';\nimport { fetchOk } from '../util/fetch.ts';\nimport { withHeaders } from '../util/requests.ts';\n\n/** What `ogcFeatures` asks for */\nexport interface OgcFeaturesOptions {\n /** The box the features meet: west, south, east, north (degrees) */\n bbox?: [west: number, south: number, east: number, north: number];\n /** A CQL2 filter (Part 3), as text by default: `\"hauteur > 30\"`, `\"S_INTERSECTS(geometry, POINT(2.33 48.87))\"` */\n filter?: string;\n /** The filter's language (default `'cql2-text'`) */\n filterLang?: 'cql2-text' | 'cql2-json';\n /** The CRS of the features' coordinates (Part 2), a URI (`'http://www.opengis.net/def/crs/EPSG/0/2154'`): the\n * collection names it in its `crs` member, the feature layers reproject it. Default the server's, CRS84 */\n crs?: string;\n /** The properties kept (default all of them) */\n properties?: string[];\n /** At most this many features (default 10 000) */\n count?: number;\n /** Features a page (default 1000), the next pages followed by their `next` link */\n pageSize?: number;\n signal?: AbortSignal;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;\n\n/** A link of an OGC API answer */\ninterface Link {\n href: string;\n rel?: string;\n type?: string;\n templated?: boolean;\n}\n\nconst isLink = (value: unknown): value is Link => isRecord(value) && typeof value.href === 'string';\n\n/** The links of an answer */\nconst linksOf = (value: unknown): Link[] =>\n isRecord(value) && Array.isArray(value.links) ? value.links.filter(isLink) : [];\n\n/** A page of features: a GeoJSON collection with its links */\ntype FeaturesPage<P> = FeatureCollection<P> & { links?: unknown[] };\n\nconst isFeaturesPage = <P>(value: unknown): value is FeaturesPage<P> =>\n isRecord(value) && Array.isArray(value.features);\n\n/** The JSON of a URL, the page's request headers on it */\nconst json = async (url: string | URL, signal: AbortSignal | undefined): Promise<unknown> =>\n (\n await fetchOk(url, withHeaders(url, { ...(signal ? { signal } : {}), headers: { Accept: 'application/json' } }))\n ).json();\n\n/** A link's URL, relative to the answer it came in */\nconst resolve = (href: string, base: string | URL): URL => new URL(href, base);\n\n/**\n * Features of a collection of an OGC API - Features service as GeoJSON: `await ogcFeatures(url, 'buildings', { bbox,\n * filter: 'height > 30' })`, `url` the service's landing page. The pages followed by their `next` links until `count`\n * features or the last page. With `crs`, the coordinates come in it, the collection naming it (`crs` member)\n */\nexport const ogcFeatures = async <P = Properties>(\n url: string | URL,\n collection: string,\n options: OgcFeaturesOptions = {},\n): Promise<FeatureCollection<P>> => {\n const { bbox, filter, filterLang = 'cql2-text', crs, properties, count = 10_000, pageSize = 1000, signal } = options;\n const items = new URL(`collections/${encodeURIComponent(collection)}/items`, `${String(url).replace(/\\/?$/, '/')}`);\n\n // Spaces as %20, not + (URLSearchParams): a server re-encodes a + in its next link (%2B), which breaks the filter\n // past one page\n items.search = Object.entries({\n f: 'json',\n limit: String(Math.max(1, Math.min(pageSize, count))),\n ...(bbox ? { bbox: bbox.join(',') } : {}),\n ...(filter ? { filter, 'filter-lang': filterLang } : {}),\n ...(crs ? { crs } : {}),\n ...(properties ? { properties: properties.join(',') } : {}),\n })\n .map(([key, value]) => `${key}=${encodeURIComponent(value)}`)\n .join('&');\n\n const features: FeatureCollection<P>['features'] = [];\n let next: URL | undefined = items;\n\n while (next && features.length < count) {\n const page: unknown = await json(next, signal);\n\n if (!isFeaturesPage<P>(page)) throw new Error(`isard: ${String(next)}: not a GeoJSON feature collection`);\n features.push(...page.features);\n\n const link = linksOf(page).find((l) => l.rel === 'next');\n // An empty page ends it whatever its links say (a server that always links further)\n next = link && page.features.length > 0 ? resolve(link.href, next) : undefined;\n }\n\n return {\n type: 'FeatureCollection',\n features: features.slice(0, count),\n ...(crs ? { crs: { type: 'name', properties: { name: crs } } } : {}),\n };\n};\n\n/** A tileset of OGC API - Tiles as isard reads it: its tiles' URL template (`{z}`, `{x}`, `{y}`), its levels, whether\n * its tiles are images (`'map'`) or vector tiles (`'vector'`), its credits */\nexport interface OgcTileset {\n url: string;\n minZoom: number;\n maxZoom: number;\n dataType: 'map' | 'vector';\n attribution?: string;\n}\n\n/** The level numbers of a tileset's limits, if it has some */\nconst levelsOf = (tileset: Record<string, unknown>): number[] =>\n (Array.isArray(tileset.tileMatrixSetLimits) ? tileset.tileMatrixSetLimits : [])\n .map((limit) => (isRecord(limit) ? Number(limit.tileMatrix) : Number.NaN))\n .filter(Number.isInteger);\n\n/** Whether a tileset's grid is Web Mercator's */\nconst isWebMercator = (tileset: Record<string, unknown>): boolean =>\n [tileset.tileMatrixSetURI, tileset.tileMatrixSetId, tileset.tileMatrixSet].some(\n (id) => typeof id === 'string' && /WebMercatorQuad$/i.test(id),\n );\n\n/**\n * A tileset of OGC API - Tiles read from its metadata (`…/tiles/WebMercatorQuad`, or the list of a collection's\n * tilesets `…/tiles`, its Web Mercator one taken): its tiles' URL template, its levels, its kind. In Web Mercator only\n * (`WebMercatorQuad`, the engine's grid)\n */\nexport const ogcTiles = async (url: string | URL, { signal }: { signal?: AbortSignal } = {}): Promise<OgcTileset> => {\n const answer: unknown = await json(url, signal);\n\n if (!isRecord(answer)) throw new Error(`isard: ${String(url)}: not a tileset`);\n // A list of tilesets: its Web Mercator one\n if (Array.isArray(answer.tilesets)) {\n const listed = answer.tilesets.filter(isRecord).find(isWebMercator);\n // Its own link (`self`), else the first that is not its tiling scheme's\n const links = listed ? linksOf(listed) : [];\n const link = links.find((l) => l.rel === 'self') ?? links.find((l) => !l.rel?.endsWith('tiling-scheme'));\n\n if (!link) throw new Error(`isard: ${String(url)}: no tileset in Web Mercator (WebMercatorQuad)`);\n\n return ogcTiles(resolve(link.href, url), signal ? { signal } : {});\n }\n if (!isWebMercator(answer))\n throw new Error(`isard: ${String(url)}: a tileset in Web Mercator (WebMercatorQuad) only`);\n\n const tiles = linksOf(answer).filter((l) => l.rel === 'item' && l.href.includes('{tileMatrix}'));\n const vector = tiles.find((l) => /mapbox-vector-tile|mvt|pbf/i.test(l.type ?? ''));\n const image = tiles.find((l) => /^image\\//.test(l.type ?? ''));\n const dataType = answer.dataType === 'vector' || (vector && !image) ? 'vector' : 'map';\n const link = (dataType === 'vector' ? vector : image) ?? tiles[0];\n\n if (!link) throw new Error(`isard: ${String(url)}: no URL template of its tiles`);\n\n const template = resolve(link.href.replace(/\\{(tileMatrix|tileRow|tileCol)\\}/g, '_$1_'), url)\n .toString()\n .replace('_tileMatrix_', '{z}')\n .replace('_tileRow_', '{y}')\n .replace('_tileCol_', '{x}');\n const levels = levelsOf(answer);\n\n return {\n url: template,\n minZoom: levels.length > 0 ? Math.min(...levels) : 0,\n maxZoom: levels.length > 0 ? Math.max(...levels) : 22,\n dataType,\n ...(typeof answer.attribution === 'string' ? { attribution: answer.attribution } : {}),\n };\n};\n\n/** A raster layer's options from an OGC API - Tiles map tileset (`ogcTiles`): `map.addRaster(await ogcMapTiles(url))` */\nexport const ogcMapTiles = async (\n url: string | URL,\n options: Omit<RasterOptions, 'url'> & { signal?: AbortSignal } = {},\n): Promise<RasterOptions> => {\n const { signal, ...raster } = options;\n const tileset = await ogcTiles(url, signal ? { signal } : {});\n\n if (tileset.dataType !== 'map') throw new Error(`isard: ${String(url)}: vector tiles, a style's source`);\n\n return {\n url: tileset.url,\n minZoom: tileset.minZoom,\n maxZoom: tileset.maxZoom,\n ...(tileset.attribution ? { attribution: tileset.attribution } : {}),\n ...raster,\n };\n};\n\n/** A vector style's source from an OGC API - Tiles vector tileset (`ogcTiles`): `{ type: 'vector', tiles, minzoom,\n * maxzoom }`, in a MapLibre style's `sources` given to `map.vectorTiles({ style })` */\nexport const ogcVectorSource = async (\n url: string | URL,\n { signal }: { signal?: AbortSignal } = {},\n): Promise<{ type: 'vector'; tiles: string[]; minzoom: number; maxzoom: number; attribution?: string }> => {\n const tileset = await ogcTiles(url, signal ? { signal } : {});\n\n if (tileset.dataType !== 'vector') throw new Error(`isard: ${String(url)}: images, a raster layer's tiles`);\n\n return {\n type: 'vector',\n tiles: [tileset.url],\n minzoom: tileset.minZoom,\n maxzoom: tileset.maxZoom,\n ...(tileset.attribution ? { attribution: tileset.attribution } : {}),\n };\n};\n"]}
package/dist/index.d.ts CHANGED
@@ -33,6 +33,7 @@ export { type Crs, type CrsLike, getCrs, lambertConformalConic, registerCrs, rep
33
33
  export { parseGpx } from './data/gpx.ts';
34
34
  export { type IfcElement, type IfcModel, type IfcOptions, type IfcPlace, type IfcProperties, type IfcStorey, loadIfc, WEB_IFC, } from './data/ifc.ts';
35
35
  export { parseKml } from './data/kml.ts';
36
+ export { type OgcFeaturesOptions, type OgcTileset, ogcFeatures, ogcMapTiles, ogcTiles, ogcVectorSource, } from './data/ogcapi.ts';
36
37
  export { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';
37
38
  export type { DecoderUrls } from './decoding/decoders.ts';
38
39
  export { BATIMENTS_3D_URL, type BdTopoBuilding, batiments3d, bdtopoBuildings, bdtopoRoofs, type GeocodedPlace, geoplateformeGeocode, geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION, IGN_PRESETS, type IgnPreset, lambert93Grid, } from './geoplateforme.ts';
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ export { getCrs, lambertConformalConic, registerCrs, reproject, transverseMercat
23
23
  export { parseGpx } from "./data/gpx.js";
24
24
  export { loadIfc, WEB_IFC, } from "./data/ifc.js";
25
25
  export { parseKml } from "./data/kml.js";
26
+ export { ogcFeatures, ogcMapTiles, ogcTiles, ogcVectorSource, } from "./data/ogcapi.js";
26
27
  export { parseTopoJson } from "./data/topojson.js";
27
28
  export { BATIMENTS_3D_URL, batiments3d, bdtopoBuildings, bdtopoRoofs, geoplateformeGeocode, geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION, IGN_PRESETS, lambert93Grid, } from "./geoplateforme.js";
28
29
  export { windAt, windFields } from "./grids.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * isard: a WebGL2 map engine for large, interactive data layers, labels and 3D Tiles.\n *\n * ```ts\n * import { GeoMap } from 'isard';\n * const map = await GeoMap.create(container, { center: [2.4246, 48.8457], zoom: 13 });\n * const network = map.addNetwork({ nodes, edges, max: 1800, contour: 300 });\n * map.on('hover', ({ lonLat }) => lonLat && network.setValues(travelTimes(lonLat)));\n * map.addTiles3d({ url: 'https://…/tileset.json' });\n * map.addControl(new NavigationControl());\n * new Marker().setLonLat([2.4246, 48.8457]).setPopup(new Popup({ offset: [0, -34] }).setText('Here')).addTo(map);\n * ```\n */\nexport { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemap/basemaps.ts';\nexport type { TileGrid, TileMatrix } from './basemap/grid.ts';\nexport { coniferModel, type TreeColors, treeModel } from './basemap/models/trees.ts';\nexport {\n PMTiles,\n type PmtilesEntry,\n type PmtilesHeader,\n type PmtilesTileType,\n tileIdToZxy,\n zxyToTileId,\n} from './basemap/pmtiles.ts';\nexport { basicStyle, type PmtilesOptions } from './basemap/pmtileslayer.ts';\nexport type {\n CandidateIcon,\n CandidateOverlap,\n Json,\n LabelCandidate,\n RasterSource,\n Style,\n StyleLayer,\n} from './basemap/vectorstyle.ts';\nexport type { VectorExtrusionOptions } from './basemap/vectortiles/extrusions.ts';\nexport type { FurnitureOptions } from './basemap/vectortiles/furniture.ts';\nexport type { LabelsOptions } from './basemap/vectortiles/labels.ts';\nexport type { LampsOptions } from './basemap/vectortiles/lamps.ts';\nexport type { StreetWindLayer, StreetWindOptions } from './basemap/vectortiles/street-wind.ts';\nexport type { LoadedStyle } from './basemap/vectortiles/style.ts';\nexport type { TreesOptions } from './basemap/vectortiles/trees.ts';\nexport { isStreet, type VectorsOptions } from './basemap/vectortiles/vectors.ts';\nexport type { VectorRasterOptions, VectorTilesOptions } from './basemap/vectortiles.ts';\nexport { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './basemap/vectortiles.ts';\nexport { parseWmtsGrid, wmtsGrid } from './basemap/wmts.ts';\nexport { type ColladaImages, colladaImages, loadCollada, parseCollada } from './data/collada.ts';\nexport {\n type Crs,\n type CrsLike,\n getCrs,\n lambertConformalConic,\n registerCrs,\n reproject,\n transverseMercator,\n} from './data/crs.ts';\nexport { parseGpx } from './data/gpx.ts';\nexport {\n type IfcElement,\n type IfcModel,\n type IfcOptions,\n type IfcPlace,\n type IfcProperties,\n type IfcStorey,\n loadIfc,\n WEB_IFC,\n} from './data/ifc.ts';\nexport { parseKml } from './data/kml.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';\nexport type { DecoderUrls } from './decoding/decoders.ts';\nexport {\n BATIMENTS_3D_URL,\n type BdTopoBuilding,\n batiments3d,\n bdtopoBuildings,\n bdtopoRoofs,\n type GeocodedPlace,\n geoplateformeGeocode,\n geoplateformeWfs,\n geoplateformeWms,\n geoplateformeWmts,\n IGN_ATTRIBUTION,\n IGN_PRESETS,\n type IgnPreset,\n lambert93Grid,\n} from './geoplateforme.ts';\nexport { type Grid, windAt, windFields } from './grids.ts';\nexport type { CustomFrame, CustomLayerInterface } from './layers/custom.ts';\nexport { CustomLayer } from './layers/custom.ts';\nexport type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './layers/extrusions.ts';\nexport { ExtrusionLayer } from './layers/extrusions.ts';\nexport type {\n CircleOptions,\n CircleStyle,\n Feature,\n FeatureCollection,\n FeatureData,\n FeatureLayerStyle,\n FillOptions,\n FillStyle,\n Geometry,\n LineOptions,\n LineStyle,\n Position,\n Properties,\n Ramp,\n Size,\n Stops,\n Styled,\n} from './layers/features.ts';\nexport { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './layers/features.ts';\nexport type { FlowField, FlowOptions, FlowStyle, TimedField } from './layers/flow.ts';\nexport { FlowLayer, flowFieldFromImage, flowFieldsFromImage } from './layers/flow.ts';\nexport type { TextPart } from './layers/glyphs.ts';\nexport { DEFAULT_FONT, GLYPHS_URL } from './layers/glyphs.ts';\nexport type { GroundOptions, GroundTexture, GroundUniform } from './layers/ground.ts';\nexport { GroundLayer } from './layers/ground.ts';\nexport type { ImageOptions, Pixels, SpriteIcon } from './layers/icons.ts';\nexport { Layer } from './layers/layers.ts';\nexport type { ModelInstance, ModelOptions } from './layers/models.ts';\nexport { ModelLayer } from './layers/models.ts';\nexport { NetworkLayer } from './layers/network.ts';\nexport {\n type CalibratedPanoramaOptions,\n type Panorama,\n type PanoramaOptions,\n type PanoramaPhoto,\n Panoramas,\n type PhotoPanoramaOptions,\n} from './layers/panoramas.ts';\nexport { type PhotoOptions, photoModel } from './layers/photos.ts';\nexport type { ClassStyle, PointCloudOptions, PointCloudStyle, PointColor } from './layers/pointclouds.ts';\nexport { CLASSIFICATIONS, ELEVATION_RAMP, PointCloudLayer } from './layers/pointclouds.ts';\nexport { RasterLayer } from './layers/raster.ts';\nexport type { Overlap, SymbolOptions, SymbolStyle } from './layers/symbols.ts';\nexport { SymbolLayer } from './layers/symbols.ts';\nexport { Tiles3dLayer } from './layers/tiles3d.ts';\nexport { type TreeKind, type TreeOptions, treeKind } from './layers/trees.ts';\nexport { type VectorFeature, VectorLayer, type VectorSublayer } from './layers/vectors.ts';\nexport type { HoverPicking } from './map/hover-pick.ts';\nexport { GeoMap, type LayerSpec } from './map.ts';\nexport {\n PANORAMAX_API,\n type PanoramaxPicture,\n type PanoramaxSequenceOptions,\n panoramaxPanoramas,\n panoramaxPhoto,\n panoramaxPicture,\n panoramaxSequence,\n panoramaxStyle,\n} from './panoramax.ts';\nexport type {\n AnimationOptions,\n AtmosphereOptions,\n Basemap,\n BasemapName,\n BodyOptions,\n CelestialBody,\n ClipBox,\n ClipCylinder,\n ClipPolygon,\n ClipVolume,\n Drape,\n FeatureColor,\n FeatureHit,\n FirstPersonView,\n FitBoundsOptions,\n FitBox,\n FlyToOptions,\n GeoMapOptions,\n LoadingMode,\n LonLat,\n MapEvents,\n MapGpuTimings,\n MapHoverFeatureEvent,\n MapMemory,\n MapPointerEvent,\n NetworkOptions,\n NetworkStyle,\n PickOptions,\n Placement,\n Point,\n Projection,\n Quality,\n RasterGrid,\n RasterOptions,\n RasterStyle,\n SunOptions,\n SwipeOptions,\n TerrainEncoding,\n TerrainModel,\n TerrainOptions,\n Tiles3dOptions,\n Tiles3dStyle,\n ViewshedOptions,\n} from './types.ts';\nexport {\n AttributionControl,\n type AttributionOptions,\n type Control,\n type ControlPosition,\n NavigationControl,\n type NavigationOptions,\n} from './ui/controls.ts';\nexport { MinimapControl, type MinimapOptions } from './ui/minimap.ts';\nexport {\n type Anchor,\n Marker,\n type MarkerEvent,\n type MarkerEvents,\n type MarkerOptions,\n Panel,\n type PanelOptions,\n Popup,\n type PopupEvents,\n type PopupOptions,\n} from './ui/overlay.ts';\nexport { lengthLabel, roundLength, ScaleControl, type ScaleOptions } from './ui/scale.ts';\nexport { SearchControl, type SearchOptions } from './ui/search.ts';\nexport { setRequestHeaders } from './util/requests.ts';\nexport type { RoofMode } from './util/roofs.ts';\nexport { sunPosition } from './util/sun.ts';\nexport type {\n Camera,\n NetworkStats,\n PickHit,\n PickResult,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n RasterLayerStats,\n Tiles3dStats,\n} from './wasm/isard_webgpu.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * isard: a WebGL2 map engine for large, interactive data layers, labels and 3D Tiles.\n *\n * ```ts\n * import { GeoMap } from 'isard';\n * const map = await GeoMap.create(container, { center: [2.4246, 48.8457], zoom: 13 });\n * const network = map.addNetwork({ nodes, edges, max: 1800, contour: 300 });\n * map.on('hover', ({ lonLat }) => lonLat && network.setValues(travelTimes(lonLat)));\n * map.addTiles3d({ url: 'https://…/tileset.json' });\n * map.addControl(new NavigationControl());\n * new Marker().setLonLat([2.4246, 48.8457]).setPopup(new Popup({ offset: [0, -34] }).setText('Here')).addTo(map);\n * ```\n */\nexport { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemap/basemaps.ts';\nexport type { TileGrid, TileMatrix } from './basemap/grid.ts';\nexport { coniferModel, type TreeColors, treeModel } from './basemap/models/trees.ts';\nexport {\n PMTiles,\n type PmtilesEntry,\n type PmtilesHeader,\n type PmtilesTileType,\n tileIdToZxy,\n zxyToTileId,\n} from './basemap/pmtiles.ts';\nexport { basicStyle, type PmtilesOptions } from './basemap/pmtileslayer.ts';\nexport type {\n CandidateIcon,\n CandidateOverlap,\n Json,\n LabelCandidate,\n RasterSource,\n Style,\n StyleLayer,\n} from './basemap/vectorstyle.ts';\nexport type { VectorExtrusionOptions } from './basemap/vectortiles/extrusions.ts';\nexport type { FurnitureOptions } from './basemap/vectortiles/furniture.ts';\nexport type { LabelsOptions } from './basemap/vectortiles/labels.ts';\nexport type { LampsOptions } from './basemap/vectortiles/lamps.ts';\nexport type { StreetWindLayer, StreetWindOptions } from './basemap/vectortiles/street-wind.ts';\nexport type { LoadedStyle } from './basemap/vectortiles/style.ts';\nexport type { TreesOptions } from './basemap/vectortiles/trees.ts';\nexport { isStreet, type VectorsOptions } from './basemap/vectortiles/vectors.ts';\nexport type { VectorRasterOptions, VectorTilesOptions } from './basemap/vectortiles.ts';\nexport { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './basemap/vectortiles.ts';\nexport { parseWmtsGrid, wmtsGrid } from './basemap/wmts.ts';\nexport { type ColladaImages, colladaImages, loadCollada, parseCollada } from './data/collada.ts';\nexport {\n type Crs,\n type CrsLike,\n getCrs,\n lambertConformalConic,\n registerCrs,\n reproject,\n transverseMercator,\n} from './data/crs.ts';\nexport { parseGpx } from './data/gpx.ts';\nexport {\n type IfcElement,\n type IfcModel,\n type IfcOptions,\n type IfcPlace,\n type IfcProperties,\n type IfcStorey,\n loadIfc,\n WEB_IFC,\n} from './data/ifc.ts';\nexport { parseKml } from './data/kml.ts';\nexport {\n type OgcFeaturesOptions,\n type OgcTileset,\n ogcFeatures,\n ogcMapTiles,\n ogcTiles,\n ogcVectorSource,\n} from './data/ogcapi.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';\nexport type { DecoderUrls } from './decoding/decoders.ts';\nexport {\n BATIMENTS_3D_URL,\n type BdTopoBuilding,\n batiments3d,\n bdtopoBuildings,\n bdtopoRoofs,\n type GeocodedPlace,\n geoplateformeGeocode,\n geoplateformeWfs,\n geoplateformeWms,\n geoplateformeWmts,\n IGN_ATTRIBUTION,\n IGN_PRESETS,\n type IgnPreset,\n lambert93Grid,\n} from './geoplateforme.ts';\nexport { type Grid, windAt, windFields } from './grids.ts';\nexport type { CustomFrame, CustomLayerInterface } from './layers/custom.ts';\nexport { CustomLayer } from './layers/custom.ts';\nexport type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './layers/extrusions.ts';\nexport { ExtrusionLayer } from './layers/extrusions.ts';\nexport type {\n CircleOptions,\n CircleStyle,\n Feature,\n FeatureCollection,\n FeatureData,\n FeatureLayerStyle,\n FillOptions,\n FillStyle,\n Geometry,\n LineOptions,\n LineStyle,\n Position,\n Properties,\n Ramp,\n Size,\n Stops,\n Styled,\n} from './layers/features.ts';\nexport { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './layers/features.ts';\nexport type { FlowField, FlowOptions, FlowStyle, TimedField } from './layers/flow.ts';\nexport { FlowLayer, flowFieldFromImage, flowFieldsFromImage } from './layers/flow.ts';\nexport type { TextPart } from './layers/glyphs.ts';\nexport { DEFAULT_FONT, GLYPHS_URL } from './layers/glyphs.ts';\nexport type { GroundOptions, GroundTexture, GroundUniform } from './layers/ground.ts';\nexport { GroundLayer } from './layers/ground.ts';\nexport type { ImageOptions, Pixels, SpriteIcon } from './layers/icons.ts';\nexport { Layer } from './layers/layers.ts';\nexport type { ModelInstance, ModelOptions } from './layers/models.ts';\nexport { ModelLayer } from './layers/models.ts';\nexport { NetworkLayer } from './layers/network.ts';\nexport {\n type CalibratedPanoramaOptions,\n type Panorama,\n type PanoramaOptions,\n type PanoramaPhoto,\n Panoramas,\n type PhotoPanoramaOptions,\n} from './layers/panoramas.ts';\nexport { type PhotoOptions, photoModel } from './layers/photos.ts';\nexport type { ClassStyle, PointCloudOptions, PointCloudStyle, PointColor } from './layers/pointclouds.ts';\nexport { CLASSIFICATIONS, ELEVATION_RAMP, PointCloudLayer } from './layers/pointclouds.ts';\nexport { RasterLayer } from './layers/raster.ts';\nexport type { Overlap, SymbolOptions, SymbolStyle } from './layers/symbols.ts';\nexport { SymbolLayer } from './layers/symbols.ts';\nexport { Tiles3dLayer } from './layers/tiles3d.ts';\nexport { type TreeKind, type TreeOptions, treeKind } from './layers/trees.ts';\nexport { type VectorFeature, VectorLayer, type VectorSublayer } from './layers/vectors.ts';\nexport type { HoverPicking } from './map/hover-pick.ts';\nexport { GeoMap, type LayerSpec } from './map.ts';\nexport {\n PANORAMAX_API,\n type PanoramaxPicture,\n type PanoramaxSequenceOptions,\n panoramaxPanoramas,\n panoramaxPhoto,\n panoramaxPicture,\n panoramaxSequence,\n panoramaxStyle,\n} from './panoramax.ts';\nexport type {\n AnimationOptions,\n AtmosphereOptions,\n Basemap,\n BasemapName,\n BodyOptions,\n CelestialBody,\n ClipBox,\n ClipCylinder,\n ClipPolygon,\n ClipVolume,\n Drape,\n FeatureColor,\n FeatureHit,\n FirstPersonView,\n FitBoundsOptions,\n FitBox,\n FlyToOptions,\n GeoMapOptions,\n LoadingMode,\n LonLat,\n MapEvents,\n MapGpuTimings,\n MapHoverFeatureEvent,\n MapMemory,\n MapPointerEvent,\n NetworkOptions,\n NetworkStyle,\n PickOptions,\n Placement,\n Point,\n Projection,\n Quality,\n RasterGrid,\n RasterOptions,\n RasterStyle,\n SunOptions,\n SwipeOptions,\n TerrainEncoding,\n TerrainModel,\n TerrainOptions,\n Tiles3dOptions,\n Tiles3dStyle,\n ViewshedOptions,\n} from './types.ts';\nexport {\n AttributionControl,\n type AttributionOptions,\n type Control,\n type ControlPosition,\n NavigationControl,\n type NavigationOptions,\n} from './ui/controls.ts';\nexport { MinimapControl, type MinimapOptions } from './ui/minimap.ts';\nexport {\n type Anchor,\n Marker,\n type MarkerEvent,\n type MarkerEvents,\n type MarkerOptions,\n Panel,\n type PanelOptions,\n Popup,\n type PopupEvents,\n type PopupOptions,\n} from './ui/overlay.ts';\nexport { lengthLabel, roundLength, ScaleControl, type ScaleOptions } from './ui/scale.ts';\nexport { SearchControl, type SearchOptions } from './ui/search.ts';\nexport { setRequestHeaders } from './util/requests.ts';\nexport type { RoofMode } from './util/roofs.ts';\nexport { sunPosition } from './util/sun.ts';\nexport type {\n Camera,\n NetworkStats,\n PickHit,\n PickResult,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n RasterLayerStats,\n Tiles3dStats,\n} from './wasm/isard_webgpu.js';\n"]}
Binary file
Binary file
Binary file
Binary file
@@ -31,7 +31,7 @@ export { Panel, type PanelProps } from './Panel.tsx';
31
31
  export { Popup, type PopupProps } from './Popup.tsx';
32
32
  export { FirstPerson, Panoramas, type PanoramasProps, Photo, type PhotoProps } from './Street.tsx';
33
33
  export { Swipe, SwipeOther, type SwipeProps } from './Swipe.tsx';
34
- export { collada, geojson, gpx, type Source, source, useLoaded, useLoadedEvent, useSource, wfs, windGrids, } from './sources.ts';
34
+ export { collada, geojson, gpx, ogcFeatures, type Source, source, useLoaded, useLoadedEvent, useSource, wfs, windGrids, } from './sources.ts';
35
35
  export { Geometry, type GeometryProps, VectorGeometry, type VectorGeometryProps } from './VectorGeometry.tsx';
36
36
  export { Extrusions, Furniture, Labels, Lamps, Raster, StreetWind, Trees, useVectorTiles, VectorTiles, type VectorTilesProps, } from './VectorTiles.tsx';
37
37
  export { Viewshed } from './Viewshed.tsx';
@@ -26,7 +26,7 @@ export { Panel } from "./Panel.js";
26
26
  export { Popup } from "./Popup.js";
27
27
  export { FirstPerson, Panoramas, Photo } from "./Street.js";
28
28
  export { Swipe, SwipeOther } from "./Swipe.js";
29
- export { collada, geojson, gpx, source, useLoaded, useLoadedEvent, useSource, wfs, windGrids, } from "./sources.js";
29
+ export { collada, geojson, gpx, ogcFeatures, source, useLoaded, useLoadedEvent, useSource, wfs, windGrids, } from "./sources.js";
30
30
  export { Geometry, VectorGeometry } from "./VectorGeometry.js";
31
31
  export { Extrusions, Furniture, Labels, Lamps, Raster, StreetWind, Trees, useVectorTiles, VectorTiles, } from "./VectorTiles.js";
32
32
  export { Viewshed } from "./Viewshed.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAkB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAqB,MAAM,cAAe,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAmB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,GAAG,EAAiB,QAAQ,EAAE,MAAM,UAAW,CAAC;AACzD,OAAO,EAAE,QAAQ,EAA0C,MAAM,eAAgB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAsD,MAAM,YAAa,CAAC;AACxF,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAc,CAAC;AACxD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAuB,KAAK,EAAmB,MAAM,aAAc,CAAC;AACnG,OAAO,EAAE,KAAK,EAAE,UAAU,EAAmB,MAAM,YAAa,CAAC;AACjE,OAAO,EACL,OAAO,EACP,OAAO,EACP,GAAG,EAEH,MAAM,EACN,SAAS,EACT,cAAc,EACd,SAAS,EACT,GAAG,EACH,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAsB,cAAc,EAA4B,MAAM,qBAAsB,CAAC;AAC9G,OAAO,EACL,UAAU,EACV,SAAS,EACT,MAAM,EACN,KAAK,EACL,MAAM,EACN,UAAU,EACV,KAAK,EACL,cAAc,EACd,WAAW,GAEZ,MAAM,kBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAgB,CAAC","sourcesContent":["/**\n * Isard in React: the map, its layers, markers, popups, panels and effects as components, created when they mount,\n * updated by the least their props need and removed when they unmount.\n *\n * ```tsx\n * <IsardMap preset=\"ign-3d\" center={[2.35, 48.85]} zoom={15} style={{ height: 400 }}>\n * <VectorTiles style={OPENFREEMAP_STYLES.liberty}>\n * <Geometry roofs=\"generated\" />\n * <Trees />\n * <Labels />\n * </VectorTiles>\n * <Layer type=\"lines\" data={routes} color=\"#0057b8\" width={3} />\n * <Marker lonLat={[2.35, 48.85]}><Popup>Here</Popup></Marker>\n * </IsardMap>\n * ```\n */\n\nexport type { Layer as LayerHandle } from '../layers/layers.ts';\nexport type { GeoMap, LayerSpec } from '../map.ts';\nexport type { LonLat } from '../types.ts';\nexport type { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle } from '../ui/overlay.ts';\nexport type { Camera } from '../wasm/isard_webgpu.js';\nexport { ClipVolume, type ClipVolumeProps } from './ClipVolume.tsx';\nexport { Control, type ControlProps } from './Control.tsx';\nexport { CustomLayer, type CustomLayerProps } from './CustomLayer.tsx';\nexport { useMap, useMapEvent, useMapRedraw } from './context.ts';\nexport { Ifc, type IfcProps, useFrame } from './Ifc.tsx';\nexport { IsardMap, type IsardMapProps, type MapEventProps } from './IsardMap.tsx';\nexport { Layer, type LayerHandles, type LayerProps, type LayerType } from './Layer.tsx';\nexport { Marker, type MarkerProps } from './Marker.tsx';\nexport { Panel, type PanelProps } from './Panel.tsx';\nexport { Popup, type PopupProps } from './Popup.tsx';\nexport { FirstPerson, Panoramas, type PanoramasProps, Photo, type PhotoProps } from './Street.tsx';\nexport { Swipe, SwipeOther, type SwipeProps } from './Swipe.tsx';\nexport {\n collada,\n geojson,\n gpx,\n type Source,\n source,\n useLoaded,\n useLoadedEvent,\n useSource,\n wfs,\n windGrids,\n} from './sources.ts';\nexport { Geometry, type GeometryProps, VectorGeometry, type VectorGeometryProps } from './VectorGeometry.tsx';\nexport {\n Extrusions,\n Furniture,\n Labels,\n Lamps,\n Raster,\n StreetWind,\n Trees,\n useVectorTiles,\n VectorTiles,\n type VectorTilesProps,\n} from './VectorTiles.tsx';\nexport { Viewshed } from './Viewshed.tsx';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAkB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAqB,MAAM,cAAe,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAmB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,GAAG,EAAiB,QAAQ,EAAE,MAAM,UAAW,CAAC;AACzD,OAAO,EAAE,QAAQ,EAA0C,MAAM,eAAgB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAsD,MAAM,YAAa,CAAC;AACxF,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAc,CAAC;AACxD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,KAAK,EAAmB,MAAM,YAAa,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAuB,KAAK,EAAmB,MAAM,aAAc,CAAC;AACnG,OAAO,EAAE,KAAK,EAAE,UAAU,EAAmB,MAAM,YAAa,CAAC;AACjE,OAAO,EACL,OAAO,EACP,OAAO,EACP,GAAG,EACH,WAAW,EAEX,MAAM,EACN,SAAS,EACT,cAAc,EACd,SAAS,EACT,GAAG,EACH,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAsB,cAAc,EAA4B,MAAM,qBAAsB,CAAC;AAC9G,OAAO,EACL,UAAU,EACV,SAAS,EACT,MAAM,EACN,KAAK,EACL,MAAM,EACN,UAAU,EACV,KAAK,EACL,cAAc,EACd,WAAW,GAEZ,MAAM,kBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAgB,CAAC","sourcesContent":["/**\n * Isard in React: the map, its layers, markers, popups, panels and effects as components, created when they mount,\n * updated by the least their props need and removed when they unmount.\n *\n * ```tsx\n * <IsardMap preset=\"ign-3d\" center={[2.35, 48.85]} zoom={15} style={{ height: 400 }}>\n * <VectorTiles style={OPENFREEMAP_STYLES.liberty}>\n * <Geometry roofs=\"generated\" />\n * <Trees />\n * <Labels />\n * </VectorTiles>\n * <Layer type=\"lines\" data={routes} color=\"#0057b8\" width={3} />\n * <Marker lonLat={[2.35, 48.85]}><Popup>Here</Popup></Marker>\n * </IsardMap>\n * ```\n */\n\nexport type { Layer as LayerHandle } from '../layers/layers.ts';\nexport type { GeoMap, LayerSpec } from '../map.ts';\nexport type { LonLat } from '../types.ts';\nexport type { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle } from '../ui/overlay.ts';\nexport type { Camera } from '../wasm/isard_webgpu.js';\nexport { ClipVolume, type ClipVolumeProps } from './ClipVolume.tsx';\nexport { Control, type ControlProps } from './Control.tsx';\nexport { CustomLayer, type CustomLayerProps } from './CustomLayer.tsx';\nexport { useMap, useMapEvent, useMapRedraw } from './context.ts';\nexport { Ifc, type IfcProps, useFrame } from './Ifc.tsx';\nexport { IsardMap, type IsardMapProps, type MapEventProps } from './IsardMap.tsx';\nexport { Layer, type LayerHandles, type LayerProps, type LayerType } from './Layer.tsx';\nexport { Marker, type MarkerProps } from './Marker.tsx';\nexport { Panel, type PanelProps } from './Panel.tsx';\nexport { Popup, type PopupProps } from './Popup.tsx';\nexport { FirstPerson, Panoramas, type PanoramasProps, Photo, type PhotoProps } from './Street.tsx';\nexport { Swipe, SwipeOther, type SwipeProps } from './Swipe.tsx';\nexport {\n collada,\n geojson,\n gpx,\n ogcFeatures,\n type Source,\n source,\n useLoaded,\n useLoadedEvent,\n useSource,\n wfs,\n windGrids,\n} from './sources.ts';\nexport { Geometry, type GeometryProps, VectorGeometry, type VectorGeometryProps } from './VectorGeometry.tsx';\nexport {\n Extrusions,\n Furniture,\n Labels,\n Lamps,\n Raster,\n StreetWind,\n Trees,\n useVectorTiles,\n VectorTiles,\n type VectorTilesProps,\n} from './VectorTiles.tsx';\nexport { Viewshed } from './Viewshed.tsx';\n"]}
@@ -5,6 +5,7 @@
5
5
  * the source changes (its key), given up when the component goes; React's strict mode, mounting twice, loads once what
6
6
  * it keeps. A source is plain data compared by its key: written inline at each render, it loads nothing again.
7
7
  */
8
+ import type { OgcFeaturesOptions } from '../data/ogcapi.ts';
8
9
  import type * as Grids from '../grids.ts';
9
10
  import type { FeatureCollection, Properties } from '../layers/features.ts';
10
11
  import type { TimedField } from '../layers/flow.ts';
@@ -27,6 +28,8 @@ export declare const wfs: <P = Properties>(typeName: string, box: [west: number,
27
28
  count?: number;
28
29
  srsName?: string;
29
30
  }) => Source<FeatureCollection<P>>;
31
+ /** The features of a collection of an OGC API - Features service (`ogcFeatures`): by box, by a CQL2 filter */
32
+ export declare const ogcFeatures: <P = Properties>(url: string, collection: string, options?: Omit<OgcFeaturesOptions, "signal">) => Source<FeatureCollection<P>>;
30
33
  /** A COLLADA model read into a glTF binary (`loadCollada`): a models layer's `data` */
31
34
  export declare const collada: (url: string) => Source<Uint8Array<ArrayBuffer>>;
32
35
  /** The wind of a GRIB2 or NetCDF file (`map.readGrids`, `windFields`): a flow layer's `fields`, read by the map's
@@ -31,6 +31,11 @@ export const wfs = (typeName, box, options = {}) => source(`wfs:${JSON.stringify
31
31
  const { geoplateformeWfs } = await import("../geoplateforme.js");
32
32
  return geoplateformeWfs(typeName, box, { ...options, signal });
33
33
  });
34
+ /** The features of a collection of an OGC API - Features service (`ogcFeatures`): by box, by a CQL2 filter */
35
+ export const ogcFeatures = (url, collection, options = {}) => source(`ogcFeatures:${JSON.stringify([url, collection, options])}`, async (signal) => {
36
+ const { ogcFeatures: load } = await import("../data/ogcapi.js");
37
+ return load(url, collection, { ...options, signal });
38
+ });
34
39
  /** A COLLADA model read into a glTF binary (`loadCollada`): a models layer's `data` */
35
40
  export const collada = (url) => source(`collada:${url}`, async (signal) => {
36
41
  const { loadCollada } = await import("../data/collada.js");
@@ -1 +1 @@
1
- {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../src/react/sources.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a component loads, declared rather than written as an effect: `useSource(wfs(typeName, box))` gives the\n * Géoplateforme's features once fetched (undefined before), to give to a `<Layer>`'s `data`; `geojson(url)`,\n * `gpx(url)`, `collada(url)`, `windGrids(url)` the same, `useLoaded(key, load)` anything else. Loaded again only when\n * the source changes (its key), given up when the component goes; React's strict mode, mounting twice, loads once what\n * it keeps. A source is plain data compared by its key: written inline at each render, it loads nothing again.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type * as Grids from '../grids.ts';\nimport type { FeatureCollection, Properties } from '../layers/features.ts';\nimport type { TimedField } from '../layers/flow.ts';\nimport type { GeoMap } from '../map.ts';\nimport { useMap } from './context.ts';\n\n/** Something a component loads: `$source` tells two sources apart (the same key, the same thing loaded), `load` loads\n * it, given up when `signal` aborts; `map` the map it needs (loaded inside an `<IsardMap>` then, once the map is there) */\nexport interface Source<T> {\n readonly $source: string;\n readonly map?: true;\n load(signal: AbortSignal, map: GeoMap | undefined): Promise<T>;\n}\n\n/** A source of its own: `key` the same for the same thing loaded (its URL and options, say) */\nexport const source = <T>(key: string, load: (signal: AbortSignal) => Promise<T>): Source<T> => ({\n $source: key,\n load,\n});\n\n/** A GeoJSON file */\nexport const geojson = <P = Properties>(url: string): Source<FeatureCollection<P>> =>\n source(`geojson:${url}`, async (signal) => {\n const response = await fetch(url, { signal });\n\n if (!response.ok) throw new Error(`${url}: ${response.status}`);\n\n return response.json();\n });\n\n/** A GPX file's tracks, routes and waypoints (`parseGpx`) */\nexport const gpx = <P = Properties>(url: string): Source<FeatureCollection<P>> =>\n source(`gpx:${url}`, async (signal) => {\n const [{ parseGpx }, response] = await Promise.all([import('../data/gpx.ts'), fetch(url, { signal })]);\n\n if (!response.ok) throw new Error(`${url}: ${response.status}`);\n\n return parseGpx<P>(await response.text());\n });\n\n/** The Géoplateforme's features of a type in a box (`geoplateformeWfs`) */\nexport const wfs = <P = Properties>(\n typeName: string,\n box: [west: number, south: number, east: number, north: number],\n options: { count?: number; srsName?: string } = {},\n): Source<FeatureCollection<P>> =>\n source(`wfs:${JSON.stringify([typeName, box, options])}`, async (signal) => {\n const { geoplateformeWfs } = await import('../geoplateforme.ts');\n\n return geoplateformeWfs<P>(typeName, box, { ...options, signal });\n });\n\n/** A COLLADA model read into a glTF binary (`loadCollada`): a models layer's `data` */\nexport const collada = (url: string): Source<Uint8Array<ArrayBuffer>> =>\n source(`collada:${url}`, async (signal) => {\n const { loadCollada } = await import('../data/collada.ts');\n\n return loadCollada(url, { signal });\n });\n\n/** The wind of a GRIB2 or NetCDF file (`map.readGrids`, `windFields`): a flow layer's `fields`, read by the map's\n * workers (inside an `<IsardMap>`) */\nexport const windGrids = (url: string, options: Parameters<typeof Grids.windFields>[1] = {}): Source<TimedField[]> => ({\n $source: `wind:${url}:${JSON.stringify(options)}`,\n map: true,\n load: async (_, map) => {\n if (!map) throw new Error('windGrids: no map');\n\n const { windFields } = await import('../grids.ts');\n\n return windFields(await map.readGrids(url), options);\n },\n});\n\n/**\n * What `load` gives, once loaded (undefined before, or when it failed: `onError`). Loaded again when `key` changes (a\n * string, or an object compared by identity: `useStableOptions`'), given up when the component goes (its signal\n * aborted), what it gave let go then by `dispose`; nothing loaded while `key` is undefined\n */\nexport const useLoaded = <T>(\n key: unknown,\n load: (signal: AbortSignal) => Promise<T>,\n { onError = console.error, dispose }: { onError?: (error: unknown) => void; dispose?: (value: T) => void } = {},\n): T | undefined => {\n const [loaded, setLoaded] = useState<{ key: unknown; value: T }>();\n // Read when the key changes only: inline functions at each render load nothing again\n const latest = useRef({ load, onError, dispose });\n\n latest.current = { load, onError, dispose };\n // Loading while mounted and the key the same; a strict mode's first mount aborted, what it gave let go\n useEffect(() => {\n if (key === undefined) return;\n\n const controller = new AbortController();\n const kept: { value?: T } = {};\n const { load, onError, dispose } = latest.current;\n\n load(controller.signal).then(\n (value) => {\n if (controller.signal.aborted) {\n dispose?.(value);\n\n return;\n }\n kept.value = value;\n setLoaded({ key, value });\n },\n (error: unknown) => {\n if (!controller.signal.aborted) onError(error);\n },\n );\n\n return () => {\n controller.abort();\n if (kept.value !== undefined) dispose?.(kept.value);\n };\n }, [key]);\n\n return loaded && loaded.key === key ? loaded.value : undefined;\n};\n\n/** What a source loads, once loaded (undefined before; none without a source). A source needing the map takes the one\n * around, or `map` (outside an `<IsardMap>`: the one its `onLoad` gave); a failure given to `onError` */\nexport const useSource = <T>(\n source: Source<T> | undefined,\n options: { map?: GeoMap | undefined; onError?: (error: unknown) => void } = {},\n): T | undefined => {\n const around = useMap();\n const map = options.map ?? around;\n\n // A source needing the map waits for it\n return useLoaded(\n source && (!source.map || map) ? source.$source : undefined,\n (signal) => source?.load(signal, map) ?? Promise.reject(new Error('no source')),\n options.onError ? { onError: options.onError } : {},\n );\n};\n\n/** Calls `listener` once with each value loaded (the listener may change at each render) */\nexport const useLoadedEvent = <T>(value: T | undefined, listener: ((value: T) => void) | undefined): void => {\n const latest = useRef(listener);\n\n latest.current = listener;\n useEffect(() => {\n if (value !== undefined) latest.current?.(value);\n }, [value]);\n};\n"]}
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../src/react/sources.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a component loads, declared rather than written as an effect: `useSource(wfs(typeName, box))` gives the\n * Géoplateforme's features once fetched (undefined before), to give to a `<Layer>`'s `data`; `geojson(url)`,\n * `gpx(url)`, `collada(url)`, `windGrids(url)` the same, `useLoaded(key, load)` anything else. Loaded again only when\n * the source changes (its key), given up when the component goes; React's strict mode, mounting twice, loads once what\n * it keeps. A source is plain data compared by its key: written inline at each render, it loads nothing again.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { OgcFeaturesOptions } from '../data/ogcapi.ts';\nimport type * as Grids from '../grids.ts';\nimport type { FeatureCollection, Properties } from '../layers/features.ts';\nimport type { TimedField } from '../layers/flow.ts';\nimport type { GeoMap } from '../map.ts';\nimport { useMap } from './context.ts';\n\n/** Something a component loads: `$source` tells two sources apart (the same key, the same thing loaded), `load` loads\n * it, given up when `signal` aborts; `map` the map it needs (loaded inside an `<IsardMap>` then, once the map is there) */\nexport interface Source<T> {\n readonly $source: string;\n readonly map?: true;\n load(signal: AbortSignal, map: GeoMap | undefined): Promise<T>;\n}\n\n/** A source of its own: `key` the same for the same thing loaded (its URL and options, say) */\nexport const source = <T>(key: string, load: (signal: AbortSignal) => Promise<T>): Source<T> => ({\n $source: key,\n load,\n});\n\n/** A GeoJSON file */\nexport const geojson = <P = Properties>(url: string): Source<FeatureCollection<P>> =>\n source(`geojson:${url}`, async (signal) => {\n const response = await fetch(url, { signal });\n\n if (!response.ok) throw new Error(`${url}: ${response.status}`);\n\n return response.json();\n });\n\n/** A GPX file's tracks, routes and waypoints (`parseGpx`) */\nexport const gpx = <P = Properties>(url: string): Source<FeatureCollection<P>> =>\n source(`gpx:${url}`, async (signal) => {\n const [{ parseGpx }, response] = await Promise.all([import('../data/gpx.ts'), fetch(url, { signal })]);\n\n if (!response.ok) throw new Error(`${url}: ${response.status}`);\n\n return parseGpx<P>(await response.text());\n });\n\n/** The Géoplateforme's features of a type in a box (`geoplateformeWfs`) */\nexport const wfs = <P = Properties>(\n typeName: string,\n box: [west: number, south: number, east: number, north: number],\n options: { count?: number; srsName?: string } = {},\n): Source<FeatureCollection<P>> =>\n source(`wfs:${JSON.stringify([typeName, box, options])}`, async (signal) => {\n const { geoplateformeWfs } = await import('../geoplateforme.ts');\n\n return geoplateformeWfs<P>(typeName, box, { ...options, signal });\n });\n\n/** The features of a collection of an OGC API - Features service (`ogcFeatures`): by box, by a CQL2 filter */\nexport const ogcFeatures = <P = Properties>(\n url: string,\n collection: string,\n options: Omit<OgcFeaturesOptions, 'signal'> = {},\n): Source<FeatureCollection<P>> =>\n source(`ogcFeatures:${JSON.stringify([url, collection, options])}`, async (signal) => {\n const { ogcFeatures: load } = await import('../data/ogcapi.ts');\n\n return load<P>(url, collection, { ...options, signal });\n });\n\n/** A COLLADA model read into a glTF binary (`loadCollada`): a models layer's `data` */\nexport const collada = (url: string): Source<Uint8Array<ArrayBuffer>> =>\n source(`collada:${url}`, async (signal) => {\n const { loadCollada } = await import('../data/collada.ts');\n\n return loadCollada(url, { signal });\n });\n\n/** The wind of a GRIB2 or NetCDF file (`map.readGrids`, `windFields`): a flow layer's `fields`, read by the map's\n * workers (inside an `<IsardMap>`) */\nexport const windGrids = (url: string, options: Parameters<typeof Grids.windFields>[1] = {}): Source<TimedField[]> => ({\n $source: `wind:${url}:${JSON.stringify(options)}`,\n map: true,\n load: async (_, map) => {\n if (!map) throw new Error('windGrids: no map');\n\n const { windFields } = await import('../grids.ts');\n\n return windFields(await map.readGrids(url), options);\n },\n});\n\n/**\n * What `load` gives, once loaded (undefined before, or when it failed: `onError`). Loaded again when `key` changes (a\n * string, or an object compared by identity: `useStableOptions`'), given up when the component goes (its signal\n * aborted), what it gave let go then by `dispose`; nothing loaded while `key` is undefined\n */\nexport const useLoaded = <T>(\n key: unknown,\n load: (signal: AbortSignal) => Promise<T>,\n { onError = console.error, dispose }: { onError?: (error: unknown) => void; dispose?: (value: T) => void } = {},\n): T | undefined => {\n const [loaded, setLoaded] = useState<{ key: unknown; value: T }>();\n // Read when the key changes only: inline functions at each render load nothing again\n const latest = useRef({ load, onError, dispose });\n\n latest.current = { load, onError, dispose };\n // Loading while mounted and the key the same; a strict mode's first mount aborted, what it gave let go\n useEffect(() => {\n if (key === undefined) return;\n\n const controller = new AbortController();\n const kept: { value?: T } = {};\n const { load, onError, dispose } = latest.current;\n\n load(controller.signal).then(\n (value) => {\n if (controller.signal.aborted) {\n dispose?.(value);\n\n return;\n }\n kept.value = value;\n setLoaded({ key, value });\n },\n (error: unknown) => {\n if (!controller.signal.aborted) onError(error);\n },\n );\n\n return () => {\n controller.abort();\n if (kept.value !== undefined) dispose?.(kept.value);\n };\n }, [key]);\n\n return loaded && loaded.key === key ? loaded.value : undefined;\n};\n\n/** What a source loads, once loaded (undefined before; none without a source). A source needing the map takes the one\n * around, or `map` (outside an `<IsardMap>`: the one its `onLoad` gave); a failure given to `onError` */\nexport const useSource = <T>(\n source: Source<T> | undefined,\n options: { map?: GeoMap | undefined; onError?: (error: unknown) => void } = {},\n): T | undefined => {\n const around = useMap();\n const map = options.map ?? around;\n\n // A source needing the map waits for it\n return useLoaded(\n source && (!source.map || map) ? source.$source : undefined,\n (signal) => source?.load(signal, map) ?? Promise.reject(new Error('no source')),\n options.onError ? { onError: options.onError } : {},\n );\n};\n\n/** Calls `listener` once with each value loaded (the listener may change at each render) */\nexport const useLoadedEvent = <T>(value: T | undefined, listener: ((value: T) => void) | undefined): void => {\n const latest = useRef(listener);\n\n latest.current = listener;\n useEffect(() => {\n if (value !== undefined) latest.current?.(value);\n }, [value]);\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isard",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "A WebGL2 map engine for large, interactive data layers, labels and 3D Tiles over raster or vector basemaps (Rust core in WebAssembly)",
5
5
  "license": "MIT",
6
6
  "author": "Kevin Graff",