@nika-js/onlymap 0.2.1 → 0.2.2

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/llms.txt CHANGED
@@ -21,6 +21,7 @@ OnlyMapJS is NOT raw deck.gl and NOT generic HTML/JSX. The rules below are the d
21
21
  - `<om-widget type="legend|layer-switcher|basemap-switcher|zoom-controls|scale-bar|attribution|filter|vega-lite" position="bottom-right">` — static UI panels. No `type` + HTML + `<script type="om/widget">` = custom widget with `ctx` (`ctx.layers`, `ctx.data(id)`, `ctx.dataInViewport(id)`, `ctx.stats(id, field)`, `ctx.viewport`, `ctx.selection`, `ctx.emit(action, payload)`), `this.watch = ['data:<layerId>', 'viewport', 'selection', 'layers']`, `this.$(sel)`, `vegaEmbed`/`d3` as globals.
22
22
  - `<om-overlay id="..." anchor-from="selection">` — rich geo-anchored HTML (≤ ~20 per map). Anchors: `anchor="[lng, lat]"` (static), `anchor-from="selection"` (follows picks), or `anchor-layer="regions" anchor-feature-id="mission"` (anchored to a feature's own geometry — bbox center — no coordinates in markup; `{{field}}` interpolates that feature's attributes). `{{field}}` interpolates the picked feature HTML-escaped; `{{{field}}}` is raw (avoid). For labels on many features use `PopupLayer`, not overlays.
23
23
  - `<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`, `filter-layer`, `highlight-feature`, `zoom-to-feature`, `set-basemap`. One payload contract everywhere: `{ layer, target, feature, featureId, coordinate }`.
24
+ - `<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 ("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), so 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.
24
25
  - 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`.
25
26
  - `<om-story id="tour" autoplay loop interrupt="pause|ignore">` — a storyboard of `<om-step>` children. Each step: `action="..."` + payload attributes (same kebab-case rule as behaviors) + `duration`/`delay`/`parallel` timing. Steps REFERENCE layers/overlays by id (`layer=`/`target=`) — a step must NEVER contain elements (validation error). Control: `<om-widget type="player" story="tour">`, the story-play/story-pause/story-seek actions, or `storyEl.play()/pause()/seek(ms)`. Seeking restores initial state then applies steps before T; use declarative payloads (e.g. `action="toggle-layer" visible="true"`, not bare toggles) so scrubbing is deterministic. Effect verbs as bare step attributes: `<om-step fade layer="regions" duration="1s">` (opacity reveal — start the layer at `opacity="0"`), `pulse` (attention flash), `trace` (progressive draw — whole-layer needs a TripsLayer; add `feature-id="..."` to make ONE polygon/line draw itself on inside any layer, or use it from a click behavior for click-to-trace), `populate` (rows drop in one by one — ordered by the authored filter-field, a payload `field`, or data order).
26
27
  - Filtering: `filter-field="magnitude" filter-range="[4, 10]"` on a layer (GPU-side, live-updatable via the `filter-layer` action); pair with `<om-widget type="filter" layer="..." field="...">`.
@@ -93,7 +93,7 @@
93
93
  "references": [
94
94
  {
95
95
  "name": "README",
96
- "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/docs/../README.md"
96
+ "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/README.md"
97
97
  }
98
98
  ]
99
99
  },
@@ -1294,6 +1294,17 @@
1294
1294
  }
1295
1295
  ]
1296
1296
  },
