@nika-js/onlymap 0.6.0 → 0.6.1

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/README.md +18 -6
  3. package/THIRD-PARTY-LICENSES.md +27 -0
  4. package/dist/{LercDecode.es-fbo6h5rt.js → LercDecode.es-CJnypw8j.js} +1 -1
  5. package/dist/{basemap-CprSan9q.js → basemap-DrQ0-eyR.js} +1 -1
  6. package/dist/cityjson-D_V5GY8b.js +332 -0
  7. package/dist/crs-Ciu7Xs7a.js +108 -0
  8. package/dist/crs.d.ts +50 -0
  9. package/dist/ctx.d.ts +8 -1
  10. package/dist/elements/om-map.d.ts +26 -2
  11. package/dist/elements/om-overlay.d.ts +1 -1
  12. package/dist/elements/om-widget.d.ts +4 -0
  13. package/dist/feature-colors.d.ts +41 -0
  14. package/dist/{geoparquet-Bm8pfxyo.js → geoparquet-Dix4lTNy.js} +1 -1
  15. package/dist/html-data.d.ts +1 -1
  16. package/dist/ifc-Dc-TdSJr.js +877 -0
  17. package/dist/ifc.d.ts +406 -0
  18. package/dist/{index-Bz-rbmhj.js → index-1UgNlfGR.js} +20892 -18886
  19. package/dist/{index-GOwMjqm6.js → index-BQMjW5w0.js} +1 -1
  20. package/dist/{index-DSRIZR81.js → index-B_1PPJgC.js} +1 -1
  21. package/dist/{index-CCQttJzO.js → index-CAuT5j9Y.js} +2 -2
  22. package/dist/{index-UzmNhuS0.js → index-CXPaeisL.js} +1 -1
  23. package/dist/index.d.ts +8 -0
  24. package/dist/layer-registry.d.ts +14 -0
  25. package/dist/layers/bim-layer.d.ts +104 -0
  26. package/dist/layers/feature-mesh-layer.d.ts +288 -0
  27. package/dist/layers/gltf-scene-walk.d.ts +55 -0
  28. package/dist/{lerc-CuifOkoA.js → lerc-CbTjQ7uI.js} +2 -2
  29. package/dist/meshopt_simplifier-Co6uRDDA.js +370 -0
  30. package/dist/onlymap.standalone.js +57996 -54706
  31. package/dist/onlymapjs.js +69 -67
  32. package/dist/programmatic.d.ts +22 -2
  33. package/dist/{raster-dysYIQ_k.js → raster-0b0nSHUh.js} +2 -2
  34. package/dist/{raster-pipeline-ZdCOGfqV.js → raster-pipeline-D8siq7-4.js} +1 -1
  35. package/dist/react/om-overlay.d.ts +9 -0
  36. package/dist/react.js +144 -144
  37. package/dist/runtime-core.d.ts +110 -3
  38. package/dist/selection.d.ts +33 -0
  39. package/dist/site-placement.d.ts +85 -0
  40. package/dist/testing.d.ts +6 -2
  41. package/dist/tile3d-metadata.d.ts +185 -0
  42. package/dist/version.d.ts +1 -1
  43. package/dist/widget-registry.d.ts +11 -0
  44. package/dist/widgets/ifc-clash.d.ts +18 -0
  45. package/dist/widgets/ifc.d.ts +41 -0
  46. package/dist/{zarr-OewK7k2K.js → zarr-DCYro_Vs.js} +79 -66
  47. package/docs/testing.md +2 -2
  48. package/llms.txt +3 -3
  49. package/onlymapjs.html-data.json +152 -0
  50. package/package.json +3 -1
  51. package/skills/onlymapjs/SKILL.md +4 -2
  52. package/skills/onlymapjs/references/react.md +1 -1
  53. package/skills/onlymapjs/references/syntax.md +298 -11
  54. package/dist/cityjson-urQeujQv.js +0 -407
@@ -127,6 +127,9 @@
127
127
  },
