@nika-js/onlymap 0.6.13 → 0.6.15

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 (36) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{LercDecode.es-DB1mYTrm.js → LercDecode.es-BWmtr6fp.js} +1 -1
  3. package/dist/attribute-resolution.d.ts +2 -0
  4. package/dist/{basemap-CDp9EsvL.js → basemap-DQeUv-pk.js} +1 -1
  5. package/dist/clip-box-controller.d.ts +1 -1
  6. package/dist/clip-box.d.ts +0 -32
  7. package/dist/data-layer.d.ts +0 -17
  8. package/dist/effects.d.ts +1 -0
  9. package/dist/elements/om-map.d.ts +0 -20
  10. package/dist/elements/om-story.d.ts +0 -18
  11. package/dist/expr/errors.d.ts +3 -0
  12. package/dist/field-access.d.ts +10 -0
  13. package/dist/geodesy.d.ts +11 -0
  14. package/dist/{geoparquet-CI3o8X5-.js → geoparquet-DsYXvvEo.js} +1 -1
  15. package/dist/{index-Dio4lUCZ.js → index-BTJy4dWy.js} +1 -1
  16. package/dist/{index-CnKC1yuV.js → index-Bnkk4jcp.js} +26197 -26173
  17. package/dist/{index-Bue-53Xo.js → index-CbHslg3u.js} +1 -1
  18. package/dist/{index-BJh0t_nt.js → index-DMRuqiXV.js} +2 -2
  19. package/dist/{index-DMu0qL9C.js → index-gMV11Nr5.js} +1 -1
  20. package/dist/layer-registry.d.ts +10 -0
  21. package/dist/layers/marker-icons.d.ts +0 -2
  22. package/dist/legend-spec.d.ts +1 -6
  23. package/dist/{lerc-B1LFm9ra.js → lerc-Cw1YMyb0.js} +2 -2
  24. package/dist/onlymap.standalone.js +33282 -33258
  25. package/dist/onlymapjs.js +1 -1
  26. package/dist/programmatic.d.ts +0 -16
  27. package/dist/{raster-DQ1dS7mZ.js → raster-BJaQlAzq.js} +2 -2
  28. package/dist/{raster-pipeline-mXzwFf0A.js → raster-pipeline-BCVaME9y.js} +1 -1
  29. package/dist/react.js +215 -232
  30. package/dist/runtime-core.d.ts +37 -0
  31. package/dist/site-placement.d.ts +0 -2
  32. package/dist/version.d.ts +1 -1
  33. package/dist/{zarr-BSoVUvcs.js → zarr-C6xeWGwX.js} +2 -2
  34. package/package.json +1 -1
  35. package/skills/onlymapjs/SKILL.md +1 -1
  36. package/skills/onlymapjs/references/syntax.md +2 -2
package/CHANGELOG.md CHANGED
@@ -8,6 +8,19 @@ Note: npm collapsed a few closely-spaced releases — the GPX/FlatGeobuf (0.5.4)
8
8
  and GeoParquet (0.5.5) work shipped to npm together as **0.5.6**, so npm's
9
9
  version list jumps 0.5.3 → 0.5.6. Each logical version is listed here regardless.
10
10
 
11
+ ## 0.6.15 — 2026-08-21
12
+
13
+ ### Changed
14
+ - **Smoother interactive dragging on complex maps.** Dragging the measure or clip-box gizmos (and any other live animation) now rebuilds the scene once per frame instead of up to ~10 times — the same visual result with a fraction of the work, which shows up as steadier frame rates and lower battery drain on layer-heavy maps, especially in mobile WebViews.
15
+
16
+ ## 0.6.14 — 2026-08-21
17
+
18
+ ### Fixed
19
+ - **Dashed lines render again.** `dash="[4, 2]"` had been drawing solid lines since 0.6.2 — the terrain patch merge was unintentionally stripping every layer's extensions on flat maps (issue #36).
20
+ - **Filters visibly apply again on maps without terrain** — same underlying cause as the dash fix. Filter widgets and statistics were always correct; the map itself just wasn't hiding filtered-out features.
21
+ - **Maps built in code now match maps built in HTML.** Built-in defaults apply (e.g. BIM models are clickable by default), `{z}/{x}/{y}` tile URLs load as tiles instead of failing, legends generate automatically, and `classifyBy` now works in React.
22
+ - **`snap="false"` and `clip="false"` now opt a layer out**, matching what validation already accepted; `snap="off"` / `clip="off"` unchanged.
23
+
11
24
  ## 0.6.13 — 2026-08-20
12
25
 
13
26
  ### Fixed
