@nika-js/onlymap 0.1.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.
Files changed (77) hide show
  1. package/.vscode/onlymap.code-snippets +173 -0
  2. package/LICENSE.md +133 -0
  3. package/README.md +188 -0
  4. package/bin/onlymapjs.mjs +182 -0
  5. package/dist/Arrow.dom-7AXne1TU.js +5233 -0
  6. package/dist/actions.d.ts +30 -0
  7. package/dist/attribute-resolution.d.ts +73 -0
  8. package/dist/basemap-D95W0IIA.js +25203 -0
  9. package/dist/basemap.d.ts +72 -0
  10. package/dist/convert-arrow-schema-CvZ3cT5m.js +94 -0
  11. package/dist/csp-sandbox.d.ts +20 -0
  12. package/dist/ctx.d.ts +49 -0
  13. package/dist/d3-bundle.d.ts +218 -0
  14. package/dist/data-emit.d.ts +10 -0
  15. package/dist/data-layer.d.ts +150 -0
  16. package/dist/declarative-filter.d.ts +12 -0
  17. package/dist/dev-error-panel.d.ts +15 -0
  18. package/dist/draw-controller.d.ts +51 -0
  19. package/dist/draw.d.ts +102 -0
  20. package/dist/effects.d.ts +39 -0
  21. package/dist/elements/om-behavior.d.ts +13 -0
  22. package/dist/elements/om-layer.d.ts +11 -0
  23. package/dist/elements/om-map.d.ts +168 -0
  24. package/dist/elements/om-overlay.d.ts +82 -0
  25. package/dist/elements/om-step.d.ts +12 -0
  26. package/dist/elements/om-story.d.ts +67 -0
  27. package/dist/elements/om-widget.d.ts +29 -0
  28. package/dist/env.d.ts +41 -0
  29. package/dist/expr/cache.d.ts +28 -0
  30. package/dist/expr/compile.d.ts +27 -0
  31. package/dist/expr/errors.d.ts +10 -0
  32. package/dist/expr/full-js-block.d.ts +17 -0
  33. package/dist/expr/index.d.ts +12 -0
  34. package/dist/expr/output-type.d.ts +12 -0
  35. package/dist/expr/scale.d.ts +13 -0
  36. package/dist/expr/script-block.d.ts +16 -0
  37. package/dist/expr/whitelist.d.ts +28 -0
  38. package/dist/field-access.d.ts +24 -0
  39. package/dist/html-data.d.ts +25 -0
  40. package/dist/index-2v2NXF_n.js +435 -0
  41. package/dist/index-BFjXVHly.js +605 -0
  42. package/dist/index-C9w78NS9.js +4883 -0
  43. package/dist/index-CU-iOTdr.js +75292 -0
  44. package/dist/index-D74olQ9w.js +3907 -0
  45. package/dist/index-Do7hmHwi.js +1457 -0
  46. package/dist/index.d.ts +76 -0
  47. package/dist/ir-snapshot.d.ts +54 -0
  48. package/dist/ir.d.ts +66 -0
  49. package/dist/layer-registry.d.ts +27 -0
  50. package/dist/layers/popup-layer.d.ts +65 -0
  51. package/dist/onlymapjs.css +1 -0
  52. package/dist/onlymapjs.js +30 -0
  53. package/dist/onlymapjs.umd.cjs +8618 -0
  54. package/dist/parse-manifest.d.ts +19 -0
  55. package/dist/recordbatch-HRu0SMKp.js +4742 -0
  56. package/dist/runtime-core.d.ts +170 -0
  57. package/dist/selection.d.ts +31 -0
  58. package/dist/stats.d.ts +29 -0
  59. package/dist/table-accessors-DBjWgN0C.js +204 -0
  60. package/dist/template-interpolation.d.ts +6 -0
  61. package/dist/testing.d.ts +90 -0
  62. package/dist/timeline.d.ts +37 -0
  63. package/dist/validation.d.ts +22 -0
  64. package/dist/vega-loader.d.ts +22 -0
  65. package/dist/viewport-filter.d.ts +25 -0
  66. package/dist/widget-registry.d.ts +23 -0
  67. package/dist/widget-script.d.ts +1 -0
  68. package/dist/widgets/built-in.d.ts +1 -0
  69. package/dist/widgets/dom-utils.d.ts +4 -0
  70. package/llms.txt +43 -0
  71. package/onlymapjs.html-data.json +1688 -0
  72. package/package.json +111 -0
  73. package/skills/onlymapjs/SKILL.md +61 -0
  74. package/skills/onlymapjs/agents/openai.yaml +4 -0
  75. package/skills/onlymapjs/references/patterns.md +213 -0
  76. package/skills/onlymapjs/references/syntax.md +342 -0
  77. package/skills/onlymapjs/references/testing.md +126 -0