128
128
  {
129
129
  "name": "maptiler-terrain"
130
+ },
131
+ {
132
+ "name": "mapterhorn"
130
133
  }
131
134
  ]
132
135
  },
@@ -239,6 +242,9 @@
239
242
  {
240
243
  "name": "ArcLayer"
241
244
  },
245
+ {
246
+ "name": "BIMLayer"
247
+ },
242
248
  {
243
249
  "name": "BitmapLayer"
244
250
  },
@@ -442,6 +448,18 @@
442
448
  "name": "source",
443
449
  "description": "registerSource decoder plugin name for stream messages."
444
450
  },
451
+ {
452
+ "name": "site-origin",
453
+ "description": "Georeferencing (Tile3DLayer, PathLayer): where the model sits, \"[lng, lat]\" or \"[lng, lat, elevation]\". Overrides a tileset's baked position; required to place a PathLayer of local metres."
454
+ },
455
+ {
456
+ "name": "site-heading",
457
+ "description": "Georeferencing: bearing in degrees clockwise from true north. On its own, rotates the model where it stands."
458
+ },
459
+ {
460
+ "name": "site-scale",
461
+ "description": "Georeferencing: uniform scale multiplier (default 1)."
462
+ },
445
463
  {
446
464
  "name": "get-position",
447
465
  "description": "Accessor for deck.gl getPosition — expression language: $field, scale(), formatDate(), arithmetic."
@@ -890,6 +908,54 @@
890
908
  "name": "point-size",
891
909
  "description": "deck.gl pointSize."
892
910
  },
911
+ {
912
+ "name": "pick-features",
913
+ "description": "deck.gl pickFeatures."
914
+ },
915
+ {
916
+ "name": "feature-id-property",
917
+ "description": "deck.gl featureIdProperty."
918
+ },
919
+ {
920
+ "name": "feature-styles",
921
+ "description": "deck.gl featureStyles."
922
+ },
923
+ {
924
+ "name": "feature-color-by",
925
+ "description": "deck.gl featureColorBy."
926
+ },
927
+ {
928
+ "name": "feature-color-scale",
929
+ "description": "deck.gl featureColorScale."
930
+ },
931
+ {
932
+ "name": "feature-palette",
933
+ "description": "deck.gl featurePalette."
934
+ },
935
+ {
936
+ "name": "feature-color-strength",
937
+ "description": "deck.gl featureColorStrength."
938
+ },
939
+ {
940
+ "name": "feature-filter-field",
941
+ "description": "deck.gl featureFilterField."
942
+ },
943
+ {
944
+ "name": "isolate-features",
945
+ "description": "deck.gl isolateFeatures."
946
+ },
947
+ {
948
+ "name": "hide-features",
949
+ "description": "deck.gl hideFeatures."
950
+ },
951
+ {
952
+ "name": "ghost-features",
953
+ "description": "deck.gl ghostFeatures."
954
+ },
955
+ {
956
+ "name": "ghost-opacity",
957
+ "description": "deck.gl ghostOpacity."
958
+ },
893
959
  {
894
960
  "name": "get-point-color",
895
961
  "description": "Accessor for deck.gl getPointColor — expression language: $field, scale(), formatDate(), arithmetic."
@@ -1525,6 +1591,18 @@
1525
1591
  {
1526
1592
  "name": "layer",
1527
1593
  "description": "Scope selection-anchored overlays to one layer's picks."
1594
+ },
1595
+ {
1596
+ "name": "selection-type",
1597
+ "description": "Scope selection-anchored overlays to one pick type — \"click\" keeps a click-opened popup from following hover picks; \"hover\" is the mirror. Absent: every pick applies.",
1598
+ "values": [
1599
+ {
1600
+ "name": "click"
1601
+ },
1602
+ {
1603
+ "name": "hover"
1604
+ }
1605
+ ]
1528
1606
  }
1529
1607
  ],
1530
1608
  "references": [
@@ -1741,6 +1819,24 @@
1741
1819
  },