@@ -19,7 +19,7 @@ async function v(N = {}) {
19
19
  if (n) {
20
20
  const { createRequire: I } = await import(
21
21
  /*webpackIgnore:true*/
22
- "./lerc-B1LFm9ra.js"
22
+ "./lerc-Cw1YMyb0.js"
23
23
  ).then((g) => g._);
24
24
  var O = I(import.meta.url);
25
25
  }
@@ -34,6 +34,8 @@ export declare const FILTER_ATTRS: Set<string>;
34
34
  * `PathStyleExtension` (already bundled for DataFilterExtension), which only
35
35
  * applies to layers that stroke a path.
36
36
  */
37
+ /** `data-emit`-style attribute name → camelCase (shared by om-map's payload reads and om-story's step parsing — both DOM-lane, one regex). */
38
+ export declare function kebabToCamel(name: string): string;
37
39
  export declare const DASH_ATTRS: Set<string>;
38
40
  /** Classified symbology (spec: issue #12; src/classify.ts) — universal layer attributes like `filter-*`, resolved where the data is in hand (parse-manifest / descriptorToIR), never per-schema deck props. */
39
41
  export declare const CLASSIFY_ATTRS: Set<string>;
@@ -1,4 +1,4 @@
1
- import { C as ny, L as sy, M as oy, m as ay, c as ka, z as oc, a as Sd, G as sm, V as ly, W as cy, b as uy, g as hy, d as Vu, f as Ed, e as dy, l as py, u as fy, D as Qf, h as my } from "./index-CnKC1yuV.js";
1
+ import { C as ny, L as sy, M as oy, m as ay, c as ka, z as oc, a as Sd, G as sm, V as ly, W as cy, b as uy, g as hy, d as Vu, f as Ed, e as dy, l as py, u as fy, D as Qf, h as my } from "./index-Bnkk4jcp.js";
2
2
  const Cd = Math.PI / 180, gy = 180 / Math.PI;
3
3
  function em(Pe, Q = 0) {
4
4
  const me = Math.min(180, Pe) * Cd;
@@ -44,7 +44,7 @@ export declare class ClipBoxController {
44
44
  * `syncVisuals()` so `handleGizmoDrag` can drive this every mousemove
45
45
  * frame from its own LOCAL `grab.liveBox` without going anywhere near
46
46
  * `core.setClipBox`/DOM attributes (see that method's own doc comment).
47
- * `patchAnimatedProps` alone is cheap and frame-rate-safe; this is the
47
+ * `patchAnimatedProps` is cheap and frame-rate-safe (patches within one JS turn coalesce into a single scene rebuild); this is the
48
48
  * same reason `measure-controller.ts`'s volume gizmo redraws through
49
49
  * `patchAnimatedProps` on every drag frame instead of writing anything
50
50
  * to the DOM until the gesture actually ends.
@@ -1,35 +1,3 @@
1
- /**
2
- * Clip box (spec: issue #34 §"Cutting / Clipping", tier 2 — the geometric
3
- * complement to issue #26's clip PLANE). A real oriented... well, AXIS-
4
- * ALIGNED (v1 scope, confirmed explicitly — rotation is a documented
5
- * follow-up, not this) 3D box: geometry outside it is discarded (or, in
6
- * `highlight` mode, dimmed rather than removed — "non-destructive"), so a
7
- * dense scene (a BIM model, a point cloud, a city block) can be cut open to
8
- * see what's inside.
9
- *
10
- * Map-level scene state (spec: `<om-map clip-box-min="..." clip-box-max="..."
11
- * clip-box-invert clip-box-highlight>`), same architecture as `lighting`/
12
- * `terrain`: attribute-backed, undoable, live-editable, applied to every
13
- * layer by default with a per-layer `clip="off"` escape hatch — see
14
- * `applyClipBox`'s own doc comment for why that default (not opt-in) is
15
- * the right one here specifically.
16
- *
17
- * Three corrections from the original design review, all reflected below:
18
- * 1. "Outside the box" is `!inside` (De Morgan's law on the AND of 6
19
- * half-spaces) — NOT a literal OR of 6 flipped half-space tests, which
20
- * would (incorrectly) require re-deriving 6 new inequalities; negating
21
- * the single boolean `inside` result is simpler and exactly equivalent.
22
- * 2. Plane/box bounds are expressed in deck's COMMON SPACE (via
23
- * `Layer#projectPosition`, the SAME mechanism the built-in `ClipExtension`
24
- * uses for its own 2D bounds) — never raw lng/lat — so one authored box
25
- * clips layers in different coordinate systems (geographic, meter-offset
26
- * BIM placements, etc.) correctly.
27
- * 3. Picking (including the `pickable:'3d'` depth pass) is covered for
28
- * free: `discard` inside `fs:DECKGL_FILTER_COLOR` is the SAME shader
29
- * stage deck's own picking pass reuses — no separate picking-specific
30
- * code needed, confirmed by the built-in `ClipExtension` doing nothing
31
- * extra for picking either.
32
- */
33
1
  import { LayerExtension } from "@deck.gl/core";
34
2
  import type { Layer } from "@deck.gl/core";
35
3
  import type { LayerIR } from "./ir";
@@ -1,20 +1,3 @@
1
- /**
2
- * Data Layer (spec: "Module Breakdown / Data Layer").
3
- * Fetches the `data` attribute URL and caches the parsed response by URL, or
4
- * (Phase 3) reads inline JSON from a child `<script type="application/json">`
5
- * synchronously with no fetch/cache involved. Full request-generation/
6
- * AbortController handling (Q6: "Async data loading & the reconcile race") is
7
- * still a minimal, safe subset here — a per-URL fetch generation so a
8
- * superseded request can't clobber a newer one — not the full machinery.
9
- *
10
- * Columnar (spec: "Columnar / GeoArrow Ingestion"): the Data Layer is where
11
- * columnar sources become `ColumnarData` — Arrow IPC files (`.arrow`,
12
- * lazy-importing apache-arrow so it never weighs on the eager bundle) and
13
- * column-oriented JSON (`{ columns: { field: [...] } }`, inline or fetched).
14
- * Columnar data is handed to deck.gl as-is (zero row materialization on the
15
- * render path); row objects are materialized lazily and memoized only when
16
- * a row-consuming surface (ctx.data, picking, highlight-by-id) asks.
17
- */
18
1
  import type { Shape, ColumnarData, LayerData } from "./ir";
19
2
  export declare function isColumnar(data: LayerData): data is ColumnarData;
20
3
  /** `Array` as-is, or a FeatureCollection's `.features`, or a lone object wrapped in an array. */
package/dist/effects.d.ts CHANGED
@@ -13,6 +13,7 @@ import type { RuntimeCore } from "./runtime-core";
13
13
  export declare function traceProgress(t01: number, t0: number, t1: number): number;
14
14
  /** Oscillates 1 → low → 1 per cycle (cosine), ending exactly at 1 for whole cycles. */
15
15
  export declare function pulseOpacity(t01: number, cycles: number, low?: number): number;
16
+ export declare function prefersReducedMotion(): boolean;
16
17
  export interface LayerEffect {
17
18
  /** t01 ∈ [0, 1] → the plain-prop patch for this frame. */
18
19
  frame(t01: number): Record<string, unknown>;
@@ -1,22 +1,3 @@
1
- /**
2
- * <om-map> — spec: "Manifest Format / Core elements", "Architecture Layers",
3
- * "Runtime Context API", "Reactivity — the watch declaration".
4
- * Light DOM (spec: "DOM Model — Shadow vs. Light"): hosts the deck.gl canvas
5
- * (inside an internal mount div) and the <om-layer>/<om-widget> children
6
- * as normal siblings.
7
- *
8
- * Reconciler: full reparse per reconcile (still no diff-skipping of unchanged
9
- * DOM — accessor-level memoization/fingerprinting does the real work, see
10
- * attribute-resolution.ts / runtime-core.ts), microtask-batched (spec:
11
- * "MutationObserver burst batching") so N mutations in one synchronous burst
12
- * collapse into a single reconcile. No basemap adapter yet (Phase 6).
13
- *
14
- * Phase 4: also the widget pub-sub hub — maintains the live layer-IR
15
- * registry (for ctx.layers/data/stats), the current selection, and notifies
16
- * registered widgets per their `watch` tokens (spec: "Reactivity"). This
17
- * internal registration API (registerWidgetInternal/unregisterWidgetInternal/
18
- * emit) is consumed by OmWidgetElement, not part of the public package API.
19
- */
20
1
  import { HTMLElementBase } from "../env";
21
2
  import { type RuntimeContext } from "../ctx";
22
3
  import { type LightingIR } from "../scene-lighting";
@@ -73,7 +54,6 @@ export declare class OmMapElement extends HTMLElementBase {
73
54
  /** Dedup guard for the no-terrain-for-elevation error — same shape as `warnedApproximatePlacement`. */
74
55
  private erroredNoTerrainForElevation;
75
56
  private readyFired;
76
- private visibleSizeChecked;
77
57
  /** Custom-state holder for the `om-collapsed` height-floor marker — see applyHeightFloor. */
78
58
  private internals;
79
59
  private resolveReady;
@@ -1,21 +1,3 @@
1
- /**
2
- * <om-story> — the storyboard element (spec: "Map Stories"). A story is a
3
- * time-sequenced action dispatcher: where <om-behavior> maps event →
4
- * action, a story maps time → action, through the exact same action-payload
5
- * contract (mapEl.emit). It owns the clock; nothing owns the story — the
6
- * player widget is optional chrome that emits story-play/pause/seek.
7
- *
8
- * Composability guarantee (spec): steps reference layers/overlays by id and
9
- * never contain them; delete the story and the map is byte-for-byte the
10
- * same map.
11
- *
12
- * Scrub model (spec, v1): seek(T) = restore captured initial state, then
13
- * re-fire the FINAL state of every step starting ≤ T (instant — payload
14
- * duration overridden to 0). Step-granularity; mid-step interpolation is
15
- * deferred. Initial state is captured on first play from the attributes the
16
- * built-in-action steps will touch (statically computable from payloads)
17
- * plus the camera; custom-action steps are replay-only (warned once).
18
- */
19
1
  import { HTMLElementBase } from "../env";
20
2
  export type StoryState = "idle" | "playing" | "paused" | "ended";
21
3
  export declare class OmStoryElement extends HTMLElementBase {
@@ -8,3 +8,6 @@ export declare class CompileError extends Error {
8
8
  readonly fix: string;
9
9
  constructor(message: string, fix: string);
10
10
  }
11
+ import type { Program } from "estree";
12
+ /** Shared acorn container parse for both accessor-block flavors — one grammar, one error shape; only the fix hint names the block. */
13
+ export declare function parseProgram(blockText: string, blockLabel: string): Program;
@@ -22,3 +22,13 @@ export declare function matchesFeatureId(row: unknown, featureId: string, shape:
22
22
  * asRows view — the Tier-2 rule, stated once here instead of at each caller.
23
23
  */
24
24
  export declare function findRowIndexById(data: LayerData, featureId: string, shape: Shape): number;
25
+ /**
26
+ * Shape-less named-field read: a GeoJSON Feature's field lives under
27
+ * `properties`, a flat row carries it directly — probe both, `in`-checked so
28
+ * an explicit null/undefined stored under properties still wins. For callers
29
+ * that have no `Shape` in hand (the Tracking layer pair); everything with a
30
+ * shape should use `getField`.
31
+ */
32
+ export declare function readNamedField(row: unknown, field: string): unknown;
33
+ /** Recursively walks GeoJSON `coordinates` (Point/LineString/Polygon/Multi*) collecting every [lng, lat] vertex. */
34
+ export declare function collectCoordinates(coordinates: unknown, out: [number, number][]): void;
package/dist/geodesy.d.ts CHANGED
@@ -23,6 +23,15 @@ export type LngLat = [number, number];
23
23
  export declare function distanceMeters(a: LngLat, b: LngLat, radius?: number): number;
24
24
  /** Total haversine length of a polyline in meters (0 for < 2 points). */
25
25
  export declare function pathLengthMeters(points: LngLat[], radius?: number): number;
26
+ /**
27
+ * Web Mercator ground resolution — meters per screen pixel at a latitude and
28
+ * zoom. The one formula four controllers used to carry inline (draw close
29
+ * guard, clip-box handle radius, measure hover tolerance, filter histogram).
30
+ * `minCosLat` clamps the cosine near the poles (the clip-box gizmo needs a
31
+ * floor so handle hit radii stay finite above ~84°); the default 0 keeps the
32
+ * exact classic formula.
33
+ */
34
+ export declare function metersPerPixel(latitude: number, zoom: number, minCosLat?: number): number;
26
35
  export interface PathSample {
27
36
  position: LngLat;
28
37
  /** Cumulative distance (m) from the path's start. */
@@ -42,6 +51,8 @@ export interface PathSample {
42
51
  */
43
52
  export declare function resamplePath(points: LngLat[], count: number): PathSample[];
44
53
  export declare function resamplePathWithVertices(points: LngLat[], count: number): PathSample[];
54
+ /** Drop a trailing vertex that duplicates the first (a closed ring → open list). */
55
+ export declare function openRing(ring: LngLat[]): LngLat[];
45
56
  /**
46
57
  * Spherical polygon area in m² via the Chamberlain–Duquette line integral (the
47
58
  * exact index form Turf's `ringArea` uses, so results match Turf's fixtures).
@@ -1,4 +1,4 @@
1
- import { r as p, n as d } from "./index-CnKC1yuV.js";
1
+ import { r as p, n as d } from "./index-Bnkk4jcp.js";
2
2
  function g(t) {
3
3
  if (t == null) return !0;
4
4
  const e = t, n = e.id?.code;
@@ -1,4 +1,4 @@
1
- import { ae as _t, af as Ct } from "./index-CnKC1yuV.js";
1
+ import { ae as _t, af as Ct } from "./index-Bnkk4jcp.js";
2
2
  function Yt(e, r, t = 2, i, o = "xy") {
3
3
  const s = r && r.length, l = s ? r[0] * t : e.length;
4
4
  let c = Ut(e, 0, l, t, !0, i && i[0], o);