1297
+ {
1298
+ "name": "om-fallback",
1299
+ "description": "Static fallback shown only when the library never boots — JS-disabled contexts like chat-app/email file previews (iOS QuickLook), file managers, sandboxed webviews. Direct child of <om-map>; hidden automatically once the map upgrades. Good practice on any page that may be shared as a file. Without one, the stylesheet shows a text-only default banner. Requires onlymapjs.css to load without JS (link tag / bundled / inlined).",
1300
+ "attributes": [],
1301
+ "references": [
1302
+ {
1303
+ "name": "README",
1304
+ "url": "https://github.com/NikaGeospatial/onlymapjs/blob/main/README.md"
1305
+ }
1306
+ ]
1307
+ },
1297
1308
  {
1298
1309
  "name": "om-behavior",
1299
1310
  "description": "Declarative event → action wiring. Every other attribute becomes a payload key (kebab→camel).",
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@nika-js/onlymap",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Interactive WebGL maps from declarative HTML — a custom-element manifest drives deck.gl: rendering, data loading, live updates, picking, widgets, and validation. No build step.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
9
9
  "author": "NikaGeospatial",
10
- "homepage": "https://github.com/NikaGeospatial/onlymapjs#readme",
10
+ "homepage": "https://www.nikaplanet.com/onlymap",
11
11
  "repository": {
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/NikaGeospatial/onlymapjs.git"
@@ -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, 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), or help with OnlyMapJS syntax, validation, widgets, data formats, testing, or publishing examples.
4
4
  ---
5
5
 
6
6
  # OnlyMapJS
@@ -65,9 +65,12 @@ Load the smallest reference needed for the task:
65
65
  - Live entity updates -> `wss://` stream with `key` and optional `source` decoder.
66
66
  - REST snapshot that changes over time -> `refresh="5s"`.
67
67
  - User sketching -> `data="draw:sketch"` layer plus `<om-widget type="draw" target="sketch">`.
68
+ - Page may travel as a file (shared, emailed, downloaded) or be embedded -> add an `<om-fallback>` child to `<om-map>`. Chat-app and email previews render HTML with JavaScript disabled (iOS QuickLook), so the map cannot boot there; the fallback is what recipients see instead. It is hidden automatically once the map boots. Good practice on every complete page — without one, the stylesheet shows a generic text-only banner.
68
69
 
69
70
  ## Output Expectations
70
71
 
71
72
  When creating a map page, output a complete runnable HTML file unless the user asks for a fragment. Include CSS only as needed for page sizing or custom widgets/overlays. Keep the first screen the usable map, not a landing page.
72
73
 
74
+ Include an `<om-fallback>` element (a short "this map requires JavaScript — open in a browser" message, optionally with a hosted-version link) as a direct child of `<om-map>` on any complete page. For the fallback to render in no-JS previews, `onlymapjs.css` must load without JavaScript — a real `<link rel="stylesheet">` or inlined `<style>`, not only a runtime `import` (bundler-emitted stylesheets are fine).
75
+
73
76
  When modifying an existing page, preserve the user's data URLs, layer ids, and styling unless the request requires changing them.
@@ -29,11 +29,17 @@ Use these patterns as starting points. Replace data URLs, layer ids, fields, cen
29
29
  pickable></om-layer>
30
30
  <om-widget type="legend" position="bottom-right" title="Layers"></om-widget>
31
31
  <om-widget type="zoom-controls" position="top-right"></om-widget>
32
+ <!-- Shown only where scripts never run (chat-app/email file previews) -->
33
+ <om-fallback>
34
+ <p>This interactive map requires JavaScript — open this file in a web browser.</p>
35
+ </om-fallback>
32
36
  </om-map>
33
37
  </body>
34
38
  </html>
35
39
  ```
36
40
 
41
+ Every complete-page pattern below should also carry an `<om-fallback>` (omitted for brevity) — see the good-practice rule in SKILL.md.
42
+
37
43
  ## Click Popup
38
44
 
39
45
  ```html
@@ -19,13 +19,13 @@ Static CDN page:
19
19
  <script type="module" src="https://esm.sh/@nika-js/onlymap@0.1.0"></script>
20
20
  ```
21
21
 
22
- If using MapLibre basemaps from a built package, include the CSS import or stylesheet. Standalone `basemap="none"` maps do not need the CSS.
22
+ Always include `onlymapjs.css` it carries the MapLibre basemap styles and the no-JS fallback rules (`<om-fallback>` / default banner). For the fallback to work in script-disabled previews it must load without JavaScript: a real `<link rel="stylesheet">` or inlined `<style>` on no-build pages (a bundler-emitted stylesheet is fine in npm projects).
23
23
 
24
24
  ## Elements
25
25
 
26
26
  ### `<om-map>`
27
27
 
28
- Root element. Children are layers, widgets, overlays, behaviors, and stories.
28
+ Root element. Children are layers, widgets, overlays, behaviors, stories, and an optional fallback.
29
29
 
30
30
  Common attributes:
31
31
 
@@ -243,6 +243,26 @@ Example:
243
243
  <om-behavior on="click" layer="quakes" action="show-overlay" target="detail"></om-behavior>
244
244
  ```
245
245
 
246
+ ### `<om-fallback>`
247
+
248
+ Static content shown only where scripts never run — chat-app/email file previews (iOS QuickLook), file managers, sandboxed webviews. Hidden automatically once the map boots. Good practice on every complete page, especially one that may be shared as a file.
249
+
250
+ Rules:
251
+
252
+ - Direct child of `<om-map>` (validation warns elsewhere), one per map.
253
+ - No attributes; plain HTML content — links work, so include a hosted-version URL when one exists.
254
+ - Without an `<om-fallback>`, the stylesheet shows a generic text-only banner instead.
255
+ - Requires `onlymapjs.css` to load without JavaScript (see Import Patterns above).
256
+
257
+ Example:
258
+
259
+ ```html
260
+ <om-fallback>
261
+ <p><strong>This interactive map requires JavaScript.</strong><br />
262
+ Open this file in a web browser, or visit <a href="https://example.com/map">the hosted version</a>.</p>
263
+ </om-fallback>
264
+ ```
265
+
246
266
  ### `<om-behavior>`
247
267
 
248
268
  Declarative event to action binding.