@nika-js/onlymap 0.4.4 → 0.5.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/README.md +10 -7
- package/THIRD-PARTY-LICENSES.md +2 -2
- package/bin/onlymapjs.mjs +14 -1
- package/dist/{LercDecode.es-CgN9Gb9e.js → LercDecode.es-B-OFS9hR.js} +1 -1
- package/dist/{basemap-Bfn5Z__c.js → basemap-CXVNH22A.js} +3 -3
- package/dist/cityjson-urQeujQv.js +407 -0
- package/dist/cityjson.d.ts +138 -0
- package/dist/data-layer.d.ts +10 -0
- package/dist/elements/om-map.d.ts +70 -0
- package/dist/{index-lXrP3rPo.js → index-BonJP_St.js} +1 -1
- package/dist/index-CW1n5LdO.js +4006 -0
- package/dist/{index-CnitG1VX.js → index-CjZMcGou.js} +2 -2
- package/dist/{index-M8KfTTol.js → index-DE7T4lfa.js} +1 -1
- package/dist/{index-KgO0MBqA.js → index-DiYFebYs.js} +11514 -11259
- package/dist/{index-C4cWRigY.js → index-DuY3Zn6r.js} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/layer-registry.d.ts +22 -0
- package/dist/{lerc-l-QFh62d.js → lerc-BhtFlCQ3.js} +2 -2
- package/dist/license.d.ts +34 -8
- package/dist/onlymap.standalone.js +23608 -22941
- package/dist/onlymapjs.js +69 -65
- package/dist/programmatic.d.ts +4 -0
- package/dist/quota-notice.d.ts +43 -0
- package/dist/raster-BpVAEzbU.js +4842 -0
- package/dist/react.js +162 -161
- package/dist/runtime-core.d.ts +9 -0
- package/dist/testing.d.ts +6 -0
- package/dist/version.d.ts +1 -1
- package/dist/widget-layout.d.ts +20 -0
- package/docs/3d-assets.md +99 -1
- package/docs/testing.md +4 -2
- package/llms.txt +2 -2
- package/onlymapjs.html-data.json +12 -8
- package/package.json +3 -2
- package/skills/onlymapjs/SKILL.md +4 -2
- package/skills/onlymapjs/references/patterns.md +4 -0
- package/skills/onlymapjs/references/syntax.md +70 -17
- package/skills/onlymapjs/references/testing.md +2 -1
- package/dist/raster-BBA_oI-d.js +0 -8843
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CityJSON / CityJSONSeq ingestion (spec: "CityJSON ingestion"; issue #25).
|
|
3
|
+
*
|
|
4
|
+
* A LAZY chunk — reached only through `CITYJSON_FORMAT`'s dynamic import in
|
|
5
|
+
* data-layer.ts, so neither this decoder nor proj4 weighs on the eager
|
|
6
|
+
* bundle (the src/raster.ts precedent). proj4 itself is imported lazily
|
|
7
|
+
* AGAIN inside `resolveCrs`, so a file already in lon/lat never pays for it.
|
|
8
|
+
*
|
|
9
|
+
* Two output shapes share one geometry computation (`computeCityObjectGeometry`):
|
|
10
|
+
*
|
|
11
|
+
* - DEFAULT — one GeoJSON `Feature` per CityObject: a 2D footprint polygon
|
|
12
|
+
* plus DERIVED height properties, rendered through GeoJsonLayer's
|
|
13
|
+
* `extruded` + `get-elevation`. Lit, pickable, GPU-filterable,
|
|
14
|
+
* terrain-aware — and, because extrusion is a flat-topped prism, it
|
|
15
|
+
* cannot draw the actual shape of a pitched/hipped LoD2.2 roof no matter
|
|
16
|
+
* how accurate the derived height is.
|
|
17
|
+
* - `?om-surfaces=1` — one flat row PER FACE (wall, roof, ground), each
|
|
18
|
+
* carrying its real 3D ring coordinates (real per-vertex height, not a
|
|
19
|
+
* uniform extrusion) for `SolidPolygonLayer` with `extruded="false"` and
|
|
20
|
+
* `full3d`. This draws the true reconstructed shape. The tradeoff: deck's
|
|
21
|
+
* solid-polygon vertex shader computes lighting only inside its
|
|
22
|
+
* `if (solidPolygon.extruded)` branch (verified against
|
|
23
|
+
* solid-polygon-layer-vertex-main.glsl.js), so this path is unavoidably
|
|
24
|
+
* unlit — flat per-face fill color, no shading from surface orientation.
|
|
25
|
+
* `_full3d` is what makes near-vertical wall polygons triangulate at all:
|
|
26
|
+
* without it earcut works in the flat xy plane, where a wall's projected
|
|
27
|
+
* area is ~zero and the face silently vanishes.
|
|
28
|
+
*
|
|
29
|
+
* Semantics are not discarded in either mode: they drive which vertices
|
|
30
|
+
* count as roof (so the derived heights are real roof heights, not
|
|
31
|
+
* bounding-box heights) and survive as a `surface_type` per-face property in
|
|
32
|
+
* surfaces mode.
|
|
33
|
+
*/
|
|
34
|
+
/** [x, y, z] in the source CRS — decompressed, not yet reprojected. */
|
|
35
|
+
type Vec3 = [number, number, number];
|
|
36
|
+
/** A face is a list of rings; ring[0] is the outer boundary, the rest are holes. */
|
|
37
|
+
type Face = number[][];
|
|
38
|
+
interface CityJsonTransform {
|
|
39
|
+
scale?: number[];
|
|
40
|
+
translate?: number[];
|
|
41
|
+
}
|
|
42
|
+
interface CityJsonSemantics {
|
|
43
|
+
surfaces?: {
|
|
44
|
+
type?: string;
|
|
45
|
+
}[];
|
|
46
|
+
values?: unknown;
|
|
47
|
+
}
|
|
48
|
+
interface CityJsonGeometry {
|
|
49
|
+
type?: string;
|
|
50
|
+
lod?: string | number;
|
|
51
|
+
boundaries?: unknown;
|
|
52
|
+
semantics?: CityJsonSemantics;
|
|
53
|
+
}
|
|
54
|
+
interface CityObject {
|
|
55
|
+
type?: string;
|
|
56
|
+
attributes?: Record<string, unknown>;
|
|
57
|
+
geometry?: CityJsonGeometry[];
|
|
58
|
+
parents?: string[];
|
|
59
|
+
children?: string[];
|
|
60
|
+
}
|
|
61
|
+
export declare function decompressVertices(vertices: number[][] | undefined, transform: CityJsonTransform | undefined): Vec3[];
|
|
62
|
+
/**
|
|
63
|
+
* Geometry → flat face list. Surface-less geometry types (points, lines) and
|
|
64
|
+
* anything unrecognized yield no faces, so the CityObject is skipped rather
|
|
65
|
+
* than emitted with a broken footprint.
|
|
66
|
+
*/
|
|
67
|
+
export declare function flattenToFaces(geometry: CityJsonGeometry): Face[];
|
|
68
|
+
/** One semantic surface type per face (`"RoofSurface"`, …), aligned by index. */
|
|
69
|
+
export declare function faceSemantics(geometry: CityJsonGeometry, faceCount: number): (string | undefined)[];
|
|
70
|
+
/**
|
|
71
|
+
* Highest-LoD geometry that actually has surfaces. Higher LoD wins even though
|
|
72
|
+
* the output is an extrusion: an LoD2 solid carries real roof vertices and
|
|
73
|
+
* semantics, so its derived heights beat LoD1's single stated height.
|
|
74
|
+
* `?om-lod=` pins a specific one (see `parseCityJsonDocument`).
|
|
75
|
+
*/
|
|
76
|
+
export declare function chooseGeometry(geometries: CityJsonGeometry[] | undefined, lodPin?: number): CityJsonGeometry | undefined;
|
|
77
|
+
/** `"https://www.opengis.net/def/crs/EPSG/0/7415"` / `"urn:ogc:def:crs:EPSG::7415"` / `"EPSG:7415"` → 7415. */
|
|
78
|
+
export declare function parseEpsgCode(referenceSystem: string | undefined): number | undefined;
|
|
79
|
+
/** Source [x, y] → WGS84 [lon, lat]. */
|
|
80
|
+
export interface CrsAdapter {
|
|
81
|
+
toLngLat(x: number, y: number): [number, number];
|
|
82
|
+
/**
|
|
83
|
+
* True when source coordinates are already metres (a projected grid), so
|
|
84
|
+
* horizontal areas can be measured on them directly. Geographic sources are
|
|
85
|
+
* in degrees and need a local metric frame first — see `buildFeature`.
|
|
86
|
+
*/
|
|
87
|
+
projected: boolean;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build the reprojection adapter for a document. An unsupported EPSG code
|
|
91
|
+
* throws rather than silently misplacing a whole city — the failure surfaces
|
|
92
|
+
* through the Data Layer's own `Failed to fetch data="…"` path, the same as
|
|
93
|
+
* any other format error.
|
|
94
|
+
*/
|
|
95
|
+
export declare function resolveCrs(referenceSystem: string | undefined, url: string): Promise<CrsAdapter>;
|
|
96
|
+
/** Derived property names. Documented as reserved — they win over same-named source attributes. */
|
|
97
|
+
export interface DerivedProperties {
|
|
98
|
+
cityobject_id: string;
|
|
99
|
+
cityobject_type: string;
|
|
100
|
+
parent_id?: string;
|
|
101
|
+
lod?: string;
|
|
102
|
+
ground_height: number;
|
|
103
|
+
roof_height: number;
|
|
104
|
+
eaves_height: number;
|
|
105
|
+
ridge_height: number;
|
|
106
|
+
roof_area: number;
|
|
107
|
+
surface_count: number;
|
|
108
|
+
}
|
|
109
|
+
export declare function defaultFillColor(surfaceType: string | undefined, cityObjectType: string | undefined): string;
|
|
110
|
+
/**
|
|
111
|
+
* CityObjects → features (default) or per-face surface rows (`mode:
|
|
112
|
+
* "surfaces"`, see `parseSurfacesFlag`). Geometry usually hangs off child
|
|
113
|
+
* objects (`BuildingPart`, `BridgePart`), so a parent's attributes are
|
|
114
|
+
* inherited by its children — the child's own values win, and `parent_id`
|
|
115
|
+
* keeps the hierarchy walkable for selection.
|
|
116
|
+
*/
|
|
117
|
+
export declare function decodeCityObjects(cityObjects: Record<string, CityObject> | undefined, vertices: Vec3[], crs: CrsAdapter, lodPin: number | undefined, mode?: "footprint" | "surfaces"): unknown[];
|
|
118
|
+
/** `?om-lod=1.2` → 1.2. The DataFormat contract sees only the URL, so this is the option channel. */
|
|
119
|
+
export declare function parseLodPin(url: string): number | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* `?om-surfaces=1` → per-face `SolidPolygonLayer` rows instead of the default
|
|
122
|
+
* footprint-extrusion `GeoJsonLayer` Features. Same option-channel idiom as
|
|
123
|
+
* `om-lod` — and the same URL-keyed cache benefit: a plain URL and its
|
|
124
|
+
* `?om-surfaces=1` counterpart parse and cache independently, so one manifest
|
|
125
|
+
* can point a `GeoJsonLayer` at one and a `SolidPolygonLayer` at the other.
|
|
126
|
+
*/
|
|
127
|
+
export declare function parseSurfacesFlag(url: string): boolean;
|
|
128
|
+
/** A whole `.city.json` document. One JSON parse — a single JSON value has no incremental path. */
|
|
129
|
+
export declare function parseCityJsonDocument(res: Response, url: string): Promise<unknown[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Streaming `.city.jsonl`. `push` hands the Data Layer a fresh array reference
|
|
132
|
+
* every batch so deck.gl's shallow `data` diff fires and the city fills in as
|
|
133
|
+
* it downloads; the returned array is the complete set.
|
|
134
|
+
*/
|
|
135
|
+
export declare function parseCityJsonSeq(res: Response, url: string, push: (features: unknown[]) => void): Promise<unknown[]>;
|
|
136
|
+
/** Test hook — resets the once-per-page missing-CRS warning. */
|
|
137
|
+
export declare function resetCityJsonWarningsForTests(): void;
|
|
138
|
+
export {};
|
package/dist/data-layer.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ export interface DataFormat {
|
|
|
70
70
|
match(url: string, contentType?: string): boolean;
|
|
71
71
|
/** Parse the claimed response. The parser module should be lazy-imported here (HU1 — the apache-arrow precedent). `url` is the requested URL (res.url is empty on constructed Responses — test fetches, service workers). */
|
|
72
72
|
parse(res: Response, url: string): Promise<LayerData>;
|
|
73
|
+
/**
|
|
74
|
+
* Optional progressive variant for record-per-line formats (CityJSONSeq):
|
|
75
|
+
* `push` publishes a partial snapshot mid-download, taking the same
|
|
76
|
+
* cache-swap + notify path a stream flush takes, so the map fills in as
|
|
77
|
+
* bytes arrive instead of staying empty until EOF. Pass a FRESH array
|
|
78
|
+
* reference each time — deck.gl diffs `data` by identity. When present this
|
|
79
|
+
* is used instead of `parse`; the returned value is the complete dataset.
|
|
80
|
+
* `push` is a no-op during a `refresh` re-fetch — see getData for why.
|
|
81
|
+
*/
|
|
82
|
+
parseIncremental?(res: Response, url: string, push: (partial: LayerData) => void): Promise<LayerData>;
|
|
73
83
|
}
|
|
74
84
|
/**
|
|
75
85
|
* Row objects → ColumnarData (the memory-efficient shape: one array per
|
|
@@ -55,6 +55,9 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
55
55
|
private errorPanel;
|
|
56
56
|
private runtimeErrors;
|
|
57
57
|
private readyFired;
|
|
58
|
+
private visibleSizeChecked;
|
|
59
|
+
/** Custom-state holder for the `om-collapsed` height-floor marker — see applyHeightFloor. */
|
|
60
|
+
private internals;
|
|
58
61
|
private resolveReady;
|
|
59
62
|
readonly ready: Promise<void>;
|
|
60
63
|
private readonly viewSettle;
|
|
@@ -67,6 +70,8 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
67
70
|
private widgetLayer;
|
|
68
71
|
private readonly slotContainers;
|
|
69
72
|
private readonly mandatedChromeHosts;
|
|
73
|
+
/** Slots that host mandated chrome (badge/attribution) — set at host creation, so the collision-dim exemption is a slot-level flag, not a per-flush DOM scan. */
|
|
74
|
+
private readonly slotsWithMandatedChrome;
|
|
70
75
|
private widgetResizeObserver;
|
|
71
76
|
private widgetsFolded;
|
|
72
77
|
private foldPassPending;
|
|
@@ -99,13 +104,22 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
99
104
|
* adapters mount/unmount the actual controls inside.
|
|
100
105
|
*/
|
|
101
106
|
private ensureMandatedChromeHost;
|
|
107
|
+
/** True while an internal reparent (slotting/manual-flip) is moving a widget — its transient disconnect must NOT be read as an author removal. */
|
|
108
|
+
private inSlotReparent;
|
|
109
|
+
/** Wrap an internal reparent: suppress history AND flag it as a move so unregisterWidgetInternal keeps the fold/anchor bookkeeping. */
|
|
110
|
+
private reparent;
|
|
102
111
|
slotWidgetInternal(el: HTMLElement, slot: WidgetSlot): void;
|
|
103
112
|
/** Called by <om-widget> when its live `fold` attribute changes. */
|
|
104
113
|
refreshWidgetFoldInternal(): void;
|
|
105
114
|
private startWidgetFoldObserver;
|
|
115
|
+
private foldBreakpointRaw?;
|
|
116
|
+
private foldBreakpointCache;
|
|
117
|
+
/** Cached breakpoint resolution — re-probes only when the token string actually changes, not on every ResizeObserver tick. */
|
|
106
118
|
private foldBreakpointPx;
|
|
107
119
|
private measureWidgetFold;
|
|
108
120
|
private updateWidgetFoldForWidth;
|
|
121
|
+
/** Lift the bottom-end row clear of the bottom drawer toggle while folded. Applied here AND in the fold pass so a lazily-created bottom-end container still gets it. */
|
|
122
|
+
private syncFoldBottomOffset;
|
|
109
123
|
private scheduleFoldPass;
|
|
110
124
|
private shouldFoldWidget;
|
|
111
125
|
private ensureFoldDrawer;
|
|
@@ -172,6 +186,7 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
172
186
|
* modeled (headless has no rects; this no-ops there).
|
|
173
187
|
*/
|
|
174
188
|
private dimSlotsAgainstOverlays;
|
|
189
|
+
/** widgets-toggle can sit in any author-chosen slot, so still scan for it (attribution/badge are covered by the slot flag). */
|
|
175
190
|
private slotHasNeverHidesWidget;
|
|
176
191
|
emit(event: string, payload?: Record<string, unknown>): void;
|
|
177
192
|
/** Recenters (and optionally rezooms) the map — instant, not an animated fly. */
|
|
@@ -218,6 +233,20 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
218
233
|
*/
|
|
219
234
|
injectPickInternal(selection: Selection | null): void;
|
|
220
235
|
injectDragPickInternal(selection: Selection): void;
|
|
236
|
+
/** Every click/hover map coordinate (spec: "Manual Drawing"): drives the
|
|
237
|
+
* internal draw controller AND fires the public `om-map-point` event, so
|
|
238
|
+
* consumer capture tools the built-in draw widget doesn't cover
|
|
239
|
+
* (rectangle/circle AOIs) can subscribe. The two consumers are
|
|
240
|
+
* DECOUPLED: the event dispatches first (dispatchEvent isolates a
|
|
241
|
+
* throwing listener), then the draw controller runs — so neither a
|
|
242
|
+
* throwing draw session nor a throwing listener can starve the other.
|
|
243
|
+
* Fires at pointer rate on hover (no debounce — vertex capture needs
|
|
244
|
+
* every point); heavy listeners should throttle their own work. */
|
|
245
|
+
private handleMapPoint;
|
|
246
|
+
/** Harness map-point injection (spec: "Consumer Testing Surface") — the
|
|
247
|
+
* same path a real deck click/hover coordinate takes, so the om-map-point
|
|
248
|
+
* event and custom capture tools are testable without a GPU. */
|
|
249
|
+
injectMapPointInternal(coordinate: [number, number] | null, kind?: "click" | "hover"): void;
|
|
221
250
|
/** Harness setView (spec: "Consumer Testing Surface") — the one path that reaches pitch/bearing. */
|
|
222
251
|
setViewInternal(partial: {
|
|
223
252
|
longitude?: number;
|
|
@@ -258,6 +287,33 @@ export declare class OmMapElement extends HTMLElementBase {
|
|
|
258
287
|
private dispatchRendererLoad;
|
|
259
288
|
/** Fires `om-map-ready` / resolves `.ready` once the first reconcile ran, the renderer is up, and no declared data URL is still loading. */
|
|
260
289
|
private checkReady;
|
|
290
|
+
/**
|
|
291
|
+
* Per-element half of the base-layout guardrail: mark the host `om-collapsed`
|
|
292
|
+
* so the layered `min-height` floor applies, but ONLY while it genuinely
|
|
293
|
+
* measures zero. Gating the floor this way is what lets an explicit author
|
|
294
|
+
* height win outright — a map with any height never carries the state, so the
|
|
295
|
+
* floor rule never matches it and a 300px map stays 300px.
|
|
296
|
+
*
|
|
297
|
+
* Clear-then-re-measure makes it idempotent and self-correcting: the connect-
|
|
298
|
+
* time call runs mid-parse, where a parent sized by later siblings still
|
|
299
|
+
* measures zero, and the post-ready call drops a floor that turned out to be
|
|
300
|
+
* unnecessary.
|
|
301
|
+
*
|
|
302
|
+
* A custom state rather than an attribute or inline style, deliberately: the
|
|
303
|
+
* host's own MutationObserver treats attribute writes as manifest edits (a
|
|
304
|
+
* reconcile), history.ts records them as undo steps, and either would
|
|
305
|
+
* serialize into a saved manifest. A custom state touches none of that.
|
|
306
|
+
*/
|
|
307
|
+
private applyHeightFloor;
|
|
308
|
+
/**
|
|
309
|
+
* First-shot guardrail: warn (once) if the map has no visible size once it is
|
|
310
|
+
* ready. The base-layout default covers a bare `<om-map>`, but a constrained
|
|
311
|
+
* parent (a 0-height flex/grid cell, `height:100%` under an unsized ancestor)
|
|
312
|
+
* can still collapse it — a silent blank map otherwise.
|
|
313
|
+
* Skipped headless: jsdom/happy-dom report 0×0 by design, and `mountForTest`
|
|
314
|
+
* sets the `headless` attribute, so this never fires in the test harness.
|
|
315
|
+
*/
|
|
316
|
+
private checkVisibleSize;
|
|
261
317
|
private pickPayload;
|
|
262
318
|
/**
|
|
263
319
|
* Dispatches to every `<om-behavior on="eventName">` (live-queried, like
|
|
@@ -302,6 +358,20 @@ declare global {
|
|
|
302
358
|
/** "user" if any change in the settled burst came from a canvas gesture; "programmatic" for pure API/action/story moves. */
|
|
303
359
|
origin: "user" | "programmatic";
|
|
304
360
|
}>;
|
|
361
|
+
/** Every click/hover's map coordinate (null when the pointer is off any
|
|
362
|
+
* geometry deck can unproject) — the consumer hook for custom capture
|
|
363
|
+
* tools beyond the built-in draw widget. */
|
|
364
|
+
"om-map-point": CustomEvent<{
|
|
365
|
+
coordinate: [number, number] | null;
|
|
366
|
+
kind: "click" | "hover";
|
|
367
|
+
}>;
|
|
368
|
+
/** A Tile3DLayer finished loading its root tileset — detail carries the
|
|
369
|
+
* authored layer id and the live deck `Tileset3D` for tools (e.g. region
|
|
370
|
+
* export) that need the real tileset, not the IR. */
|
|
371
|
+
"om-tileset-load": CustomEvent<{
|
|
372
|
+
layerId: string;
|
|
373
|
+
tileset: unknown;
|
|
374
|
+
}>;
|
|
305
375
|
}
|
|
306
376
|
}
|
|
307
377
|
export {};
|