ofs-object 0.1.1 → 0.1.3
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/README.md +42 -4
- package/dist/index.d.ts +313 -4
- package/dist/ofs-object.cjs +74 -73
- package/dist/ofs-object.js +7037 -6460
- package/docs/API.md +9 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,6 +47,38 @@ npm install mapbox-gl
|
|
|
47
47
|
|
|
48
48
|
> MapLibre v6 เป็น ES module ล้วน (ไม่มี CommonJS) ถ้าจะใช้ `require()` ใน Node ต้องใช้ MapLibre v5 หรือใช้ Mapbox แทน — ผ่าน bundler (Angular, Vite, webpack) ใช้ได้ตามปกติ
|
|
49
49
|
|
|
50
|
+
#### ⚠️ ต้องส่ง Map Engine เข้ามาเอง
|
|
51
|
+
|
|
52
|
+
**ไลบรารีนี้ไม่ `import` map engine ตัวไหนเลย** — เพราะถ้า import ตัวใดตัวหนึ่งไว้ มันจะกลายเป็น
|
|
53
|
+
dependency บังคับของทุกคน คนที่ใช้ Mapbox และไม่ได้ลง `maplibre-gl` จะ build ไม่ผ่านด้วย
|
|
54
|
+
`Can't resolve 'maplibre-gl'` ตั้งแต่ยังไม่ได้รันโค้ด
|
|
55
|
+
|
|
56
|
+
ดังนั้นตอนให้ `init()` สร้างแผนที่ ต้องส่ง library เข้ามาด้วย:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// MapLibre v6 ไม่มี default export → ใช้ namespace import
|
|
60
|
+
import * as maplibregl from 'maplibre-gl';
|
|
61
|
+
|
|
62
|
+
const ofs = new OFSObject({ mapOptions: { maplibregl } });
|
|
63
|
+
await ofs.init('map', { center: [100.5, 13.7], zoom: 12 });
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// Mapbox
|
|
68
|
+
import mapboxgl from 'mapbox-gl';
|
|
69
|
+
|
|
70
|
+
const ofs = new OFSObject({
|
|
71
|
+
mapAdapter: new MapboxAdapter(),
|
|
72
|
+
mapOptions: { mapboxgl, accessToken: 'pk....' },
|
|
73
|
+
});
|
|
74
|
+
await ofs.init('map');
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
หรือโหลดจาก `<script>` tag ก็ได้ ไลบรารีจะอ่านจาก `window.maplibregl` / `window.mapboxgl` ให้เอง
|
|
78
|
+
|
|
79
|
+
> **ถ้าแอปสร้าง Map เอง** (แนะนำสำหรับ Angular/React/Vue — ดูหัวข้อด้านล่าง) แล้วส่งเข้ามาทาง
|
|
80
|
+
> `new OFSObject({ map })` **ไม่ต้องส่ง engine เลย** เพราะไลบรารีไม่ต้องสร้างแผนที่
|
|
81
|
+
|
|
50
82
|
### Stylesheet
|
|
51
83
|
|
|
52
84
|
Widget ที่ไลบรารี mount ให้ (Command Console, Legend, แผง Symbology, ตาราง Attribute, แผง Topology) ต้องการไฟล์ CSS หนึ่งไฟล์:
|
|
@@ -95,12 +127,15 @@ npm install git+ssh://git@github.com/<user>/OnFarmObject.git#main
|
|
|
95
127
|
|
|
96
128
|
```typescript
|
|
97
129
|
import { OFSObject, MapLibreAdapter, LegendWidget } from 'ofs-object';
|
|
130
|
+
import * as maplibregl from 'maplibre-gl';
|
|
98
131
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
99
132
|
|
|
100
133
|
async function initMap() {
|
|
101
134
|
// 1. สร้าง Instance หลักของ OFSObject (ใช้ MapLibre เป็นค่าเริ่มต้น)
|
|
135
|
+
// ต้องส่ง maplibregl เข้ามา เพราะไลบรารีไม่ import map engine เอง
|
|
102
136
|
const ofs = new OFSObject({
|
|
103
137
|
mapAdapter: new MapLibreAdapter(),
|
|
138
|
+
mapOptions: { maplibregl },
|
|
104
139
|
});
|
|
105
140
|
|
|
106
141
|
// 2. กำหนดแผนที่ลงบน HTML Container Element id="map"
|
|
@@ -259,8 +294,9 @@ initMap();
|
|
|
259
294
|
|
|
260
295
|
<script type="module">
|
|
261
296
|
import { OFSObject } from 'ofs-object';
|
|
297
|
+
import * as maplibregl from 'maplibre-gl';
|
|
262
298
|
|
|
263
|
-
const ofs = new OFSObject();
|
|
299
|
+
const ofs = new OFSObject({ mapOptions: { maplibregl } });
|
|
264
300
|
await ofs.init('map');
|
|
265
301
|
ofs.consoleWidget.mount('console-mount');
|
|
266
302
|
</script>
|
|
@@ -273,6 +309,7 @@ initMap();
|
|
|
273
309
|
```tsx
|
|
274
310
|
import React, { useEffect, useRef } from 'react';
|
|
275
311
|
import { OFSObject, LegendWidget } from 'ofs-object';
|
|
312
|
+
import * as maplibregl from 'maplibre-gl';
|
|
276
313
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
277
314
|
|
|
278
315
|
export const MapView: React.FC = () => {
|
|
@@ -283,7 +320,7 @@ export const MapView: React.FC = () => {
|
|
|
283
320
|
useEffect(() => {
|
|
284
321
|
if (!mapContainerRef.current) return;
|
|
285
322
|
|
|
286
|
-
const ofs = new OFSObject();
|
|
323
|
+
const ofs = new OFSObject({ mapOptions: { maplibregl } });
|
|
287
324
|
ofsRef.current = ofs;
|
|
288
325
|
|
|
289
326
|
ofs.init(mapContainerRef.current, {
|
|
@@ -339,7 +376,7 @@ export class MapViewComponent implements OnInit, OnDestroy {
|
|
|
339
376
|
private ofs!: OFSObject;
|
|
340
377
|
|
|
341
378
|
async ngOnInit() {
|
|
342
|
-
this.ofs = new OFSObject();
|
|
379
|
+
this.ofs = new OFSObject({ mapOptions: { maplibregl } });
|
|
343
380
|
await this.ofs.init(this.mapContainer.nativeElement, {
|
|
344
381
|
center: [100.5, 13.7],
|
|
345
382
|
zoom: 13,
|
|
@@ -455,6 +492,7 @@ const ofs = new OFSObject({ map, console: myAngularConsole });
|
|
|
455
492
|
<script setup lang="ts">
|
|
456
493
|
import { onMounted, onUnmounted, ref } from 'vue';
|
|
457
494
|
import { OFSObject, LegendWidget } from 'ofs-object';
|
|
495
|
+
import * as maplibregl from 'maplibre-gl';
|
|
458
496
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
459
497
|
|
|
460
498
|
const mapContainer = ref<HTMLDivElement | null>(null);
|
|
@@ -464,7 +502,7 @@ let ofs: OFSObject | null = null;
|
|
|
464
502
|
onMounted(async () => {
|
|
465
503
|
if (!mapContainer.value) return;
|
|
466
504
|
|
|
467
|
-
ofs = new OFSObject();
|
|
505
|
+
ofs = new OFSObject({ mapOptions: { maplibregl } });
|
|
468
506
|
await ofs.init(mapContainer.value, {
|
|
469
507
|
center: [100.5, 13.7],
|
|
470
508
|
zoom: 12,
|
package/dist/index.d.ts
CHANGED
|
@@ -272,6 +272,15 @@ export declare abstract class BaseGLAdapter implements IMapAdapter {
|
|
|
272
272
|
protected whenStyleLoaded(map: any): Promise<void>;
|
|
273
273
|
bindDataSource(dataSource: OFSDataSource, thematicEngine?: OFSThematicEngine): void;
|
|
274
274
|
protected syncAllLayers(): void;
|
|
275
|
+
/**
|
|
276
|
+
* Put a raster or vector tile layer on the map, or bring an existing one up to date.
|
|
277
|
+
*
|
|
278
|
+
* Tile layers are registered in the same `glLayers` table as feature layers, so removal, stacking
|
|
279
|
+
* and the clean hand-back in `removeOwnLayers` treat both kinds alike without knowing which is
|
|
280
|
+
* which. What they do not share is the data path: there is no GeoJSON to send, so nothing here
|
|
281
|
+
* touches sources after the first creation except to rebuild when the styling changes.
|
|
282
|
+
*/
|
|
283
|
+
syncTileLayer(layer: OFSTileLayer): void;
|
|
275
284
|
syncLayer(layer: OFSLayerData): void;
|
|
276
285
|
/** Reordering several layers emits one update per layer; restack once */
|
|
277
286
|
private scheduleLayerOrder;
|
|
@@ -1478,6 +1487,12 @@ export declare function findIntersectingFeature(dataSource: OFSDataSource, targe
|
|
|
1478
1487
|
feature: Feature<Geometry, any>;
|
|
1479
1488
|
} | null;
|
|
1480
1489
|
|
|
1490
|
+
/**
|
|
1491
|
+
* The engine to build a map with, or null when the caller has not supplied one.
|
|
1492
|
+
* `options` wins over the global: passing a library explicitly should always be what gets used.
|
|
1493
|
+
*/
|
|
1494
|
+
export declare function findMapEngine(global: MapEngineGlobal, options?: Record<string, any>): any | null;
|
|
1495
|
+
|
|
1481
1496
|
export declare function forEachPosition(geometry: Geometry, fn: (c: Position) => void): void;
|
|
1482
1497
|
|
|
1483
1498
|
/** Degrees as "45°30'20"" (bearing) or "45.5056°" */
|
|
@@ -2040,7 +2055,11 @@ export declare interface LegendGroupViewModel {
|
|
|
2040
2055
|
export declare interface LegendLayerViewModel {
|
|
2041
2056
|
id: string;
|
|
2042
2057
|
name: string;
|
|
2043
|
-
|
|
2058
|
+
/**
|
|
2059
|
+
* Geometry for a feature layer, or the tile kind for one served from a tile server. Tile layers
|
|
2060
|
+
* carry no features and no symbology, so `items` is empty and `featureCount` is zero for them.
|
|
2061
|
+
*/
|
|
2062
|
+
type: LayerGeometryType | 'raster' | 'vector';
|
|
2044
2063
|
visible: boolean;
|
|
2045
2064
|
/** Visible and all parent groups visible */
|
|
2046
2065
|
rendered: boolean;
|
|
@@ -2156,6 +2175,33 @@ export declare function listExpressionVariables(): string[];
|
|
|
2156
2175
|
|
|
2157
2176
|
export declare function listMarkerIcons(): string[];
|
|
2158
2177
|
|
|
2178
|
+
/**
|
|
2179
|
+
* Read a project back onto the map.
|
|
2180
|
+
*
|
|
2181
|
+
* Layers go in before groups are wired up and before the themes are applied, so that a theme never
|
|
2182
|
+
* arrives for a layer that is not there yet.
|
|
2183
|
+
*/
|
|
2184
|
+
export declare function loadProject(dataSource: OFSDataSource, thematicEngine: OFSThematicEngine, project: OFSProjectFile, options?: LoadProjectOptions): LoadProjectResult;
|
|
2185
|
+
|
|
2186
|
+
export declare interface LoadProjectOptions {
|
|
2187
|
+
/**
|
|
2188
|
+
* Clear what is already loaded first (default). Turning this off merges the project in, which
|
|
2189
|
+
* replaces any layer whose id it also defines.
|
|
2190
|
+
*/
|
|
2191
|
+
replace?: boolean;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
export declare interface LoadProjectResult {
|
|
2195
|
+
layers: string[];
|
|
2196
|
+
tileLayers: string[];
|
|
2197
|
+
groups: number;
|
|
2198
|
+
features: number;
|
|
2199
|
+
themes: number;
|
|
2200
|
+
view?: ProjectView;
|
|
2201
|
+
/** Layers the file described but carried no data for */
|
|
2202
|
+
emptyLayers: string[];
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2159
2205
|
export declare function localName(name: string): string;
|
|
2160
2206
|
|
|
2161
2207
|
export declare type LocationPredicate = 'intersects' | 'within' | 'contains' | 'disjoint' | 'touches' | 'crosses' | 'within-distance';
|
|
@@ -2171,6 +2217,12 @@ export declare function makeCurve(vertices: Coordinate[], bulges: number[], sagT
|
|
|
2171
2217
|
|
|
2172
2218
|
export declare class MapboxAdapter extends BaseGLAdapter {
|
|
2173
2219
|
readonly engineName: "mapbox";
|
|
2220
|
+
/**
|
|
2221
|
+
* Build a map in `container`.
|
|
2222
|
+
*
|
|
2223
|
+
* `mapbox-gl` is not imported by this package - see `resolve-engine.ts` - so pass the library in
|
|
2224
|
+
* as `options.mapboxgl`, or load it from a script tag.
|
|
2225
|
+
*/
|
|
2174
2226
|
init(container: HTMLElement | string, options?: Record<string, any>): Promise<void>;
|
|
2175
2227
|
}
|
|
2176
2228
|
|
|
@@ -2189,6 +2241,22 @@ export declare interface MapClickEvent {
|
|
|
2189
2241
|
originalEvent: MouseEvent;
|
|
2190
2242
|
}
|
|
2191
2243
|
|
|
2244
|
+
/**
|
|
2245
|
+
* Finding the map engine an adapter should build its map with.
|
|
2246
|
+
*
|
|
2247
|
+
* Neither `maplibre-gl` nor `mapbox-gl` is imported anywhere in this package, and that is
|
|
2248
|
+
* deliberate. Both are optional peer dependencies, but a static `import` of one is a hard
|
|
2249
|
+
* dependency for every consumer regardless of what they actually use: the import sits in the
|
|
2250
|
+
* bundle, the bundler has to resolve it, and an application built on Mapbox that never installed
|
|
2251
|
+
* `maplibre-gl` fails at build time with "Can't resolve 'maplibre-gl'" before a line of code runs.
|
|
2252
|
+
* It failed even for applications that create their own map and hand it over with `attach()`, where
|
|
2253
|
+
* the engine is never needed at all.
|
|
2254
|
+
*
|
|
2255
|
+
* So the engine is handed to the adapter rather than imported: through `options`, or from the global
|
|
2256
|
+
* a CDN script tag leaves on `window`.
|
|
2257
|
+
*/
|
|
2258
|
+
export declare type MapEngineGlobal = 'maplibregl' | 'mapboxgl';
|
|
2259
|
+
|
|
2192
2260
|
export declare class MapEngineNotInitializedError extends OFSError {
|
|
2193
2261
|
constructor(message?: string);
|
|
2194
2262
|
}
|
|
@@ -2220,6 +2288,13 @@ export declare interface MapImage {
|
|
|
2220
2288
|
|
|
2221
2289
|
export declare class MapLibreAdapter extends BaseGLAdapter {
|
|
2222
2290
|
readonly engineName: "maplibre";
|
|
2291
|
+
/**
|
|
2292
|
+
* Build a map in `container`.
|
|
2293
|
+
*
|
|
2294
|
+
* `maplibre-gl` is not imported by this package - see `resolve-engine.ts` for why - so pass the
|
|
2295
|
+
* library in as `options.maplibregl`, or load it from a script tag. An application that creates
|
|
2296
|
+
* its own map does not come through here at all; it calls `attach()`.
|
|
2297
|
+
*/
|
|
2223
2298
|
init(container: HTMLElement | string, options?: Record<string, any>): Promise<void>;
|
|
2224
2299
|
}
|
|
2225
2300
|
|
|
@@ -2608,6 +2683,14 @@ export declare interface OfsCurveMeta {
|
|
|
2608
2683
|
|
|
2609
2684
|
export declare class OFSDataSource extends TypedEventEmitter<OFSDataSourceEvents> {
|
|
2610
2685
|
private layers;
|
|
2686
|
+
/**
|
|
2687
|
+
* Tile layers are kept apart from feature layers on purpose. Everything that reads
|
|
2688
|
+
* `getAllLayers()` - snapping, topology, export, the attribute table, the AI context - wants
|
|
2689
|
+
* features, and a tile layer has none to give. Mixing them into that list would mean auditing
|
|
2690
|
+
* every one of those callers for a case that can only ever be "skip this". `getDisplayLayers()`
|
|
2691
|
+
* brings the two back together for the things that do treat them alike: the legend and the stack.
|
|
2692
|
+
*/
|
|
2693
|
+
private tileLayers;
|
|
2611
2694
|
private groups;
|
|
2612
2695
|
private activeLayerId;
|
|
2613
2696
|
private selectionStore;
|
|
@@ -2648,7 +2731,36 @@ export declare class OFSDataSource extends TypedEventEmitter<OFSDataSourceEvents
|
|
|
2648
2731
|
*/
|
|
2649
2732
|
getAllLayers(): OFSLayerData[];
|
|
2650
2733
|
/**
|
|
2651
|
-
*
|
|
2734
|
+
* Add a raster or vector tile layer.
|
|
2735
|
+
*
|
|
2736
|
+
* ```ts
|
|
2737
|
+
* ds.addTileLayer({ id: 'ortho', name: 'Aerial', kind: 'raster',
|
|
2738
|
+
* tiles: ['https://tiles.example/{z}/{x}/{y}.png'], tileSize: 256, zIndex: -1 });
|
|
2739
|
+
* ```
|
|
2740
|
+
*
|
|
2741
|
+
* A vector tile set also needs `styles`, naming which layer inside the tile to draw and how; a
|
|
2742
|
+
* vector tile carries no styling of its own, so there is nothing to fall back on.
|
|
2743
|
+
*/
|
|
2744
|
+
addTileLayer(metadata: TileLayerMetadata): OFSTileLayer;
|
|
2745
|
+
getTileLayer(layerId: string): OFSTileLayer | undefined;
|
|
2746
|
+
/** Tile layers, lowest in the stack first */
|
|
2747
|
+
getTileLayers(): OFSTileLayer[];
|
|
2748
|
+
removeTileLayer(layerId: string): boolean;
|
|
2749
|
+
/** Replace the drawing instructions of a vector tile layer */
|
|
2750
|
+
setTileLayerStyles(layerId: string, styles: OFSTileLayer['styles']): void;
|
|
2751
|
+
/**
|
|
2752
|
+
* Every layer that appears on the map, tile and feature alike, lowest first.
|
|
2753
|
+
*
|
|
2754
|
+
* This is what the legend lists and what decides the drawing order, so a raster basemap at
|
|
2755
|
+
* zIndex -1 sits under the parcels without either side knowing about the other.
|
|
2756
|
+
*/
|
|
2757
|
+
getDisplayLayers(): (OFSLayerData | OFSTileLayer)[];
|
|
2758
|
+
/** A layer of either kind, for the settings the two have in common */
|
|
2759
|
+
private findAnyLayer;
|
|
2760
|
+
/** Tell the right listeners that a layer changed, whichever kind it is */
|
|
2761
|
+
private emitLayerChanged;
|
|
2762
|
+
/**
|
|
2763
|
+
* Set layer visibility. Works on tile layers too, so one legend toggle drives both kinds.
|
|
2652
2764
|
*/
|
|
2653
2765
|
setLayerVisibility(layerId: string, visible: boolean): void;
|
|
2654
2766
|
/**
|
|
@@ -2691,7 +2803,7 @@ export declare class OFSDataSource extends TypedEventEmitter<OFSDataSourceEvents
|
|
|
2691
2803
|
moveLayerToGroup(layerId: string, groupId: string | null): void;
|
|
2692
2804
|
/** True when the layer is inside the group, directly or through sub-groups */
|
|
2693
2805
|
isLayerInGroup(layerId: string, groupId: string): boolean;
|
|
2694
|
-
/** A layer is drawn when it and all of its parent groups are visible */
|
|
2806
|
+
/** A layer of either kind is drawn when it and all of its parent groups are visible */
|
|
2695
2807
|
isLayerRendered(layerId: string): boolean;
|
|
2696
2808
|
setActiveLayer(layerId: string | null): void;
|
|
2697
2809
|
getActiveLayerId(): string | null;
|
|
@@ -2816,6 +2928,15 @@ export declare interface OFSDataSourceEvents {
|
|
|
2816
2928
|
'layer:updated': {
|
|
2817
2929
|
layer: OFSLayerData;
|
|
2818
2930
|
};
|
|
2931
|
+
'tile-layer:added': {
|
|
2932
|
+
layer: OFSTileLayer;
|
|
2933
|
+
};
|
|
2934
|
+
'tile-layer:removed': {
|
|
2935
|
+
layerId: string;
|
|
2936
|
+
};
|
|
2937
|
+
'tile-layer:updated': {
|
|
2938
|
+
layer: OFSTileLayer;
|
|
2939
|
+
};
|
|
2819
2940
|
'feature:added': {
|
|
2820
2941
|
layerId: string;
|
|
2821
2942
|
feature: Feature<Geometry, any>;
|
|
@@ -3465,7 +3586,25 @@ export declare interface OFSFeatureMetadata {
|
|
|
3465
3586
|
|
|
3466
3587
|
export declare class OFSFileIO {
|
|
3467
3588
|
private dataSource;
|
|
3468
|
-
|
|
3589
|
+
private thematicEngine?;
|
|
3590
|
+
/**
|
|
3591
|
+
* `thematicEngine` is only needed for projects, which carry the styling of each layer. File
|
|
3592
|
+
* import and export never touch it, so it stays optional and `saveProject` says so if it is
|
|
3593
|
+
* missing rather than silently writing a project with no symbology in it.
|
|
3594
|
+
*/
|
|
3595
|
+
constructor(dataSource: OFSDataSource, thematicEngine?: OFSThematicEngine | undefined);
|
|
3596
|
+
/** Attach the styling engine after construction, when the two are built in that order */
|
|
3597
|
+
useThematicEngine(engine: OFSThematicEngine): void;
|
|
3598
|
+
private requireThemes;
|
|
3599
|
+
/**
|
|
3600
|
+
* Write the whole map out as a project: the layers and their data, the tile layers, the groups,
|
|
3601
|
+
* the styling and the drawing order. See `project.ts`.
|
|
3602
|
+
*/
|
|
3603
|
+
saveProject(options?: SaveProjectOptions): OFSProjectFile;
|
|
3604
|
+
/** Read a project back onto the map, from an object or from the text of a `.ofsproj` file */
|
|
3605
|
+
loadProject(project: OFSProjectFile | string, options?: LoadProjectOptions): LoadProjectResult;
|
|
3606
|
+
/** A project as a file ready to be downloaded or written to disk */
|
|
3607
|
+
exportProject(name?: string, options?: SaveProjectOptions): ExportedFile;
|
|
3469
3608
|
/** Parse and add files as new layers */
|
|
3470
3609
|
import(files: InputFile[], options?: ImportOptions): ImportToDataSourceResult;
|
|
3471
3610
|
/** Browser File objects (from <input type="file"> or drag & drop) */
|
|
@@ -3795,6 +3934,8 @@ export declare class OFSObject {
|
|
|
3795
3934
|
private dynamicInput;
|
|
3796
3935
|
/** Map handed over by the host application (config.map), attached on init() */
|
|
3797
3936
|
private readonly hostMap;
|
|
3937
|
+
/** Defaults for the map init() builds; the engine itself is usually passed here */
|
|
3938
|
+
private readonly mapOptions;
|
|
3798
3939
|
constructor(config?: OFSObjectConfig);
|
|
3799
3940
|
/**
|
|
3800
3941
|
* Initialize map adapter and bind data source.
|
|
@@ -3816,12 +3957,29 @@ export declare class OFSObject {
|
|
|
3816
3957
|
/**
|
|
3817
3958
|
* Clean up all resources
|
|
3818
3959
|
*/
|
|
3960
|
+
/**
|
|
3961
|
+
* Save the whole map as a project: layers and their data, tile layers, groups, styling, drawing
|
|
3962
|
+
* order, and where the map is looking. `ofs.io.saveProject()` does the same without the view.
|
|
3963
|
+
*/
|
|
3964
|
+
saveProject(options?: SaveProjectOptions): OFSProjectFile;
|
|
3965
|
+
/** Reopen a saved project, and move the map back to where it was looking */
|
|
3966
|
+
loadProject(project: OFSProjectFile | string, options?: LoadProjectOptions): LoadProjectResult;
|
|
3967
|
+
/** Where the map is looking, or undefined before there is a map to ask */
|
|
3968
|
+
private currentView;
|
|
3819
3969
|
destroy(): void;
|
|
3820
3970
|
}
|
|
3821
3971
|
|
|
3822
3972
|
export declare interface OFSObjectConfig {
|
|
3823
3973
|
mapAdapter?: IMapAdapter;
|
|
3824
3974
|
container?: HTMLElement | string;
|
|
3975
|
+
/**
|
|
3976
|
+
* Options for the map `init()` builds, merged under the ones passed to `init()` itself.
|
|
3977
|
+
*
|
|
3978
|
+
* This is where the map engine goes. Neither `maplibre-gl` nor `mapbox-gl` is imported by this
|
|
3979
|
+
* package, so that an application using one need not install the other, which means the library
|
|
3980
|
+
* has to be handed in: `{ mapOptions: { maplibregl } }` after `import maplibregl from
|
|
3981
|
+
* 'maplibre-gl'`. A map the host creates itself needs none of this - pass it as `map` below.
|
|
3982
|
+
*/
|
|
3825
3983
|
mapOptions?: Record<string, any>;
|
|
3826
3984
|
/**
|
|
3827
3985
|
* A MapLibre / Mapbox map the host application created and keeps owning (Angular, React, Vue).
|
|
@@ -3839,6 +3997,23 @@ export declare interface OFSObjectConfig {
|
|
|
3839
3997
|
console?: IOFSConsole;
|
|
3840
3998
|
}
|
|
3841
3999
|
|
|
4000
|
+
export declare interface OFSProjectFile {
|
|
4001
|
+
format: typeof PROJECT_FORMAT;
|
|
4002
|
+
version: number;
|
|
4003
|
+
savedAt: string;
|
|
4004
|
+
/** False when the file describes the layers and their styling but carries no feature data */
|
|
4005
|
+
includesFeatures: boolean;
|
|
4006
|
+
activeLayerId: string | null;
|
|
4007
|
+
groups: LayerGroup[];
|
|
4008
|
+
layers: ProjectLayer[];
|
|
4009
|
+
/** Tile layers are always small - a URL and some numbers - so they are always written in full */
|
|
4010
|
+
tileLayers: TileLayerMetadata[];
|
|
4011
|
+
themes: ThematicDefinition[];
|
|
4012
|
+
view?: ProjectView;
|
|
4013
|
+
/** Anything the host application wants to keep with the map */
|
|
4014
|
+
extra?: Record<string, unknown>;
|
|
4015
|
+
}
|
|
4016
|
+
|
|
3842
4017
|
declare class OFSSelectionOverlay {
|
|
3843
4018
|
private dataSource;
|
|
3844
4019
|
private mapAdapter;
|
|
@@ -3979,6 +4154,38 @@ export declare class OFSThematicEngine extends TypedEventEmitter<ThematicEvents>
|
|
|
3979
4154
|
compile(layer: OFSLayerData): CompiledLayerStyle;
|
|
3980
4155
|
}
|
|
3981
4156
|
|
|
4157
|
+
export declare class OFSTileLayer {
|
|
4158
|
+
readonly id: string;
|
|
4159
|
+
readonly kind: TileLayerKind;
|
|
4160
|
+
name: string;
|
|
4161
|
+
zIndex: number;
|
|
4162
|
+
visible: boolean;
|
|
4163
|
+
opacity: number;
|
|
4164
|
+
pinned: boolean;
|
|
4165
|
+
tag?: string;
|
|
4166
|
+
groupId?: string;
|
|
4167
|
+
readonly tiles: string[];
|
|
4168
|
+
readonly url?: string;
|
|
4169
|
+
readonly tileSize: number;
|
|
4170
|
+
readonly scheme: 'xyz' | 'tms';
|
|
4171
|
+
readonly minzoom?: number;
|
|
4172
|
+
readonly maxzoom?: number;
|
|
4173
|
+
readonly bounds?: BoundingBox;
|
|
4174
|
+
readonly attribution?: string;
|
|
4175
|
+
styles: VectorTileStyle[];
|
|
4176
|
+
readonly metadata: TileLayerMetadata;
|
|
4177
|
+
constructor(metadata: TileLayerMetadata);
|
|
4178
|
+
/** The source definition a GL map engine expects. Undefined keys are dropped, not sent as null. */
|
|
4179
|
+
toSourceSpec(): Record<string, any>;
|
|
4180
|
+
/**
|
|
4181
|
+
* The GL layers to draw this tile set with, bottom first.
|
|
4182
|
+
*
|
|
4183
|
+
* Opacity is folded into the paint properties rather than applied to the layer as a whole,
|
|
4184
|
+
* because GL styles have no layer-wide opacity: each type names its own.
|
|
4185
|
+
*/
|
|
4186
|
+
toLayerSpecs(): Record<string, any>[];
|
|
4187
|
+
}
|
|
4188
|
+
|
|
3982
4189
|
export declare class OFSTopologyPanel {
|
|
3983
4190
|
private readonly dataSource;
|
|
3984
4191
|
private readonly topology;
|
|
@@ -4265,6 +4472,9 @@ export declare function parseLngLat(raw: string): Coordinate | null;
|
|
|
4265
4472
|
/** Parse a number, or null when the text is not a finite number */
|
|
4266
4473
|
export declare function parseNumber(text: string): number | null;
|
|
4267
4474
|
|
|
4475
|
+
/** Parse a project from the text of a `.ofsproj` file */
|
|
4476
|
+
export declare function parseProject(text: string): OFSProjectFile;
|
|
4477
|
+
|
|
4268
4478
|
export declare function parseWkb(bytes: Uint8Array, offset?: number): {
|
|
4269
4479
|
geometry: Geometry;
|
|
4270
4480
|
end: number;
|
|
@@ -4346,9 +4556,27 @@ export declare function printImportResult(consoleService: IOFSConsole, result: I
|
|
|
4346
4556
|
/** Print an import / export report: summary lines, then issues grouped by code */
|
|
4347
4557
|
export declare function printIssues(consoleService: IOFSConsole, issues: ImportIssue[], limit?: number): void;
|
|
4348
4558
|
|
|
4559
|
+
export declare const PROJECT_FORMAT = "ofs-project";
|
|
4560
|
+
|
|
4561
|
+
export declare const PROJECT_VERSION = 1;
|
|
4562
|
+
|
|
4349
4563
|
/** Plane to do the arc maths on, centred on the curve so distances come out in ground meters */
|
|
4350
4564
|
export declare function projectionForVertices(vertices: Coordinate[]): PlanarProjection;
|
|
4351
4565
|
|
|
4566
|
+
export declare interface ProjectLayer {
|
|
4567
|
+
metadata: LayerMetadata;
|
|
4568
|
+
/** Left out when the project was saved without feature data */
|
|
4569
|
+
features?: Feature<Geometry, any>[];
|
|
4570
|
+
}
|
|
4571
|
+
|
|
4572
|
+
/** Where the map was looking when the project was saved */
|
|
4573
|
+
export declare interface ProjectView {
|
|
4574
|
+
center: Coordinate;
|
|
4575
|
+
zoom: number;
|
|
4576
|
+
bearing?: number;
|
|
4577
|
+
pitch?: number;
|
|
4578
|
+
}
|
|
4579
|
+
|
|
4352
4580
|
export declare class PromptBuilder {
|
|
4353
4581
|
/**
|
|
4354
4582
|
* Summarize current map state for LLM prompt context.
|
|
@@ -4425,6 +4653,9 @@ export declare function renderSymbolSwatchSvg(symbol: SymbolStyle, geomType: Lay
|
|
|
4425
4653
|
/** Report an error that was caught and recovered from */
|
|
4426
4654
|
export declare function reportInternalError(scope: string, error: unknown): void;
|
|
4427
4655
|
|
|
4656
|
+
/** The engine to build a map with, or an error saying how to supply one */
|
|
4657
|
+
export declare function requireMapEngine(global: MapEngineGlobal, options?: Record<string, any>): any;
|
|
4658
|
+
|
|
4428
4659
|
/**
|
|
4429
4660
|
* Resolves all selected features across all layers in the dataset,
|
|
4430
4661
|
* prioritizing active layer features first, followed by other layers,
|
|
@@ -4548,6 +4779,21 @@ export declare function runTopologyChecks(features: AnyFeature[], layer: {
|
|
|
4548
4779
|
name?: string;
|
|
4549
4780
|
}, options?: TopologyOptions): Generator<TopologyProgress, TopologyReport, void>;
|
|
4550
4781
|
|
|
4782
|
+
/** Write the current map out as a project */
|
|
4783
|
+
export declare function saveProject(dataSource: OFSDataSource, thematicEngine: OFSThematicEngine, options?: SaveProjectOptions): OFSProjectFile;
|
|
4784
|
+
|
|
4785
|
+
export declare interface SaveProjectOptions {
|
|
4786
|
+
/**
|
|
4787
|
+
* Write the features into the file (default). Turning this off keeps the layers, their styling
|
|
4788
|
+
* and their order but leaves the data out, for a project meant to be reconnected to a database
|
|
4789
|
+
* or to files that live elsewhere - and for a project of 98,000 parcels, which is 60 MB of
|
|
4790
|
+
* GeoJSON nobody wants in version control.
|
|
4791
|
+
*/
|
|
4792
|
+
features?: boolean;
|
|
4793
|
+
view?: ProjectView;
|
|
4794
|
+
extra?: Record<string, unknown>;
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4551
4797
|
export declare interface ScaleBarPlan {
|
|
4552
4798
|
/** Ground distance the bar represents, in meters */
|
|
4553
4799
|
meters: number;
|
|
@@ -5023,6 +5269,40 @@ export declare interface ThematicEvents {
|
|
|
5023
5269
|
*/
|
|
5024
5270
|
export declare type ThematicType = 'simple' | 'categorical' | 'graduated';
|
|
5025
5271
|
|
|
5272
|
+
export declare type TileLayerKind = 'raster' | 'vector';
|
|
5273
|
+
|
|
5274
|
+
export declare interface TileLayerMetadata {
|
|
5275
|
+
id: string;
|
|
5276
|
+
name: string;
|
|
5277
|
+
kind: TileLayerKind;
|
|
5278
|
+
/**
|
|
5279
|
+
* Tile URL templates with `{z}`, `{x}` and `{y}` placeholders. Several entries are read as
|
|
5280
|
+
* mirrors of the same tile set, which is how a server spreads load across subdomains.
|
|
5281
|
+
*/
|
|
5282
|
+
tiles?: string[];
|
|
5283
|
+
/** A TileJSON document describing the tile set, as an alternative to `tiles` */
|
|
5284
|
+
url?: string;
|
|
5285
|
+
/** Raster tile edge in pixels; 512 for the retina tiles many providers serve */
|
|
5286
|
+
tileSize?: number;
|
|
5287
|
+
/** `tms` counts rows from the bottom, the opposite of the usual `xyz` */
|
|
5288
|
+
scheme?: 'xyz' | 'tms';
|
|
5289
|
+
minzoom?: number;
|
|
5290
|
+
maxzoom?: number;
|
|
5291
|
+
/** Area the tile set covers; outside it the map does not ask for tiles */
|
|
5292
|
+
bounds?: BoundingBox;
|
|
5293
|
+
/** Credit line the provider requires; map engines show it in the corner */
|
|
5294
|
+
attribution?: string;
|
|
5295
|
+
/** Required for `vector`, meaningless for `raster` */
|
|
5296
|
+
styles?: VectorTileStyle[];
|
|
5297
|
+
zIndex?: number;
|
|
5298
|
+
visible?: boolean;
|
|
5299
|
+
opacity?: number;
|
|
5300
|
+
pinned?: boolean;
|
|
5301
|
+
tag?: string;
|
|
5302
|
+
groupId?: string;
|
|
5303
|
+
[key: string]: unknown;
|
|
5304
|
+
}
|
|
5305
|
+
|
|
5026
5306
|
/** Split on whitespace, keeping "quoted text" together */
|
|
5027
5307
|
export declare function tokenizeArgs(raw: string): string[];
|
|
5028
5308
|
|
|
@@ -5299,6 +5579,14 @@ export declare function validateFieldName(name: string, existing: FieldSchema[])
|
|
|
5299
5579
|
*/
|
|
5300
5580
|
export declare function validateGeometry(geometry: Geometry | null | undefined, index: number, issues: ImportIssue[], ctx?: ValidationContext): Geometry | null;
|
|
5301
5581
|
|
|
5582
|
+
/**
|
|
5583
|
+
* Check that a value really is a project this build can open, and say what is wrong when it is not.
|
|
5584
|
+
*
|
|
5585
|
+
* A file from a newer release is refused rather than half-read: reading the parts that happen to
|
|
5586
|
+
* look familiar and quietly dropping the rest produces a map that looks plausible and is wrong.
|
|
5587
|
+
*/
|
|
5588
|
+
export declare function validateProject(value: unknown): OFSProjectFile;
|
|
5589
|
+
|
|
5302
5590
|
export declare interface ValidationContext {
|
|
5303
5591
|
file?: string;
|
|
5304
5592
|
closeRings?: boolean;
|
|
@@ -5306,6 +5594,27 @@ export declare interface ValidationContext {
|
|
|
5306
5594
|
geographic?: boolean;
|
|
5307
5595
|
}
|
|
5308
5596
|
|
|
5597
|
+
/**
|
|
5598
|
+
* How one named layer inside a vector tile should be drawn.
|
|
5599
|
+
*
|
|
5600
|
+
* Vector tiles carry several layers ("roads", "buildings", "parcels") and no instructions for
|
|
5601
|
+
* drawing any of them, so the caller says which to draw and how. Nothing is guessed: a tile set
|
|
5602
|
+
* whose styling is left out renders nothing, which is a silent blank map, so it is refused instead.
|
|
5603
|
+
*/
|
|
5604
|
+
export declare interface VectorTileStyle {
|
|
5605
|
+
/** Name of the layer inside the tile, as the tile server publishes it */
|
|
5606
|
+
sourceLayer: string;
|
|
5607
|
+
type: 'fill' | 'line' | 'circle' | 'symbol';
|
|
5608
|
+
/** GL paint properties, passed through as given */
|
|
5609
|
+
paint?: Record<string, any>;
|
|
5610
|
+
layout?: Record<string, any>;
|
|
5611
|
+
filter?: any[];
|
|
5612
|
+
minzoom?: number;
|
|
5613
|
+
maxzoom?: number;
|
|
5614
|
+
/** Suffix for the GL layer id; needed when one source layer is drawn more than once */
|
|
5615
|
+
id?: string;
|
|
5616
|
+
}
|
|
5617
|
+
|
|
5309
5618
|
export declare type WorkflowStatus = 'idle' | 'running' | 'waiting_input' | 'completed' | 'failed' | 'cancelled';
|
|
5310
5619
|
|
|
5311
5620
|
/** Convert a world math angle (radians, CCW from East) to a user angle in the frame's convention [0, 360) */
|