@@ -0,0 +1,173 @@
1
+ {
2
+ "!starter": {
3
+ "scope": "html",
4
+ "prefix": "!starter",
5
+ "description": "Full manifest: page shell + map + layer + click overlay + legend",
6
+ "body": [
7
+ "<!DOCTYPE html>",
8
+ "<html>",
9
+ "<head>",
10
+ " <meta charset=\"utf-8\" />",
11
+ " <title>${1:My map}</title>",
12
+ " <script type=\"module\">",
13
+ " import \"onlymapjs\";",
14
+ " import \"onlymapjs/onlymapjs.css\";",
15
+ " </script>",
16
+ "</head>",
17
+ "<body>",
18
+ "",
19
+ " <!-- validate → live error panel while you hand-author (strip for production) -->",
20
+ " <om-map center=\"[-122.42, 37.77]\" zoom=\"${2:11}\" basemap=\"maplibre\" validate>",
21
+ "",
22
+ " <!-- One data layer: type + data URL + accessors. pickable → behaviors can fire. -->",
23
+ " <om-layer id=\"${3:points}\" type=\"ScatterplotLayer\"",
24
+ " data=\"${4:../data/bikes.json}\"",
25
+ " label=\"${5:Points}\" color=\"${6:#e63946}\"",
26
+ " get-position=\"[\$lon, \$lat]\"",
27
+ " pickable></om-layer>",
28
+ "",
29
+ " <!-- Rich HTML popup — follows the last click via anchor-from=\"selection\" -->",
30
+ " <om-overlay id=\"${3:points}-detail\" anchor-from=\"selection\" visible=\"false\">",
31
+ " <div class=\"popup\"><strong>{{name}}</strong></div>",
32
+ " </om-overlay>",
33
+ " <om-behavior on=\"click\" layer=\"${3:points}\" action=\"show-overlay\"",
34
+ " target=\"${3:points}-detail\"></om-behavior>",
35
+ "",
36
+ " <!-- Built-in legend — reads label/color from each <om-layer> -->",
37
+ " <om-widget type=\"legend\" title=\"Layers\" position=\"top-right\"></om-widget>",
38
+ "",
39
+ " </om-map>",
40
+ "",
41
+ "</body>",
42
+ "</html>",
43
+ "$0"
44
+ ]
45
+ },
46
+
47
+ "!page": {
48
+ "scope": "html",
49
+ "prefix": "!page",
50
+ "description": "HTML page shell that loads OnlyMapJS from npm",
51
+ "body": [
52
+ "<!DOCTYPE html>",
53
+ "<html>",
54
+ "<head>",
55
+ " <meta charset=\"utf-8\" />",
56
+ " <title>${1:My map}</title>",
57
+ " <script type=\"module\">",
58
+ " import \"onlymapjs\";",
59
+ " import \"onlymapjs/onlymapjs.css\";",
60
+ " </script>",
61
+ "</head>",
62
+ "<body>",
63
+ "",
64
+ " $0",
65
+ "",
66
+ "</body>",
67
+ "</html>"
68
+ ]
69
+ },
70
+
71
+ "!map": {
72
+ "scope": "html",
73
+ "prefix": "!map",
74
+ "description": "<om-map> root with camera + basemap + validate",
75
+ "body": [
76
+ "<!-- validate → on-page error panel; basemap=\"maplibre\" needs no token -->",
77
+ "<om-map center=\"[-122.42, 37.77]\" zoom=\"${1:11}\" basemap=\"maplibre\" validate>",
78
+ "",
79
+ " $0",
80
+ "",
81
+ "</om-map>"
82
+ ]
83
+ },
84
+
85
+ "!layer": {
86
+ "scope": "html",
87
+ "prefix": "!layer",
88
+ "description": "ScatterplotLayer — points from a data URL",
89
+ "body": [
90
+ "<!-- data: JSON/GeoJSON/CSV URL, or use a <script type=\"application/json\"> child -->",
91
+ "<om-layer id=\"${1:points}\" type=\"ScatterplotLayer\"",
92
+ " data=\"${2:../data/bikes.json}\"",
93
+ " label=\"${3:Points}\" color=\"${4:#e63946}\"",
94
+ " get-position=\"[\$lon, \$lat]\"",
95
+ " pickable></om-layer>$0"
96
+ ]
97
+ },
98
+
99
+ "!geojson": {
100
+ "scope": "html",
101
+ "prefix": "!geojson",
102
+ "description": "GeoJsonLayer — polygons/lines from GeoJSON",
103
+ "body": [
104
+ "<om-layer id=\"${1:regions}\" type=\"GeoJsonLayer\"",
105
+ " data=\"${2:../data/regions.geojson}\"",
106
+ " label=\"${3:Regions}\" color=\"${4:#3388ff}\"",
107
+ " filled stroked pickable",
108
+ " get-line-color=\"[20,20,20]\"",
109
+ " line-width-min-pixels=\"2\"></om-layer>$0"
110
+ ]
111
+ },
112
+
113
+ "!overlay": {
114
+ "scope": "html",
115
+ "prefix": "!overlay",
116
+ "description": "<om-overlay> popup + click behavior wired to a layer",
117
+ "body": [
118
+ "<!-- {{field}} interpolates the picked feature; HTML-escaped by default -->",
119
+ "<om-overlay id=\"${1:detail}\" anchor-from=\"selection\" visible=\"false\">",
120
+ " <div class=\"popup\"><strong>{{${2:name}}}</strong></div>",
121
+ "</om-overlay>",
122
+ "<om-behavior on=\"click\" layer=\"${3:points}\" action=\"show-overlay\"",
123
+ " target=\"${1:detail}\"></om-behavior>$0"
124
+ ]
125
+ },
126
+
127
+ "!legend": {
128
+ "scope": "html",
129
+ "prefix": "!legend",
130
+ "description": "Built-in legend widget",
131
+ "body": [
132
+ "<om-widget type=\"legend\" title=\"${1:Layers}\" position=\"${2|top-right,top-left,bottom-right,bottom-left|}\"></om-widget>$0"
133
+ ]
134
+ },
135
+
136
+ "!draw": {
137
+ "scope": "html",
138
+ "prefix": "!draw",
139
+ "description": "Manual drawing: sketch layer + capture toolbar",
140
+ "body": [
141
+ "<om-layer id=\"${1:sketch}\" type=\"GeoJsonLayer\" data=\"draw:${1:sketch}\"",
142
+ " get-fill-color=\"[80, 140, 255, 90]\" get-line-color=\"[40, 90, 220]\"",
143
+ " point-radius-min-pixels=\"6\" line-width-min-pixels=\"3\" stroked filled pickable></om-layer>",
144
+ "<om-widget type=\"draw\" target=\"${1:sketch}\" position=\"${2|top-left,top-right,bottom-left,bottom-right|}\"",
145
+ " modes=\"${3:point line polygon}\" save=\"${4|both,download,file-system|}\"></om-widget>$0"
146
+ ]
147
+ },
148
+
149
+ "!behavior": {
150
+ "scope": "html",
151
+ "prefix": "!behavior",
152
+ "description": "Declarative <om-behavior> (click / hover / load / …)",
153
+ "body": [
154
+ "<om-behavior on=\"${1|click,hover,drag,load,data-loaded|}\" layer=\"${2:points}\"",
155
+ " action=\"${3|show-overlay,hide-overlay,show-tooltip,hide-tooltip,toggle-layer,filter-layer,highlight-feature,zoom-to-feature|}\"",
156
+ " target=\"${4:detail}\"></om-behavior>$0"
157
+ ]
158
+ },
159
+
160
+ "!inline-data": {
161
+ "scope": "html",
162
+ "prefix": "!inline-data",
163
+ "description": "Inline JSON data child (zero network requests — good for demos/tests)",
164
+ "body": [
165
+ "<script type=\"application/json\">",
166
+ "[",
167
+ " { \"id\": \"a\", \"name\": \"Alpha\", \"lon\": -122.42, \"lat\": 37.77, \"value\": 3 }",
168
+ " $0",
169
+ "]",
170
+ "</script>"
171
+ ]
172
+ }
173
+ }
package/LICENSE.md ADDED
@@ -0,0 +1,133 @@
1
+ # OnlyMap Commercial License Agreement
2
+
3
+ **Last Updated:** July 9, 2026
4
+
5
+ This OnlyMap Commercial License Agreement ("Agreement") governs access to and use of OnlyMap, published as the `OnlyMap` package or otherwise made available by the copyright holder ("Licensor"). By downloading, installing, accessing, or using the Software, you accept this Agreement.
6
+
7
+ If you are accepting this Agreement on behalf of a company or other legal entity, you represent that you have authority to bind that entity. In that case, "Licensee" and "you" refer to that entity.
8
+
9
+ ## 1. Definitions
10
+
11
+ "Software" means OnlyMap, including its compiled code, package files, documentation, examples, type definitions, updates, and other materials provided by Licensor under this Agreement.
12
+
13
+ "Application" means a website, application, service, internal tool, or other product created by Licensee that incorporates the Software and adds substantial functionality beyond the Software itself.
14
+
15
+ "Authorized Users" means Licensee's employees and contractors who need to access the Software solely for Licensee's benefit.
16
+
17
+ "Order Form" means an invoice, checkout receipt, subscription record, purchase order accepted by Licensor, or other written agreement that identifies Licensee's paid license, license scope, term, fees, support terms, or other commercial terms.
18
+
19
+ ## 2. License Grant
20
+
21
+ Subject to Licensee's compliance with this Agreement and any applicable Order Form, Licensor grants Licensee a limited, non-exclusive, non-transferable, non-sublicensable, revocable license during the applicable license term to:
22
+
23
+ 1. install and use the Software for Licensee's internal development, testing, staging, CI/CD, and production build workflows;
24
+ 2. use the Software to develop, operate, and maintain Applications;
25
+ 3. make backup, archival, and build-cache copies reasonably necessary for permitted use; and
26
+ 4. distribute the Software only as an inseparable, bundled, compiled, or minified part of an Application, solely to the extent necessary for end users to use that Application.
27
+
28
+ No ownership rights are transferred. Licensor and its licensors retain all right, title, and interest in and to the Software.
29
+
30
+ ## 3. Commercial Authorization Required
31
+
32
+ The Software is commercial proprietary software. Unless Licensor has granted Licensee a written evaluation license, Licensee may use the Software only if Licensee has purchased and maintains a valid commercial license from Licensor.
33
+
34
+ Access to an npm package, repository, package tarball, source archive, or build artifact does not by itself grant any rights beyond the rights expressly granted in this Agreement.
35
+
36
+ If an Order Form states usage limits, seat limits, application limits, domain limits, revenue limits, territory limits, term dates, or other license scope terms, Licensee must comply with those terms. If there is a conflict between this Agreement and an Order Form, the Order Form controls only for that conflict.
37
+
38
+ ## 4. npm and Package Access
39
+
40
+ Licensee may not share npm access tokens, registry credentials, private package access, license keys, or other access mechanisms with anyone other than Authorized Users.
41
+
42
+ Licensee may not mirror, republish, proxy, cache, or make the Software available through another package registry, CDN, repository, file server, or artifact store except for internal systems used solely by Authorized Users for permitted development, build, deployment, or archival purposes.
43
+
44
+ ## 5. Restrictions
45
+
46
+ Except as expressly permitted by this Agreement, Licensee may not:
47
+
48
+ 1. copy, modify, adapt, translate, fork, or create derivative works of the Software;
49
+ 2. reverse engineer, decompile, disassemble, or otherwise attempt to derive source code, underlying ideas, algorithms, or non-public interfaces of the Software, except to the limited extent applicable law prohibits this restriction;
50
+ 3. redistribute, sublicense, sell, rent, lease, lend, publish, upload, host, make available, or otherwise transfer the Software as a standalone library, SDK, package, component, service, or development tool;
51
+ 4. use the Software to create or offer a product or service that competes with the Software as a map library, visualization SDK, declarative mapping framework, or developer tool;
52
+ 5. remove, obscure, or alter proprietary notices, license notices, copyright notices, or attribution included with the Software;
53
+ 6. use the Software in violation of applicable law or third-party rights;
54
+ 7. bypass license controls, technical protection measures, usage limits, access controls, or package access restrictions; or
55
+ 8. permit any third party to do anything prohibited by this Agreement.
56
+
57
+ Licensee is responsible for all use of the Software by its Authorized Users and anyone who accesses the Software through Licensee.
58
+
59
+ ## 6. Application Distribution
60
+
61
+ Licensee may distribute Applications to its end users, customers, or internal users only if:
62
+
63
+ 1. the Application does not expose the Software as a standalone library, SDK, package, API, mapping framework, or developer tool;
64
+ 2. end users cannot reasonably extract and use the Software independently from the Application;
65
+ 3. Licensee does not grant end users any rights to modify, redistribute, sublicense, or reverse engineer the Software;
66
+ 4. Licensee's distribution complies with any Order Form limits; and
67
+ 5. Licensee remains responsible for all Software copies included in the Application.
68
+
69
+ This section permits ordinary browser delivery of bundled JavaScript that contains the Software as part of an Application. It does not permit publishing the Software itself to another registry, CDN, repository, or download site.
70
+
71
+ ## 7. Source Code
72
+
73
+ Licensor is not required to provide source code. If Licensor provides source code, readable JavaScript, TypeScript declarations, examples, or other human-readable materials, those materials are licensed only for the limited use expressly permitted by this Agreement and do not grant any open source, modification, redistribution, or sublicensing rights.
74
+
75
+ ## 8. Third-Party Software
76
+
77
+ The Software may include, depend on, interoperate with, or reference third-party software, open source packages, map data, map tiles, fonts, models, services, or other materials. Those third-party materials are governed by their own terms, and this Agreement does not limit any rights Licensee may have under applicable third-party licenses.
78
+
79
+ Licensee is responsible for obtaining and complying with all third-party licenses, API keys, service terms, map data rights, attribution requirements, and usage limits required for Licensee's Applications.
80
+
81
+ ## 9. Feedback
82
+
83
+ If Licensee provides suggestions, bug reports, feature requests, or other feedback, Licensee grants Licensor a perpetual, irrevocable, worldwide, royalty-free license to use that feedback without restriction or obligation.
84
+
85
+ ## 10. Updates and Support
86
+
87
+ Licensor may provide updates, patches, or new versions at its discretion. Unless an Order Form states otherwise, Licensor has no obligation to provide maintenance, support, uptime, compatibility commitments, or updates.
88
+
89
+ Updates are part of the Software and are governed by this Agreement unless Licensor provides different terms with the update.
90
+
91
+ ## 11. Fees and Taxes
92
+
93
+ Licensee must pay all fees stated in the applicable Order Form. Fees are non-refundable except as expressly stated in the Order Form or required by law.
94
+
95
+ Licensee is responsible for taxes, duties, levies, and similar governmental charges arising from its purchase or use of the Software, excluding taxes based on Licensor's net income.
96
+
97
+ ## 12. Term and Termination
98
+
99
+ This Agreement begins when Licensee first downloads, installs, accesses, or uses the Software and continues until terminated.
100
+
101
+ Licensor may terminate this Agreement immediately if Licensee breaches this Agreement or an Order Form. Upon termination or expiration, Licensee must stop using the Software and destroy or delete all copies in its possession or control, except that Licensee may retain archival copies required by law or ordinary backup systems if those copies are not used.
102
+
103
+ Sections that by their nature should survive termination will survive, including ownership, restrictions, payment obligations, warranty disclaimers, liability limits, and governing law.
104
+
105
+ ## 13. Disclaimer of Warranty
106
+
107
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE," WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, ACCURACY, AVAILABILITY, SECURITY, OR ERROR-FREE OPERATION.
108
+
109
+ ## 14. Limitation of Liability
110
+
111
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR WILL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR FOR LOST PROFITS, LOST REVENUE, LOST DATA, BUSINESS INTERRUPTION, OR PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF THOSE DAMAGES.
112
+
113
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR'S TOTAL LIABILITY ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT WILL NOT EXCEED THE AMOUNTS PAID BY LICENSEE TO LICENSOR FOR THE SOFTWARE DURING THE TWELVE MONTHS BEFORE THE EVENT GIVING RISE TO LIABILITY, OR USD 100 IF LICENSEE PAID NO AMOUNTS DURING THAT PERIOD.
114
+
115
+ ## 15. Export and Compliance
116
+
117
+ Licensee must comply with all applicable export control, sanctions, anti-corruption, privacy, data protection, and other laws applicable to Licensee's use of the Software.
118
+
119
+ ## 16. Assignment
120
+
121
+ Licensee may not assign or transfer this Agreement, any Order Form, or any rights or obligations under them without Licensor's prior written consent. Any attempted assignment in violation of this section is void.
122
+
123
+ ## 17. Governing Law
124
+
125
+ This Agreement is governed by the laws of the jurisdiction in which Licensor resides or is organized, without regard to conflict of law principles. The parties consent to the exclusive jurisdiction and venue of the courts located in that jurisdiction for disputes arising out of or relating to this Agreement.
126
+
127
+ ## 18. Entire Agreement
128
+
129
+ This Agreement, together with any applicable Order Form, is the entire agreement between Licensor and Licensee regarding the Software and supersedes all prior or contemporaneous agreements, proposals, or understandings about the Software.
130
+
131
+ ## 19. Contact
132
+
133
+ For licensing questions or requests for permissions beyond this Agreement, contact Licensor through the official repository, npm package page, website, or other distribution channel for the Software.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/NikaGeospatial/onlymapjs/main/onlymapbanner.png" alt="OnlyMapJS" width="100%">
3
+ </p>
4
+
5
+ # OnlyMapJS
6
+
7
+ **Interactive WebGL maps from plain HTML.** Write a declarative manifest — layers, widgets, popups, behaviors as custom elements — and OnlyMapJS drives [deck.gl](https://deck.gl) underneath: rendering, data loading, live updates, picking, and UI, with no build step and no imperative glue code.
8
+
9
+ ```html
10
+ <script type="module" src="https://esm.sh/@nika-js/onlymap"></script>
11
+
12
+ <om-map center="[-122.42, 37.77]" zoom="11" basemap="maplibre">
13
+ <om-layer id="quakes" type="ScatterplotLayer" data="./quakes.json"
14
+ label="Earthquakes" color="#b30000"
15
+ get-position="[$lon, $lat]"
16
+ get-fill-color="scale($magnitude, sequential, ['#fee8c8','#b30000'], domain=[0,7])"
17
+ get-radius="scale($magnitude, sqrt, [2, 18], domain=[0,7])"
18
+ radius-units="pixels" pickable></om-layer>
19
+
20
+ <om-widget type="legend" position="top-right"></om-widget>
21
+
22
+ <om-overlay id="detail" anchor-from="selection" visible="false">
23
+ <div><b>{{place}}</b> — M {{magnitude}}</div>
24
+ </om-overlay>
25
+ <om-behavior on="click" layer="quakes" action="show-overlay" target="detail"></om-behavior>
26
+ </om-map>
27
+ ```
28
+
29
+ That's a complete app: a no-token MapLibre basemap, data-driven colors and sizes, a legend, and a click-for-details popup. Edit any attribute on the live DOM and the map updates — the manifest *is* the state.
30
+
31
+ It's also designed to be written **by AI agents**: HTML is a reliable generation target, [`llms.txt`](llms.txt) teaches the format, and `OmMap.validate()` returns structured errors with actionable fixes — a real feedback loop instead of a blank canvas.
32
+
33
+ > ⚠️ **Status: v0.1.** Proprietary — commercial licensing terms are in [LICENSE.md](LICENSE.md); APIs may still move before 1.0.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ npm install @nika-js/onlymap
39
+ ```
40
+
41
+ Or with no build step at all, straight from a CDN:
42
+
43
+ ```html
44
+ <script type="module" src="https://esm.sh/@nika-js/onlymap"></script>
45
+ ```
46
+
47
+ Then `npx @nika-js/onlymap init` wires up VS Code IntelliSense and `!`-prefixed manifest snippets for your project. The library ships with 254 unit/behavioral tests and 12 Playwright GPU tests.
48
+
49
+ The [examples](https://github.com/NikaGeospatial/onlymapjs/tree/main/examples) are the best tour: widgets, behaviors & overlays, basemaps, columnar/Arrow data, manual drawing, 3D models, a live WebSocket ship feed, and a polled driver fleet.
50
+
51
+ ## The manifest
52
+
53
+ Five elements, one rule: **attributes are kebab-case versions of deck.gl props** (`radius-units` → `radiusUnits`), and `get-*` attributes are data-driven accessors.
54
+
55
+ | Element | Role |
56
+ |---|---|
57
+ | `<om-map>` | The map. `center`, `zoom`, `pitch`, `bearing`; `basemap="maplibre"` (default style or any style URL — no token) or `"none"` (standalone canvas); `validate` for a live on-page error panel. |
58
+ | `<om-layer>` | Any of **33 layer types** by name — all of deck.gl's core, geo, aggregation, and mesh layers (Scatterplot, GeoJson, Arc, Path, Heatmap, Hexagon, Trips, Tile, Tile3D, Scenegraph, …) plus the built-in `PopupLayer` for WebGL badges/labels at scale. `id` required; `label`/`color` feed the legend. |
59
+ | `<om-widget>` | UI panels. Built-ins: `legend`, `layer-switcher`, `zoom-controls`, `scale-bar`, `attribution`, `filter`, `draw`, `vega-lite` (live charts). Or write your own inline with HTML + a `<script type="om/widget">`. |
60
+ | `<om-overlay>` | Rich HTML anchored to a map location — a static `anchor="[lng, lat]"`, the current selection, or a feature's own geometry via `anchor-layer`/`anchor-feature-id`. `{{field}}` interpolates the picked feature, HTML-escaped by default. |
61
+ | `<om-behavior>` | Declarative interactions: `on="click|hover|drag|load|data-loaded"` → a named action. |
62
+ | `<om-story>` | A storyboard: `<om-step>` children fire actions on a timeline. Controlled by the `player` widget, behaviors, or `storyEl.play()/pause()/seek()`. |
63
+
64
+ ### Accessors without JavaScript
65
+
66
+ `get-*` attributes take a small, safe expression language — `$field` reads a datum field regardless of data shape (flat JSON, GeoJSON properties, or Arrow columns):
67
+
68
+ ```html
69
+ get-position="[$lon, $lat]"
70
+ get-radius="$population * 0.001"
71
+ get-fill-color="$value > 100 ? [255,0,0] : [0,128,255]"
72
+ get-fill-color="scale($depth, sequential, ['#ffffcc','#800026'], domain=[0,700])"
73
+ ```
74
+
75
+ Built-ins: `scale()` (types: `sequential`, `diverging`, `threshold`, `sqrt`, `log`, `pow` — explicit `domain=` required), `colorRamp()`, `clamp()`, `lerp()`, and `Math.*`. Multi-line accessors go in a `<script type="om/accessors">` block; genuinely arbitrary JS needs an explicit `js` opt-in on the layer. Untrusted (agent-written) expressions are safe by construction: the compiler is an AST whitelist, not an eval.
76
+
77
+ ### Data sources
78
+
79
+ | Source | Manifest | Notes |
80
+ |---|---|---|
81
+ | JSON / GeoJSON URL | `data="./points.json"` | flat arrays or FeatureCollections; `$field` works on both |
82
+ | Inline JSON | `<script type="application/json">` child | zero-request demos and tests |
83
+ | **Apache Arrow / GeoArrow** | `data="./big.arrow"` | points stay columnar (zero row objects on the render path); GeoArrow line/polygon geometry becomes GeoJSON features — trace, anchored cards, picking all work; zstd-compressed IPC supported; parsers lazy-load on first use |
84
+ | Columnar JSON | `{"columns": {"lon": [...], ...}}` | same columnar fast path without Arrow tooling |
85
+ | **CSV / TSV** | `data="./quakes.csv"` | parsed to typed columns (lazy ~48 KB chunk); numbers auto-typed, quoted fields intact |
86
+ | **Shapefile** | `data="./countries.shp"` | geometry + `.dbf` attributes joined into GeoJSON features (sidecars fetched with your auth config) |
87
+ | **KML** | `data="./tour.kml"` | placemarks → GeoJSON features; other formats plug in via `OmMap.registerFormat` |
88
+ | **WebSocket stream** | `data="wss://feed" key="id" flush="250ms" source="myFormat"` | upsert-by-key, burst coalescing, auto-reconnect; decode any format via `OmMap.registerSource` |
89
+ | **Polled REST snapshot** | `data="/api/fleet.json" refresh="5s"` | full-snapshot replace per poll; outages keep the last good data |
90
+ | **Draw store** | `data="draw:sketch"` | live in-memory GeoJSON feature store written by `<om-widget type="draw" target="sketch">` |
91
+
92
+ Private endpoints: `OmMap.configureData({ headers, credentials, fetch })` — applied to every fetch including refreshes. Credentials stay out of markup by design. Full guide: [docs/live-data.md](docs/live-data.md).
93
+
94
+ ### Interaction
95
+
96
+ Ten built-in actions wire to picks, widget buttons (`data-emit`), or script (`ctx.emit`) with one shared payload contract: `show-overlay`, `hide-overlay`, `show-tooltip`, `hide-tooltip`, `toggle-layer`, `highlight-feature`, `zoom-to-feature`, `filter-layer`, `zoom-in`, `zoom-out` — plus `OmMap.registerAction` for your own.
97
+
98
+ **Animation:** camera moves accept a duration — `map.flyTo(coords, zoom, { duration: 1200, curve: true })`, or the `fly-to` action (`center`/`zoom`/`pitch`/`bearing`/`duration`) from any behavior or button; `prefers-reduced-motion` is honored (moves become instant, final state identical). Per-prop GPU transitions via the `transition` attribute: `transition="get-fill-color 800ms"` fades color changes; on a streaming layer, `transition="get-position 300ms"` makes entities glide between updates.
99
+
100
+ **Map stories:** a guided tour as markup — `<om-story>` holds `<om-step>` children that fire the same actions behaviors use, on a timeline (`duration`, `delay`, `parallel`); the built-in `type="player"` widget gives play/pause/scrub, seeking restores the scene's captured initial state, one story is active per map, and grabbing the map pauses playback. Effect verbs — `fade`, `pulse`, `trace` (progressive TripsLayer draw-on; with `feature-id`, a single polygon draws itself on inside its own layer), and `populate` (rows drop in one by one via a GPU filter sweep) — work as step shorthands or plain actions. The story is a sibling that references layers by id — delete it and the map is unchanged. Guide: [docs/stories.md](docs/stories.md).
101
+
102
+ GPU filtering is declarative — `filter-field="magnitude" filter-range="[4,10]"` — updates live from the built-in `filter` slider widget, and widget statistics stay coherent with what the map shows (`ctx.stats` respects the active filter unless you opt out).
103
+
104
+ ### Widgets get a real runtime API
105
+
106
+ Custom widget scripts receive `ctx`: layer metadata, `viewport` (bounds/zoom/project), the current `selection`, `emit()`, and data access — `ctx.data(id)`, `ctx.dataInViewport(id)`, `ctx.stats(id, field)` (count/min/max/mean/stddev/percentiles/histogram, viewport-scoped on request). Declare `watch` tokens (`data:quakes viewport selection layers`) and the runtime re-renders you only when relevant state changes. `vegaEmbed` and `d3` are available as globals for charts.
107
+
108
+ ## Editor IntelliSense
109
+
110
+ `onlymapjs.html-data.json` (generated from the layer registry — `npm run gen:html-data`) gives autocomplete and hover docs for every `om-*` element and attribute in VS Code and any editor speaking the [html-customData](https://github.com/microsoft/vscode-custom-data) format:
111
+
112
+ ```bash
113
+ npx @nika-js/onlymap init
114
+ ```
115
+
116
+ That opt-in command updates `.vscode/settings.json` and copies the `!`-prefixed manifest snippets into `.vscode/onlymap.code-snippets`. It never runs automatically during install.
117
+
118
+ ```jsonc
119
+ // .vscode/settings.json
120
+ { "html.customData": ["./node_modules/@nika-js/onlymap/onlymapjs.html-data.json"] }
121
+ ```
122
+
123
+ The package also ships `!`-prefixed manifest snippets (`node_modules/@nika-js/onlymap/.vscode/onlymap.code-snippets`) — type `!starter`, `!map`, `!layer`, `!draw`, etc. to scaffold a well-formed element.
124
+
125
+ ## LLM Skill
126
+
127
+ The npm package and public mirror include a portable Skill at `skills/onlymapjs`. Skill-aware agents can install that folder to learn the OnlyMapJS manifest syntax, authoring patterns, and validation workflow instead of treating the library like raw deck.gl.
128
+
129
+ With the Vercel Labs `skills` CLI, install it from the public GitHub repo:
130
+
131
+ ```bash
132
+ npx -y skills add NikaGeospatial/onlymapjs --skill onlymapjs --agent codex
133
+ ```
134
+
135
+ Or install globally for Codex:
136
+
137
+ ```bash
138
+ npx -y skills add NikaGeospatial/onlymapjs --skill onlymapjs --agent codex --global
139
+ ```
140
+
141
+ To inspect it without installing:
142
+
143
+ ```bash
144
+ npx -y skills add NikaGeospatial/onlymapjs --list
145
+ ```
146
+
147
+ ## Validation — the feedback loop
148
+
149
+ ```js
150
+ const result = OmMap.validate(manifestHtml);
151
+ // { valid, errors: [{ severity, element, attribute, message, fix }], warnings: [...] }
152
+ ```
153
+
154
+ Exhaustive (every problem in one pass) and prescriptive (each entry carries a `fix` instruction). The same pass runs live via the `validate` attribute, rendering an on-page error panel with click-to-locate. Runtime errors (crashing accessors, bad props) are formatted into the same shape. Attributes for not-yet-implemented features warn instead of failing silently.
155
+
156
+ ## Testing your map pages
157
+
158
+ Uniquely for a WebGL map library, pages built with OnlyMapJS are testable in plain vitest/jest — no browser, no GPU:
159
+
160
+ ```js
161
+ const h = await mountForTest(myPageHtml); // headless: real projection math, no WebGL
162
+ await h.pick({ layer: "quakes", featureId: "q1" }); // same code path as a real click
163
+ expect(overlay.shadowRoot.textContent).toContain("M 6.5");
164
+ ```
165
+
166
+ Plus `OmMap.snapshotIR(html)` to lock down what a manifest *means* in a snapshot test, and `await mapEl.ready` / the `om-map-ready` event to de-flake browser e2e tests. Full guide: [docs/testing.md](docs/testing.md).
167
+
168
+ ## 3D
169
+
170
+ `ScenegraphLayer` instances glTF/GLB models at coordinates (no three.js, no loader wiring), `Tile3DLayer` consumes OGC 3D Tiles, and the camera tilts via `pitch`/`bearing` attributes. Converting IFC/CAD upstream: [docs/3d-assets.md](docs/3d-assets.md).
171
+
172
+ ## Programmatic surface
173
+
174
+ - **`OmMap.*`** — `validate`, `snapshotIR`, `registerLayer`, `registerWidget`, `registerAction`, `registerSource`, `registerFormat`, `configureData`, `getLayerSchema`
175
+ - **On a `<om-map>` element** — `ready` (promise), `flyTo(coords, zoom?)`, `setLayerVisible(id, bool)`, `getLayers()`, `emit(action, payload)`; `document.querySelector("om-map")` is fully typed
176
+ - **Testing** — `mountForTest`, and imports are SSR-safe (importing in Node/jsdom never touches browser globals)
177
+
178
+ ## Not implemented yet (honestly)
179
+
180
+ Mapbox GL basemaps, depth-interleaved 3D compositing, globe projection, SSE transport, multi-field filters, `dblclick` behaviors, the `transform` data pipeline, and the React adapter / typed builder.
181
+
182
+ ## Going deeper
183
+
184
+ | | |
185
+ |---|---|
186
+ | [docs/testing.md](docs/testing.md) · [docs/live-data.md](docs/live-data.md) · [docs/3d-assets.md](docs/3d-assets.md) · [docs/stories.md](docs/stories.md) | Consumer guides |
187
+ | [llms.txt](llms.txt) | The agent-facing quick reference |
188
+ | `skills/onlymapjs` | Installable LLM skill for OnlyMapJS authoring |