@nika-js/onlymap 0.8.0 → 0.8.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.
package/dist/onlymapjs.js CHANGED
@@ -1,4 +1,4 @@
1
- import { aC as e, aD as r, aE as t, aF as o, aG as b, aH as i, ap as l, aI as n, aJ as S, aK as c, aL as E, aM as L, aN as g, aO as T, aP as _, aQ as d, aR as A, aS as p, aT as I, aU as m, aV as D, aW as u, aX as M, aY as y, aZ as O, a_ as f, ao as R, a$ as N, aw as P, b0 as F, b1 as h, b2 as C, W as B, b3 as v, b4 as x, b5 as G, b6 as U, b7 as W, b8 as w, b9 as Y, ba as X, bb as H, bc as k, bd as J, be as K, bf as V, bg as z, bh as Q, bi as Z, bj as $, bk as j, bl as q, bm as aa, bn as sa, bo as ea, bp as ra, bq as ta, br as oa, bs as ba, bt as ia, bu as la, bv as na, bw as Sa, bx as ca, by as Ea, bz as La, bA as ga, bB as Ta, bC as _a, bD as da, bE as Aa, bF as pa, bG as Ia, bH as ma, bI as Da, bJ as ua, bK as Ma, bL as ya, bM as Oa, bN as fa, bO as Ra, bP as Na, bQ as Pa, bR as Fa, bS as ha, bT as Ca, bU as Ba, bV as va, bW as xa, bX as Ga, bY as Ua, bZ as Wa, b_ as wa, b$ as Ya, c0 as Xa, c1 as Ha, c2 as ka, c3 as Ja, c4 as Ka, c5 as Va, c6 as za, c7 as Qa, c8 as Za, c9 as $a, ca as ja, cb as qa, cc as as, cd as ss } from "./index-BGOblzWN.js";
1
+ import { aC as e, aD as r, aE as t, aF as o, aG as b, aH as i, ap as l, aI as n, aJ as S, aK as c, aL as E, aM as L, aN as g, aO as T, aP as _, aQ as d, aR as A, aS as p, aT as I, aU as m, aV as D, aW as u, aX as M, aY as y, aZ as O, a_ as f, ao as R, a$ as N, aw as P, b0 as F, b1 as h, b2 as C, W as B, b3 as v, b4 as x, b5 as G, b6 as U, b7 as W, b8 as w, b9 as Y, ba as X, bb as H, bc as k, bd as J, be as K, bf as V, bg as z, bh as Q, bi as Z, bj as $, bk as j, bl as q, bm as aa, bn as sa, bo as ea, bp as ra, bq as ta, br as oa, bs as ba, bt as ia, bu as la, bv as na, bw as Sa, bx as ca, by as Ea, bz as La, bA as ga, bB as Ta, bC as _a, bD as da, bE as Aa, bF as pa, bG as Ia, bH as ma, bI as Da, bJ as ua, bK as Ma, bL as ya, bM as Oa, bN as fa, bO as Ra, bP as Na, bQ as Pa, bR as Fa, bS as ha, bT as Ca, bU as Ba, bV as va, bW as xa, bX as Ga, bY as Ua, bZ as Wa, b_ as wa, b$ as Ya, c0 as Xa, c1 as Ha, c2 as ka, c3 as Ja, c4 as Ka, c5 as Va, c6 as za, c7 as Qa, c8 as Za, c9 as $a, ca as ja, cb as qa, cc as as, cd as ss } from "./index-D6R4z3Zs.js";
2
2
  export {
3
3
  e as ALL_POSITION_VALUES,
4
4
  r as AUDIT_EXEMPTIONS,
@@ -1,5 +1,5 @@
1
- import { c as se, t as ze, i as wt, a as Be, s as St, C as Pt, b as bt, F as Ct, A as Lt, d as It, R as fe, e as Gt, p as vt, m as Et, f as Ft, g as At, r as _e, h as jt, j as Rt, k as Ut, l as Mt, n as Ot } from "./raster-pipeline-D1yeoJo2.js";
2
- import { ax as Kt, ay as xt } from "./index-BGOblzWN.js";
1
+ import { c as se, t as ze, i as wt, a as Be, s as St, C as Pt, b as bt, F as Ct, A as Lt, d as It, R as fe, e as Gt, p as vt, m as Et, f as Ft, g as At, r as _e, h as jt, j as Rt, k as Ut, l as Mt, n as Ot } from "./raster-pipeline-X2-mnFQx.js";
2
+ import { ax as Kt, ay as xt } from "./index-D6R4z3Zs.js";
3
3
  import ye from "./index-CW1n5LdO.js";
4
4
  function Dt(e, t) {
5
5
  const n = e.length / 3, r = new Uint8ClampedArray(n * 4), o = 0, i = n, a = n * 2;
@@ -1070,7 +1070,7 @@ j.set(f.Zstd, () => import("./zstd-jXobGRcq.js").then((e) => e.decode));
1070
1070
  j.set(f.Jpeg, () => Promise.resolve(le));
1071
1071
  j.set(f.Jpeg6, () => Promise.resolve(le));
1072
1072
  j.set(f.Webp, () => Promise.resolve(le));
1073
- j.set(f.Lerc, () => import("./lerc-D7TfTy6l.js").then((e) => e.l).then((e) => e.decode));
1073
+ j.set(f.Lerc, () => import("./lerc-BdHcL8pi.js").then((e) => e.l).then((e) => e.decode));
1074
1074
  async function ce(e, t, n) {
1075
1075
  const r = j.get(t);
1076
1076
  if (!r)
@@ -1,5 +1,5 @@
1
1
  import { w as de } from "./mgrs-BY9bIvp4.js";
2
- import { am as he, an as fe, ao as se, ap as oe, aq as me, b as pe, ar as ge, l as Z, as as ve, d as be, at as xe, au as Pe, av as ye, aw as ie } from "./index-BGOblzWN.js";
2
+ import { am as he, an as fe, ao as se, ap as oe, aq as me, b as pe, ar as ge, l as Z, as as ve, d as be, at as xe, au as Pe, av as ye, aw as ie } from "./index-D6R4z3Zs.js";
3
3
  function Te(r, e, t) {
4
4
  const { projectedCorners: n } = e, { topLeft: s, topRight: o, bottomRight: i, bottomLeft: a } = n, c = t(s[0], s[1]), u = t(o[0], o[1]), l = t(i[0], i[1]), h = t(a[0], a[1]), f = [
5
5
  c,
@@ -283,6 +283,8 @@ export declare class RuntimeCore {
283
283
  private drawCaptureActive;
284
284
  /** setDragPan's last value, inverted — see standaloneControllerOverrides. */
285
285
  private dragPanSuppressed;
286
+ /** setMaxPitch's last value — the controller's tilt ceiling, or null for the default. */
287
+ private maxPitch;
286
288
  /** Retained descriptors — what the per-frame channel re-applies against. */
287
289
  private lastIRs;
288
290
  /** layerId → effect-driven plain-prop patches (the per-frame channel). */
@@ -714,6 +716,16 @@ export declare class RuntimeCore {
714
716
  */
715
717
  setDragPan(active: boolean): void;
716
718
  private standaloneControllerOverrides;
719
+ /**
720
+ * Cap how far the user can tilt, in degrees, or null for the default.
721
+ *
722
+ * On the CONTROLLER rather than the camera, in both modes: clamping a pitch
723
+ * after the gesture produced it makes the view overshoot and spring back,
724
+ * while a maximum simply refuses to go further. A cartograph frame uses this
725
+ * — it can only georeference a tilt its own shape allows, and beyond that the
726
+ * frame has no scale bar, north arrow or graticule at all.
727
+ */
728
+ setMaxPitch(maxPitch: number | null): void;
717
729
  /**
718
730
  * Used by the built-in `zoom-controls` widget's emitted zoom-in/zoom-out
719
731
  * intents. Programmatic, so — unlike a user drag/scroll — standalone mode
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * the build rootDir, and a `define` would need repeating across vite/vitest/
6
6
  * vite-node configs.
7
7
  */
8
- export declare const LIBRARY_VERSION = "0.8.0";
8
+ export declare const LIBRARY_VERSION = "0.8.1";
@@ -1,5 +1,5 @@
1
- import { A as ur, d as lr, R as zt, e as fr, m as dr, p as St, f as hr, j as pr, k as mr } from "./raster-pipeline-D1yeoJo2.js";
2
- import { ap as gr } from "./index-BGOblzWN.js";
1
+ import { A as ur, d as lr, R as zt, e as fr, m as dr, p as St, f as hr, j as pr, k as mr } from "./raster-pipeline-X2-mnFQx.js";
2
+ import { ap as gr } from "./index-D6R4z3Zs.js";
3
3
  import $t from "./index-CW1n5LdO.js";
4
4
  var Et;
5
5
  function h(e, t, n) {
package/llms.txt CHANGED
@@ -43,7 +43,7 @@ Programmatic/native bridge rule: `MapController.setLayers()` accepts normal func
43
43
  - `<om-behavior on="click|hover|drag|load|data-loaded" layer="..." action="...">` — declarative interaction. Built-in actions: `show-overlay`, `hide-overlay`, `show-tooltip`, `hide-tooltip`, `toggle-layer`, `set-pickable` (`{layer, pickable: true|false|"3d"}` — runtime picking/popup toggle, story-capturable; the per-layer popup on/off switch a viewer-facing export needs), `filter-layer`, `highlight-feature`, `zoom-to-feature`, `set-basemap`, `undo`, `redo`; scene/tool actions `set-lighting`, `set-terrain`, `set-clip-box` (`{min,max,invert?,highlight?}` / `{clear:true}`), `clip-box-edit` (`{editing}`), `export-region-3d` (`{target?, format?:"glb"|"b3dm"}` — what the draw widget's `export-3d` button emits), the draw actions `draw-mode` (`{target?:"sketch", mode:"point"|"line"|"polygon"|null}` — null exits drawing), `draw-commit`, `draw-cancel`, `draw-delete` (removes the last shape), `draw-clear`, `draw-config` (`{target?, autosave?, fillColor?, lineColor?}`) and `draw-save` (`{target?, format?:"download"|"file-system"|"both"}`) — every one of these drives the same store a `data="draw:<target>"` layer reads, so a custom toolbar can replace `<om-widget type="draw">` entirely; and the measure actions `measure-mode` (`{mode:"distance"|"area"|"volume"|null}`), `measure-units`, `measure-clear`, `measure-config` (`{profile?, baseSurface?, density?, swell?, shrink?, deadband?}`), `measure-flat-target-plane` (`{flat}`). One payload contract everywhere: `{ layer, target, feature, featureId, coordinate }`.
44
44
  - Undo/redo is built in: user-facing manifest changes (layer toggles, filter changes, basemap switches, element add/remove, drawn sketches) are recorded automatically — the manifest is the state. `<om-widget type="undo-redo">` renders the buttons; Cmd/Ctrl-Z, Shift-Cmd/Ctrl-Z, and Ctrl-Y work on any map (text inputs keep their native undo). Camera moves, hover effects, and story playback are deliberately NOT undo steps. Widget scripts: `ctx.history.canUndo/canRedo` with watch token `history`; `ctx.emit("undo")`/`ctx.emit("redo")`.
45
45
  - `<om-fallback>` — static no-JS fallback, direct child of `<om-map>` (one per map, no attributes, plain HTML content — links allowed). Shown ONLY where scripts never run (chat-app/email file previews — iOS QuickLook renders HTML attachments with JS off — file managers, sandboxed webviews); hidden automatically once the map boots. GOOD PRACTICE: include one on every complete page, especially pages that may be shared as a file. To PRODUCE a shareable single file, `npx @nika-js/onlymap export map.html` embeds every relative data/src/scenegraph URL as a data: URL (format detection preserved — the original extension rides a #name.ext fragment), pins relative library refs to the CDN, adds a generic om-fallback when missing, and warns when embedded data is heavy (>1 MB per file / >5 MB total) or when a source cannot be embedded (shapefile sidecars, COG Range streams, Zarr directories, {z}/{x}/{y} templates — those need hosting) ("This interactive map requires JavaScript — open this file in a web browser", plus a hosted-version link when one exists). Without one, the stylesheet shows a generic text-only banner. The gate is pure CSS (`om-map:not(:defined)` in onlymapjs.css) refined by the `scripting` media feature on 2023+ engines: with scripting DISABLED the fallback shows instantly; with scripting ENABLED it never flashes during a slow load and only surfaces after a ~4s grace with load-failure wording (blocked/unreachable bundle). The CSS must load without JS — a real `<link rel="stylesheet">` or inlined `<style>` on no-build pages; a bundler-emitted stylesheet is fine in npm projects.
46
- - PRINT LAYOUTS (`@nika-js/onlymap/cartograph`, separate lazy entry — the core bundle does not grow): `<om-cartograph size="A3" orientation="landscape">` is a standalone page measured in MILLIMETRES carrying `<om-frame>`s (live `<om-map>` with the frame's own camera, or `mode="static"` georeferenced rasters placed by `crs`+`corners`) plus cartographic furniture: `<om-legend for="...">` (rows DERIVED from the live map's own symbology incl. classified breaks; author literal `<om-legend-row>`s with `derived="false"`), `<om-scalebar>` (metric|imperial|nautical), `<om-north>`, `<om-graticule>` (4326/3857/UTM), `<om-shape>`, `<om-image>`, `<om-text>` with `{{title}}`/`{{date}}`/`{{frame.<id>.scale}}`/`{{atlas.<field>}}` tokens. `overview-of="<frame-id>"` draws a locator inset's footprint. `<om-atlas for="<frame-id>" layer="<layer-id>">` renders one page per feature (sequentially through ONE live map — WebGL context limits make cloned pages fail at scale) and exports a ZIP. Print via `page.print()` or `?print=1` (true page size via @page; live frames swap to print-DPI captures first), PNG via `renderCartograph(page, {dpi})` or `?export=png&dpi=300`. `bleed`/`crop-marks`/`safe-zone` (screen-only guide)/`flatten` are press-shop attributes; `cvd="deuteranopia|protanopia|tritanopia|achromatopsia"` simulates colour-vision deficiencies page-wide and `lintLegendColours()` flags collapsing palettes. Free plan: a small foot credit is injected — suppressed by any authored `om-text` crediting OnlyMap, or by a paid key on a live frame's map. Deep reference: docs/cartograph.md.
46
+ - PRINT LAYOUTS (`@nika-js/onlymap/cartograph`, separate lazy entry — the core bundle does not grow): `<om-cartograph size="A3" orientation="landscape">` is a standalone page measured in MILLIMETRES carrying `<om-frame>`s (live `<om-map>` with the frame's own camera, or `mode="static"` georeferenced rasters placed by `crs`+`corners`) plus cartographic furniture: `<om-legend for="...">` (rows DERIVED from the live map's own symbology incl. classified breaks; author literal `<om-legend-row>`s with `derived="false"`), `<om-scalebar>` (metric|imperial|nautical), `<om-north>`, `<om-graticule>` (4326/3857/UTM), `<om-shape>`, `<om-image>`, `<om-text>` with `{{title}}`/`{{date}}`/`{{frame.<id>.scale}}`/`{{atlas.<field>}}` tokens. `overview-of="<frame-id>"` draws a locator inset's footprint. A live frame caps the tilt of the map it adopts (`max-pitch` on `<om-map>`, also settable by hand for kiosk maps) at the steepest pitch its own box can still georeference — beyond it the frame's top edge reaches the horizon and it loses scale bar, north, graticule and export; the limit rises with zoom and with a wider box. `<om-atlas for="<frame-id>" layer="<layer-id>">` renders one page per feature (sequentially through ONE live map — WebGL context limits make cloned pages fail at scale) and exports a ZIP. Print via `page.print()` or `?print=1` (true page size via @page; live frames swap to print-DPI captures first), PNG via `renderCartograph(page, {dpi})` or `?export=png&dpi=300`. `bleed`/`crop-marks`/`safe-zone` (screen-only guide)/`flatten` are press-shop attributes; `cvd="deuteranopia|protanopia|tritanopia|achromatopsia"` simulates colour-vision deficiencies page-wide and `lintLegendColours()` flags collapsing palettes. Free plan: a small foot credit is injected — suppressed by any authored `om-text` crediting OnlyMap, or by a paid key on a live frame's map. Deep reference: docs/cartograph.md.
47
47
  - Animation: `transition="get-fill-color 800ms, get-radius 400ms"` on a layer GPU-animates prop changes (also smooths streaming updates via `get-position`). Camera: the `fly-to` action takes `center`/`zoom`/`pitch`/`bearing`/`duration` (e.g. `duration="2s"`) — use it in behaviors or `data-emit` buttons; `zoom-to-feature` also accepts `duration`.
48
48
  - Pull-model frame rendering (external video frameworks such as Remotion): mark the map `data-om-recording` (the determinism switch — instant camera, no transitions/gesture interrupts, byte-stable `snapshot()`), then per frame `story.seek(t, {interpolateCamera: true})` + `await mapEl.whenSettled()` + capture; the same frame is byte-identical across processes and orderings. Story effect verbs (fade/pulse/trace/populate) evaluate as pure functions of story time under the switch — a seek landing mid-trace renders the half-drawn outline; only effects dispatched OUTSIDE a story (behaviors, ctx.emit) snap to their end state. `onlymapjs record` remains the built-in push-model path; `@nika-js/onlymap-remotion` packages the pull-model path for Remotion.
49
49
  - Travel-map animation: a `trace` story step takes `follow` (camera rides the drawing tip along the path) and `easing="linear|ease-in|ease-out|ease-in-out"`; combine with a TripsLayer route + pins toggled by later steps, and export with `npx onlymapjs record`.
@@ -21,6 +21,10 @@
21
21
  "name": "bearing",
22
22
  "description": "Initial bearing in degrees."
23
23
  },
24
+ {
25
+ "name": "max-pitch",
26
+ "description": "Cap how far the user can tilt, in degrees. Applied to the controller, so an over-tilt is refused rather than clamped back. Absent = the renderer's default (60)."
27
+ },
24
28
  {
25
29
  "name": "basemap",
26
30
  "description": "Basemap: a registered preset name, \"maplibre\" (demo style), a style URL, or \"none\" (standalone canvas).",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nika-js/onlymap",
3
- "version": "0.8.0",
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.",
3
+ "version": "0.8.1",
4
+ "description": "Declarative deck.gl maps for HTML and React \u2014 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": {
7
7
  "access": "public"
@@ -123,7 +123,7 @@
123
123
  "build:types": "tsc -p tsconfig.build.json --emitDeclarationOnly",
124
124
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.e2e.json --noEmit && tsc -p cloud/workers/telemetry/tsconfig.json && tsc -p cloud/workers/examples/tsconfig.json",
125
125
  "test": "vitest run",
126
- "comment:e2e-smoke": "Release gate for rendered-pixel guarantees the unit suite can't see: the license-condition badge chrome (a red badge e2e shipped across 0.6.24 AND 0.6.25 because only vitest gated publish) and frame determinism. Deliberately tiny the full e2e suite stays a manual/CI concern.",
126
+ "comment:e2e-smoke": "Release gate for rendered-pixel guarantees the unit suite can't see: the license-condition badge chrome (a red badge e2e shipped across 0.6.24 AND 0.6.25 because only vitest gated publish) and frame determinism. Deliberately tiny \u2014 the full e2e suite stays a manual/CI concern.",
127
127
  "test:e2e:smoke": "playwright test e2e/deterministic-frames.spec.ts && playwright test e2e/examples.spec.ts -g \"attribution badge\"",
128
128
  "prepublishOnly": "node dev/tools/announce-release.mjs --check && npm run build && npm run test:e2e:smoke",
129
129
  "postpublish": "node dev/tools/announce-release.mjs",
@@ -142,7 +142,7 @@
142
142
  "dev:examples": "wrangler dev --config cloud/workers/examples/wrangler.toml",
143
143
  "gen:licenses": "node dev/gen-third-party-licenses.mjs"
144
144
  },
145
- "comment:deps": "This library ships a fully self-contained bundle in dist/ (verified: zero external bare imports), so it has NO runtime dependencies deck.gl, loaders.gl, MapLibre, Arrow, d3, acorn, etc. are build-time-only and get bundled by Vite. Keeping them here (not in dependencies) is what stops every consumer install from pulling ~250 MB it never uses.",
145
+ "comment:deps": "This library ships a fully self-contained bundle in dist/ (verified: zero external bare imports), so it has NO runtime dependencies \u2014 deck.gl, loaders.gl, MapLibre, Arrow, d3, acorn, etc. are build-time-only and get bundled by Vite. Keeping them here (not in dependencies) is what stops every consumer install from pulling ~250 MB it never uses.",
146
146
  "devDependencies": {
147
147
  "@deck.gl/aggregation-layers": "9.3.5",
148
148
  "@deck.gl/core": "9.3.5",
@@ -195,5 +195,5 @@
195
195
  "ws": "^8.21.0",
196
196
  "zustand": "^5.0.14"
197
197
  },
198
- "comment:deck-pin": "deck.gl/luma.gl devDeps are EXACT pins: they get BUNDLED into dist, and both libraries hard-throw on duplicate-version detection consumers that also ship their own deck.gl (nika-agent) must match these versions exactly. CONTRACT: the bundled deck.gl/luma.gl version is part of the release surface and only changes at the SemVer boundary a caret does NOT cross a MAJOR onlymap release (a 0.x MINOR while pre-1.0). Anything a caret floats (minor+patch once >=1.0; patch while 0.x) must NEVER move deck.gl, so a consumer can caret onlymap safely. Bumping deck is a breaking-coordination event, never a side effect of a minor/patch release or a reinstall."
198
+ "comment:deck-pin": "deck.gl/luma.gl devDeps are EXACT pins: they get BUNDLED into dist, and both libraries hard-throw on duplicate-version detection \u2014 consumers that also ship their own deck.gl (nika-agent) must match these versions exactly. CONTRACT: the bundled deck.gl/luma.gl version is part of the release surface and only changes at the SemVer boundary a caret does NOT cross \u2014 a MAJOR onlymap release (a 0.x MINOR while pre-1.0). Anything a caret floats (minor+patch once >=1.0; patch while 0.x) must NEVER move deck.gl, so a consumer can caret onlymap safely. Bumping deck is a breaking-coordination event, never a side effect of a minor/patch release or a reinstall."
199
199
  }
@@ -640,6 +640,7 @@ A separate lazy entry (`import "@nika-js/onlymap/cartograph"`; CDN: `https://unp
640
640
  ```
641
641
 
642
642
  - Frames: live (`<om-map>` child, the FRAME's camera attributes win) or `mode="static"` with `crs` + `corners` for a georeferenced raster. `overview-of="<frame-id>"` draws a locator footprint.
643
+ - A live frame caps its map's tilt at the steepest pitch the frame's own box can still georeference (past it the top edge reaches the horizon and the frame loses its scale bar, north, graticule and export). The limit rises with zoom and with a wider box; `max-pitch` on `<om-map>` is the same control, settable by hand for a kiosk map.
643
644
  - `<om-legend for>` derives rows from the live map's own symbology (classified breaks included); literal rows via `derived="false"` + `<om-legend-row>` children.
644
645
  - `<om-atlas for="<frame-id>" layer="<layer-id>">` renders one page per feature sequentially and exports a ZIP.
645
646
  - Output: `page.print()` / `?print=1` (PDF at page size), `renderCartograph(page, {dpi})` / `?export=png&dpi=300` (PNG). Press attributes: `bleed`, `crop-marks`, `safe-zone` (screen-only), `flatten`. `cvd="deuteranopia|…"` simulates colour-vision deficiency; `lintLegendColours()` flags collapsing palettes.