1742
1820
  {
1743
1821
  "name": "widgets-toggle"
1822
+ },
1823
+ {
1824
+ "name": "ifc-browser"
1825
+ },
1826
+ {
1827
+ "name": "ifc-legend"
1828
+ },
1829
+ {
1830
+ "name": "feature-inspector"
1831
+ },
1832
+ {
1833
+ "name": "ifc-inspector"
1834
+ },
1835
+ {
1836
+ "name": "ifc-loader"
1837
+ },
1838
+ {
1839
+ "name": "ifc-clash"
1744
1840
  }
1745
1841
  ]
1746
1842
  },
@@ -1930,6 +2026,62 @@
1930
2026
  "name": "options",
1931
2027
  "description": "Basemap-switcher: space-separated preset names to offer (default: every keyless registered preset)."
1932
2028
  },
2029
+ {
2030
+ "name": "fields",
2031
+ "description": "IFC widgets: space-separated property-table fields — the group-by choices offered by ifc-browser, or the rows shown by feature-inspector. Hierarchy columns render as expandable TREES and are offered automatically when the model has them: \"spatialPath\" (site → storey), \"typePath\", \"systemPath\", \"classificationPath\"."
2032
+ },
2033
+ {
2034
+ "name": "scale-fields",
2035
+ "description": "ifc-browser: space-separated NUMERIC fields offered as graduated colour ramps alongside the categorical ones."
2036
+ },
2037
+ {
2038
+ "name": "rows",
2039
+ "description": "ifc-browser: visible rows before the value list scrolls (default 6)."
2040
+ },
2041
+ {
2042
+ "name": "no-color",
2043
+ "description": "ifc-browser: hide the colour-mode select and leave the model in its own IFC surface colours."
2044
+ },
2045
+ {
2046
+ "name": "show-non-physical",
2047
+ "description": "ifc-browser: include non-physical classes (IfcSpace, IfcOpeningElement, …) in the value list, which are hidden by default."
2048
+ },
2049
+ {
2050
+ "name": "placeholder",
2051
+ "description": "feature-inspector: text shown when nothing is selected."
2052
+ },
2053
+ {
2054
+ "name": "no-outlines",
2055
+ "description": "ifc-loader: skip the companion outline PathLayer for the models it loads."
2056
+ },
2057
+ {
2058
+ "name": "layers",
2059
+ "description": "ifc-clash: the two co-registered model layer ids to compare, e.g. \"arch mep\"."
2060
+ },
2061
+ {
2062
+ "name": "tolerance",
2063
+ "description": "ifc-clash: metres of real interpenetration required before a pair counts (default 0). Raise it to ignore modelling noise."
2064
+ },
2065
+ {
2066
+ "name": "wasm-path",
2067
+ "description": "ifc-loader: serve web-ifc from your own origin instead of unpkg — required for offline, air-gapped or strict-CSP deployments. Vendor the files with `npm run vendor:web-ifc <dir>` first."
2068
+ },
2069
+ {
2070
+ "name": "federate",
2071
+ "description": "ifc-loader: accept SEVERAL models into one co-registered scene (one drop zone, one layer per model, each with its own visibility toggle) instead of replacing the previous one."
2072
+ },
2073
+ {
2074
+ "name": "independent",
2075
+ "description": "ifc-loader: do NOT share the map’s model-space origin — for pages loading unrelated models rather than disciplines of one building."
2076
+ },
2077
+ {
2078
+ "name": "outline-color",
2079
+ "description": "ifc-loader: colour for the outline overlay it builds, e.g. \"[38, 46, 58, 200]\"."
2080
+ },
2081
+ {
2082
+ "name": "ghost-opacity",
2083
+ "description": "ifc-loader: ghost fade for the mesh layer it builds (default 0.15)."
2084
+ },
1933
2085
  {
1934
2086
  "name": "title",
1935
2087
  "description": "Widget heading."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nika-js/onlymap",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Declarative deck.gl maps for HTML and React — interactive WebGL mapping with GeoJSON/CSV/Arrow data, MapLibre basemaps, widgets, popups, and live streams from a custom-element manifest or typed React components. TypeScript, no build step.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "publishConfig": {
@@ -116,6 +116,7 @@
116
116
  "test:e2e": "playwright test",
117
117
  "check-layout": "playwright test e2e/layout-audit.spec.ts",
118
118
  "gen:html-data": "vite-node dev/generate-html-data.ts",
119
+ "vendor:web-ifc": "node dev/tools/vendor-web-ifc.mjs",
119
120
  "gen:public": "npm run gen:html-data && vite-node dev/build-public.ts",
120
121
  "gen:site": "vite-node dev/build-site.ts",
121
122
  "test:public": "npm run gen:public -- --dry-run --strict",
@@ -163,6 +164,7 @@
163
164
  "hyparquet-compressors": "^1.1.1",
164
165
  "jotai": "^2.20.2",
165
166
  "maplibre-gl": "^5.24.0",
167
+ "meshoptimizer": "^1.2.0",
166
168
  "mobx": "^6.16.1",
167
169
  "playwright": "^1.61.1",
168
170
  "proj4": "^2.20.8",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: onlymapjs
3
- description: Build, edit, debug, or review OnlyMapJS declarative HTML maps and dashboards, or React maps via the @nika-js/onlymap/react adapter. Use when a user asks for an interactive map, deck.gl-style visualization, geospatial dashboard, live fleet/telemetry map, choropleth, popup/tooltip map, map story/tour, manual drawing/sketch map, 3D map assets, a React map component, a map page shared as a single HTML file (incl. no-JS fallbacks for chat/email previews), a responsive/mobile map whose controls auto-fold on narrow screens, auditing a map's widget layout with the check-layout tool, syncing OnlyMapJS map/camera state into an app state store (Redux, MobX, Zustand, Jotai — the getStore contract), or help with OnlyMapJS syntax, validation, widgets, data formats, testing, or publishing examples.
3
+ description: Build, edit, debug, or review OnlyMapJS declarative HTML maps and dashboards, or React maps via the @nika-js/onlymap/react adapter. Use when a user asks for an interactive map, deck.gl-style visualization, geospatial dashboard, live fleet/telemetry map, choropleth, popup/tooltip map, map story/tour, manual drawing/sketch map, 3D map assets, a React map component, a map page shared as a single HTML file (incl. no-JS fallbacks for chat/email previews), a responsive/mobile map whose controls auto-fold on narrow screens, auditing a map's widget layout with the check-layout tool, syncing OnlyMapJS map/camera state into an app state store (Redux, MobX, Zustand, Jotai — the getStore contract), BIM/IFC models (loading .ifc files in the browser, 3D Tiles per-element picking, isolate/hide/ghost, clash detection, model federation), or help with OnlyMapJS syntax, validation, widgets, data formats, testing, or publishing examples.
4
4
  ---
5
5
 
6
6
  # OnlyMapJS
@@ -23,7 +23,7 @@ Use OnlyMapJS as a declarative HTML map library. Write custom elements such as `
23
23
  </script>
24
24
  ```
25
25
 
26
- For no-build CDN pages, use the single-file standalone bundle from a raw-file CDN — `https://unpkg.com/@nika-js/onlymap@0.6.0` (the bare package URL serves `dist/onlymap.standalone.js`) — plus `<link rel="stylesheet" href="https://unpkg.com/@nika-js/onlymap@0.6.0/dist/onlymapjs.css">`. Never a rebundling CDN (esm.sh, skypack): re-bundling duplicates the deck.gl/luma.gl runtime and every layer fails shader compilation.
26
+ For no-build CDN pages, use the single-file standalone bundle from a raw-file CDN — `https://unpkg.com/@nika-js/onlymap@0.6.1` (the bare package URL serves `dist/onlymap.standalone.js`) — plus `<link rel="stylesheet" href="https://unpkg.com/@nika-js/onlymap@0.6.1/dist/onlymapjs.css">`. Never a rebundling CDN (esm.sh, skypack): re-bundling duplicates the deck.gl/luma.gl runtime and every layer fails shader compilation.
27
27
 
28
28
  ## React Projects
29
29
 
@@ -73,6 +73,8 @@ Load the smallest reference needed for the task:
73
73
  - Group adjacent map buttons (zoom + undo + toggle into one control group) -> just place compact button widgets in the same `position` slot; they auto-cluster. `cluster="false"` opts one out. Do NOT build a wrapper widget.
74
74
  - GeoTIFF/COG raster (DEM, satellite imagery, NDVI) -> `<om-layer type="COGLayer" src="…tif">` with `min`/`max`/`colormap` for single-band data (see syntax.md — `src`, not `data`).
75
75
  - Zarr / GeoZarr raster (chunked N-D arrays — climate/weather grids, datacubes) -> `<om-layer type="ZarrLayer" src="…​.zarr" variable="…" select="time=0">` with `min`/`max`/`colormap` (same raster styling as COGLayer). Pick the `variable` and pin every non-spatial dim in `select`. A GeoZarr store georeferences itself; a plain Zarr needs manual `bounds` + `crs` + `spatial-dims`. `src`, not `data` — and it can be any absolute URL to a remote store, which needs no server setup but must be CORS-enabled (fetched in the browser) and public (authenticated stores are a follow-up). See syntax.md.
76
+ - BIM model / .ifc file / 3D Tiles with per-element picking -> `<om-layer type="BIMLayer" src="…​.ifc" pickable>` (parses the IFC in-browser; web-ifc WASM is CDN-fetched on first use) or `type="Tile3DLayer" tileset="…" pick-features` for a pre-built tileset. Author `terrain` explicitly (`terrain="mapterhorn"`, or `terrain="off"` for flat ground) — a model that resolves real elevation (IfcMapConversion + OrthogonalHeight) on a terrain-less map raises an error through the validation channel at load time, and the library never writes attributes for you. Style by property with `feature-color-by`/`feature-color-scale` (+ `feature-palette`); isolate/hide/ghost elements declaratively with `feature-filter-field` + `isolate-features`/`hide-features`/`ghost-features` (undoable, story-steppable). See syntax.md.
77
+ - Browse/inspect/clash-check BIM models -> widgets: `ifc-loader` (drop zone, `federate` for multi-model coordination), `ifc-browser` (group/count/colour by any property field), `feature-inspector` (per-element properties on pick; `ifc-inspector` is an alias), `ifc-clash` (AABB clash overlay between two co-registered models). See syntax.md.
76
78
  - Geotagged drone JPEG -> `<om-layer type="ImageOverlay" src="…jpg" georeference="exif">`; for saved/collaborative maps persist the processed image and reconstruct with explicit `bounds` (see syntax.md; this is visualization-grade, not orthorectification).
77
79
  - Dashed line/route/boundary (or any dashed stroke) -> the `dash` attribute on a path-stroking layer: `dash="[6, 3]"` (or SVG-style `dash="6 3"`, + optional `dash-justified`) on `PathLayer`/`GeoJsonLayer`/`PolygonLayer`/`TripsLayer`. `[dashLength, gapLength]` in line-width units. Do NOT hand-wire deck's `PathStyleExtension`/`getDashArray` — the attribute mounts it; `dash` on a non-path layer is ignored with a warning.
78
80
  - CityJSON/CityJSONSeq per-face surfaces mode (`?om-surfaces=1`) -> always pair the `SolidPolygonLayer` with a companion `<om-layer type="PathLayer">` using `get-path="$outline"` to make roof/wall edges visible. This mode is unlit and `SolidPolygonLayer`'s own `wireframe` prop does nothing here (deck only builds wireframe geometry when `extruded: true`); the `PathLayer` is the only way to see face edges. Give it the same `filter-field`/`filter-range` as the fill layer so filtered-out buildings' outlines disappear too. See syntax.md.
@@ -51,7 +51,7 @@ function StatsPanel({ onToggle }) {
51
51
  - **`<OmMap>`** — `center`/`zoom`/`pitch`/`bearing` (initial; later changes move the camera, unchanged props never fight user panning), `basemap`, `headless`, `widgetStyle` (layout-token sugar, the `widget-style` attribute's twin: `"gap:10 opacity:0.9"` → `--om-widget-*` custom properties), `widgetsHidden` (hide-all: hides authored managed widget wrappers without removal, so widget state survives; provider attribution and the license badge stay visible in their slots), `widgetsFold` (default true; map-width responsive side drawers, set false to opt out), `onReady`, `onViewStateChange`, `onRuntimeError`. Give it a size via `style`/`className`. `ref` exposes the imperative `MapController` handle: `flyTo`, `setView`, `emit`, `getLayers`, `getSelection`, `injectPick`, `ready` (promise), `project`.
52
52
  - **`<OmLayer>`** — `id` + `type` (any registered deck.gl layer type) + deck props. `data`: stable inline reference or URL string (full Data Layer: CSV/Arrow/Shapefile/KML formats, `ws(s)://` streams via `source`/`streamKey`/`flush`, `refresh` polling). `label`/`color` feed `ctx.layers`; `filterField`/`filterRange` = GPU filter; `onClick`/`onHover` receive the flattened picked object (`onHover(null)` = pointer left).
53
53
  - **`<OmWidget>`** — positioning shell: `position` takes one of 8 managed slots (logical, RTL-aware: `top-start|top-center|top-end|center-start|center-end|bottom-start|bottom-center|bottom-end`; legacy corners `top-left` etc. alias) + arbitrary JSX. Same-slot widgets stack with flush edges and a shared gap; at map widths ≤640px they auto-fold into per-side drawers (`fold="never"` exempts an essential control); provider attribution joins `bottom-end` and the license badge joins `bottom-start` as in-flow members; `order={1}` sets deterministic in-slot ordering. `position="manual"` renders a plain block at the JSX site — note it sits inside OmMap's overflow-hidden box, so for UI OUTSIDE the map render your own element next to `<OmMap>` and drive the map via `useOmMap()`/the ref instead. (Automatic button-clustering of adjacent compact widgets, and collision-dim of slots under an open overlay, are HTML-lane only — in React, compose your own control group in JSX and dim via your own state.)
54
- - **`<OmOverlay>`** — geo-anchored HTML with managed projection/tracking/culling. `anchor={[lng, lat]}` or `anchorFrom="selection"` (+ `layer` to scope which picks move it); children may be `(selection) => JSX`; `anchorOffset` (default `bottom-center`); `interactive={false}` for hover-following tooltips.
54
+ - **`<OmOverlay>`** — geo-anchored HTML with managed projection/tracking/culling. `anchor={[lng, lat]}` or `anchorFrom="selection"` (+ `layer` to scope which picks move it, + `selectionType="click"|"hover"` to scope which pick TYPE — a click-opened popup wants `selectionType="click"`, else hovering any pickable feature drags and re-renders it; a click on empty space still dismisses); children may be `(selection) => JSX`; `anchorOffset` (default `bottom-center`); `interactive={false}` for hover-following tooltips.
55
55
  - **`useOmMap(watch?)`** — the same `ctx` contract HTML widget scripts get, typed: `layers`, `viewport`, `selection`, `emit`, `data()`, `dataInViewport()`, `stats()`. Watch tokens: `"viewport"`, `"selection"`, `"layers"`, `"data:<layerId>"`. Rides `useSyncExternalStore` (tearing-safe; `ctx` identity stable until a watched token fires).
56
56
  - **`controller.getStore(token)`** — framework-free `{subscribe, getSnapshot}` per watch token (cached plain-data snapshots; viewport snapshots carry `origin: "user"|"programmatic"` for echo-free two-way binding). Use it to sync map state into Redux/MobX/Zustand/Jotai — recipes in docs/external-stores.md; never mirror row arrays into a store (use the `data:<id>` version stamp + `ctx.data()`).
57
57