@honua/app-platform 0.0.20-alpha.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 (840) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +11 -0
  3. package/app/index.d.ts +164 -0
  4. package/app/index.d.ts.map +1 -0
  5. package/app/index.js +424 -0
  6. package/app-controller/controller.d.ts +425 -0
  7. package/app-controller/controller.d.ts.map +1 -0
  8. package/app-controller/controller.js +1173 -0
  9. package/app-controller/index.d.ts +14 -0
  10. package/app-controller/index.d.ts.map +1 -0
  11. package/app-controller/index.js +12 -0
  12. package/app-workspace/index.d.ts +421 -0
  13. package/app-workspace/index.d.ts.map +1 -0
  14. package/app-workspace/index.js +722 -0
  15. package/collaboration/client.d.ts +40 -0
  16. package/collaboration/client.d.ts.map +1 -0
  17. package/collaboration/client.js +299 -0
  18. package/collaboration/errors.d.ts +15 -0
  19. package/collaboration/errors.d.ts.map +1 -0
  20. package/collaboration/errors.js +17 -0
  21. package/collaboration/fixture.d.ts +41 -0
  22. package/collaboration/fixture.d.ts.map +1 -0
  23. package/collaboration/fixture.js +362 -0
  24. package/collaboration/index.d.ts +18 -0
  25. package/collaboration/index.d.ts.map +1 -0
  26. package/collaboration/index.js +14 -0
  27. package/collaboration/types.d.ts +240 -0
  28. package/collaboration/types.d.ts.map +1 -0
  29. package/collaboration/types.js +1 -0
  30. package/contract/analytics-sources.d.ts +149 -0
  31. package/contract/analytics-sources.d.ts.map +1 -0
  32. package/contract/analytics-sources.js +235 -0
  33. package/contract/edit-session.d.ts +203 -0
  34. package/contract/edit-session.d.ts.map +1 -0
  35. package/contract/edit-session.js +760 -0
  36. package/contract/edit-sketch.d.ts +91 -0
  37. package/contract/edit-sketch.d.ts.map +1 -0
  38. package/contract/edit-sketch.js +281 -0
  39. package/contract/index.d.ts +63 -0
  40. package/contract/index.d.ts.map +1 -0
  41. package/contract/index.js +52 -0
  42. package/contract/jobs.d.ts +149 -0
  43. package/contract/jobs.d.ts.map +1 -0
  44. package/contract/jobs.js +40 -0
  45. package/contract/pmtiles.d.ts +162 -0
  46. package/contract/pmtiles.d.ts.map +1 -0
  47. package/contract/pmtiles.js +155 -0
  48. package/contract/source.d.ts +447 -0
  49. package/contract/source.d.ts.map +1 -0
  50. package/contract/source.js +3909 -0
  51. package/contract/spatial-aggregation.d.ts +336 -0
  52. package/contract/spatial-aggregation.d.ts.map +1 -0
  53. package/contract/spatial-aggregation.js +298 -0
  54. package/contract/temporal.d.ts +455 -0
  55. package/contract/temporal.d.ts.map +1 -0
  56. package/contract/temporal.js +146 -0
  57. package/contract/tiles.d.ts +370 -0
  58. package/contract/tiles.d.ts.map +1 -0
  59. package/contract/tiles.js +519 -0
  60. package/contract/types.d.ts +694 -0
  61. package/contract/types.d.ts.map +1 -0
  62. package/contract/types.js +183 -0
  63. package/contract/widget-source.d.ts +205 -0
  64. package/contract/widget-source.d.ts.map +1 -0
  65. package/contract/widget-source.js +1473 -0
  66. package/control-plane/client.d.ts +95 -0
  67. package/control-plane/client.d.ts.map +1 -0
  68. package/control-plane/client.js +374 -0
  69. package/control-plane/index.d.ts +18 -0
  70. package/control-plane/index.d.ts.map +1 -0
  71. package/control-plane/index.js +14 -0
  72. package/control-plane/types.d.ts +233 -0
  73. package/control-plane/types.d.ts.map +1 -0
  74. package/control-plane/types.js +7 -0
  75. package/controls/basemap-style-binding.d.ts +54 -0
  76. package/controls/basemap-style-binding.d.ts.map +1 -0
  77. package/controls/basemap-style-binding.js +199 -0
  78. package/controls/basemap-switcher.d.ts +95 -0
  79. package/controls/basemap-switcher.d.ts.map +1 -0
  80. package/controls/basemap-switcher.js +379 -0
  81. package/controls/element-utils.d.ts +48 -0
  82. package/controls/element-utils.d.ts.map +1 -0
  83. package/controls/element-utils.js +78 -0
  84. package/controls/index.d.ts +33 -0
  85. package/controls/index.d.ts.map +1 -0
  86. package/controls/index.js +30 -0
  87. package/controls/layer-list.d.ts +98 -0
  88. package/controls/layer-list.d.ts.map +1 -0
  89. package/controls/layer-list.js +375 -0
  90. package/controls/legend-derive.d.ts +53 -0
  91. package/controls/legend-derive.d.ts.map +1 -0
  92. package/controls/legend-derive.js +196 -0
  93. package/controls/legend.d.ts +104 -0
  94. package/controls/legend.d.ts.map +1 -0
  95. package/controls/legend.js +381 -0
  96. package/controls/swipe-control.d.ts +80 -0
  97. package/controls/swipe-control.d.ts.map +1 -0
  98. package/controls/swipe-control.js +368 -0
  99. package/controls/types.d.ts +227 -0
  100. package/controls/types.d.ts.map +1 -0
  101. package/controls/types.js +11 -0
  102. package/core/auth/client-credentials-provider.d.ts +51 -0
  103. package/core/auth/client-credentials-provider.d.ts.map +1 -0
  104. package/core/auth/client-credentials-provider.js +115 -0
  105. package/core/auth/credential-store.d.ts +52 -0
  106. package/core/auth/credential-store.d.ts.map +1 -0
  107. package/core/auth/credential-store.js +82 -0
  108. package/core/auth/index.d.ts +23 -0
  109. package/core/auth/index.d.ts.map +1 -0
  110. package/core/auth/index.js +20 -0
  111. package/core/auth/oauth2-provider.d.ts +114 -0
  112. package/core/auth/oauth2-provider.d.ts.map +1 -0
  113. package/core/auth/oauth2-provider.js +408 -0
  114. package/core/auth/pkce.d.ts +25 -0
  115. package/core/auth/pkce.d.ts.map +1 -0
  116. package/core/auth/pkce.js +46 -0
  117. package/core/auth/static-providers.d.ts +20 -0
  118. package/core/auth/static-providers.d.ts.map +1 -0
  119. package/core/auth/static-providers.js +26 -0
  120. package/core/auth/token-endpoint.d.ts +40 -0
  121. package/core/auth/token-endpoint.d.ts.map +1 -0
  122. package/core/auth/token-endpoint.js +133 -0
  123. package/core/auth/types.d.ts +144 -0
  124. package/core/auth/types.d.ts.map +1 -0
  125. package/core/auth/types.js +8 -0
  126. package/core/batch.d.ts +37 -0
  127. package/core/batch.d.ts.map +1 -0
  128. package/core/batch.js +79 -0
  129. package/core/cache-state.d.ts +79 -0
  130. package/core/cache-state.d.ts.map +1 -0
  131. package/core/cache-state.js +87 -0
  132. package/core/client.d.ts +607 -0
  133. package/core/client.d.ts.map +1 -0
  134. package/core/client.js +1716 -0
  135. package/core/compatibility.d.ts +18 -0
  136. package/core/compatibility.d.ts.map +1 -0
  137. package/core/compatibility.js +245 -0
  138. package/core/errors.d.ts +139 -0
  139. package/core/errors.d.ts.map +1 -0
  140. package/core/errors.js +176 -0
  141. package/core/esri-geojson.d.ts +66 -0
  142. package/core/esri-geojson.d.ts.map +1 -0
  143. package/core/esri-geojson.js +363 -0
  144. package/core/geoparquet-sql.d.ts +162 -0
  145. package/core/geoparquet-sql.d.ts.map +1 -0
  146. package/core/geoparquet-sql.js +333 -0
  147. package/core/geoservices.d.ts +34 -0
  148. package/core/geoservices.d.ts.map +1 -0
  149. package/core/geoservices.js +434 -0
  150. package/core/grpc-adapter.d.ts +23 -0
  151. package/core/grpc-adapter.d.ts.map +1 -0
  152. package/core/grpc-adapter.js +688 -0
  153. package/core/odata.d.ts +347 -0
  154. package/core/odata.d.ts.map +1 -0
  155. package/core/odata.js +913 -0
  156. package/core/ogc-conformance.d.ts +35 -0
  157. package/core/ogc-conformance.d.ts.map +1 -0
  158. package/core/ogc-conformance.js +134 -0
  159. package/core/ogc-endpoint-layout.d.ts +70 -0
  160. package/core/ogc-endpoint-layout.d.ts.map +1 -0
  161. package/core/ogc-endpoint-layout.js +173 -0
  162. package/core/ogc-features.d.ts +23 -0
  163. package/core/ogc-features.d.ts.map +1 -0
  164. package/core/ogc-features.js +129 -0
  165. package/core/ogc-maps.d.ts +49 -0
  166. package/core/ogc-maps.d.ts.map +1 -0
  167. package/core/ogc-maps.js +126 -0
  168. package/core/ogc-processes.d.ts +118 -0
  169. package/core/ogc-processes.d.ts.map +1 -0
  170. package/core/ogc-processes.js +423 -0
  171. package/core/ogc-records.d.ts +75 -0
  172. package/core/ogc-records.d.ts.map +1 -0
  173. package/core/ogc-records.js +251 -0
  174. package/core/ogc-tiles.d.ts +125 -0
  175. package/core/ogc-tiles.d.ts.map +1 -0
  176. package/core/ogc-tiles.js +183 -0
  177. package/core/path-utils.d.ts +69 -0
  178. package/core/path-utils.d.ts.map +1 -0
  179. package/core/path-utils.js +123 -0
  180. package/core/pbf-decoder.d.ts +39 -0
  181. package/core/pbf-decoder.d.ts.map +1 -0
  182. package/core/pbf-decoder.js +702 -0
  183. package/core/process-runner.d.ts +104 -0
  184. package/core/process-runner.d.ts.map +1 -0
  185. package/core/process-runner.js +315 -0
  186. package/core/protocol-transport.d.ts +76 -0
  187. package/core/protocol-transport.d.ts.map +1 -0
  188. package/core/protocol-transport.js +15 -0
  189. package/core/query-builder.d.ts +261 -0
  190. package/core/query-builder.d.ts.map +1 -0
  191. package/core/query-builder.js +538 -0
  192. package/core/request-pipeline.d.ts +88 -0
  193. package/core/request-pipeline.d.ts.map +1 -0
  194. package/core/request-pipeline.js +273 -0
  195. package/core/spatial-filter.d.ts +93 -0
  196. package/core/spatial-filter.d.ts.map +1 -0
  197. package/core/spatial-filter.js +153 -0
  198. package/core/stac-static.d.ts +51 -0
  199. package/core/stac-static.d.ts.map +1 -0
  200. package/core/stac-static.js +195 -0
  201. package/core/stac.d.ts +67 -0
  202. package/core/stac.d.ts.map +1 -0
  203. package/core/stac.js +259 -0
  204. package/core/surfaces.d.ts +540 -0
  205. package/core/surfaces.d.ts.map +1 -0
  206. package/core/surfaces.js +1964 -0
  207. package/core/terrain-elevation.d.ts +114 -0
  208. package/core/terrain-elevation.d.ts.map +1 -0
  209. package/core/terrain-elevation.js +150 -0
  210. package/core/types.d.ts +1404 -0
  211. package/core/types.d.ts.map +1 -0
  212. package/core/types.js +13 -0
  213. package/core/wfs-capabilities.d.ts +153 -0
  214. package/core/wfs-capabilities.d.ts.map +1 -0
  215. package/core/wfs-capabilities.js +490 -0
  216. package/core/wfs-filter.d.ts +118 -0
  217. package/core/wfs-filter.d.ts.map +1 -0
  218. package/core/wfs-filter.js +634 -0
  219. package/core/wfs.d.ts +232 -0
  220. package/core/wfs.d.ts.map +1 -0
  221. package/core/wfs.js +426 -0
  222. package/core/wire-shared.d.ts +32 -0
  223. package/core/wire-shared.d.ts.map +1 -0
  224. package/core/wire-shared.js +76 -0
  225. package/core/wms-axis.d.ts +36 -0
  226. package/core/wms-axis.d.ts.map +1 -0
  227. package/core/wms-axis.js +73 -0
  228. package/core/wms-capabilities.d.ts +110 -0
  229. package/core/wms-capabilities.d.ts.map +1 -0
  230. package/core/wms-capabilities.js +559 -0
  231. package/core/wms-types.d.ts +128 -0
  232. package/core/wms-types.d.ts.map +1 -0
  233. package/core/wms-types.js +32 -0
  234. package/core/wms.d.ts +144 -0
  235. package/core/wms.d.ts.map +1 -0
  236. package/core/wms.js +338 -0
  237. package/core/wmts-capabilities.d.ts +82 -0
  238. package/core/wmts-capabilities.d.ts.map +1 -0
  239. package/core/wmts-capabilities.js +402 -0
  240. package/core/wmts.d.ts +103 -0
  241. package/core/wmts.d.ts.map +1 -0
  242. package/core/wmts.js +332 -0
  243. package/core/xml-text.d.ts +20 -0
  244. package/core/xml-text.d.ts.map +1 -0
  245. package/core/xml-text.js +85 -0
  246. package/esri-compat/basemap-gallery.d.ts +38 -0
  247. package/esri-compat/basemap-gallery.d.ts.map +1 -0
  248. package/esri-compat/basemap-gallery.js +159 -0
  249. package/esri-compat/basemap-layer-list.d.ts +35 -0
  250. package/esri-compat/basemap-layer-list.d.ts.map +1 -0
  251. package/esri-compat/basemap-layer-list.js +139 -0
  252. package/esri-compat/basemap.d.ts +32 -0
  253. package/esri-compat/basemap.d.ts.map +1 -0
  254. package/esri-compat/basemap.js +84 -0
  255. package/esri-compat/bookmarks.d.ts +36 -0
  256. package/esri-compat/bookmarks.d.ts.map +1 -0
  257. package/esri-compat/bookmarks.js +108 -0
  258. package/esri-compat/class-breaks-renderer.d.ts +50 -0
  259. package/esri-compat/class-breaks-renderer.d.ts.map +1 -0
  260. package/esri-compat/class-breaks-renderer.js +164 -0
  261. package/esri-compat/color.d.ts +22 -0
  262. package/esri-compat/color.d.ts.map +1 -0
  263. package/esri-compat/color.js +106 -0
  264. package/esri-compat/controls.d.ts +174 -0
  265. package/esri-compat/controls.d.ts.map +1 -0
  266. package/esri-compat/controls.js +479 -0
  267. package/esri-compat/coordinate-conversion.d.ts +41 -0
  268. package/esri-compat/coordinate-conversion.d.ts.map +1 -0
  269. package/esri-compat/coordinate-conversion.js +125 -0
  270. package/esri-compat/directions.d.ts +45 -0
  271. package/esri-compat/directions.d.ts.map +1 -0
  272. package/esri-compat/directions.js +123 -0
  273. package/esri-compat/editor.d.ts +47 -0
  274. package/esri-compat/editor.d.ts.map +1 -0
  275. package/esri-compat/editor.js +170 -0
  276. package/esri-compat/esri-config.d.ts +16 -0
  277. package/esri-compat/esri-config.d.ts.map +1 -0
  278. package/esri-compat/esri-config.js +23 -0
  279. package/esri-compat/esri-request.d.ts +17 -0
  280. package/esri-compat/esri-request.d.ts.map +1 -0
  281. package/esri-compat/esri-request.js +127 -0
  282. package/esri-compat/event-bus.d.ts +106 -0
  283. package/esri-compat/event-bus.d.ts.map +1 -0
  284. package/esri-compat/event-bus.js +90 -0
  285. package/esri-compat/expand.d.ts +36 -0
  286. package/esri-compat/expand.d.ts.map +1 -0
  287. package/esri-compat/expand.js +97 -0
  288. package/esri-compat/extent.d.ts +43 -0
  289. package/esri-compat/extent.d.ts.map +1 -0
  290. package/esri-compat/extent.js +140 -0
  291. package/esri-compat/feature-filter.d.ts +55 -0
  292. package/esri-compat/feature-filter.d.ts.map +1 -0
  293. package/esri-compat/feature-filter.js +109 -0
  294. package/esri-compat/feature-form.d.ts +64 -0
  295. package/esri-compat/feature-form.d.ts.map +1 -0
  296. package/esri-compat/feature-form.js +137 -0
  297. package/esri-compat/feature-layer.d.ts +173 -0
  298. package/esri-compat/feature-layer.d.ts.map +1 -0
  299. package/esri-compat/feature-layer.js +661 -0
  300. package/esri-compat/feature-set.d.ts +32 -0
  301. package/esri-compat/feature-set.d.ts.map +1 -0
  302. package/esri-compat/feature-set.js +80 -0
  303. package/esri-compat/feature-table.d.ts +141 -0
  304. package/esri-compat/feature-table.d.ts.map +1 -0
  305. package/esri-compat/feature-table.js +500 -0
  306. package/esri-compat/feature-templates.d.ts +41 -0
  307. package/esri-compat/feature-templates.d.ts.map +1 -0
  308. package/esri-compat/feature-templates.js +97 -0
  309. package/esri-compat/feature.d.ts +33 -0
  310. package/esri-compat/feature.d.ts.map +1 -0
  311. package/esri-compat/feature.js +83 -0
  312. package/esri-compat/geojson-layer.d.ts +86 -0
  313. package/esri-compat/geojson-layer.d.ts.map +1 -0
  314. package/esri-compat/geojson-layer.js +191 -0
  315. package/esri-compat/geometry-engine.d.ts +107 -0
  316. package/esri-compat/geometry-engine.d.ts.map +1 -0
  317. package/esri-compat/geometry-engine.js +266 -0
  318. package/esri-compat/graphic.d.ts +46 -0
  319. package/esri-compat/graphic.d.ts.map +1 -0
  320. package/esri-compat/graphic.js +103 -0
  321. package/esri-compat/graphics-layer.d.ts +49 -0
  322. package/esri-compat/graphics-layer.d.ts.map +1 -0
  323. package/esri-compat/graphics-layer.js +185 -0
  324. package/esri-compat/group-layer.d.ts +48 -0
  325. package/esri-compat/group-layer.d.ts.map +1 -0
  326. package/esri-compat/group-layer.js +212 -0
  327. package/esri-compat/identify.d.ts +71 -0
  328. package/esri-compat/identify.d.ts.map +1 -0
  329. package/esri-compat/identify.js +299 -0
  330. package/esri-compat/identity-manager.d.ts +74 -0
  331. package/esri-compat/identity-manager.d.ts.map +1 -0
  332. package/esri-compat/identity-manager.js +245 -0
  333. package/esri-compat/imagery-layer.d.ts +78 -0
  334. package/esri-compat/imagery-layer.d.ts.map +1 -0
  335. package/esri-compat/imagery-layer.js +167 -0
  336. package/esri-compat/label-class.d.ts +31 -0
  337. package/esri-compat/label-class.d.ts.map +1 -0
  338. package/esri-compat/label-class.js +102 -0
  339. package/esri-compat/layer-list.d.ts +77 -0
  340. package/esri-compat/layer-list.d.ts.map +1 -0
  341. package/esri-compat/layer-list.js +342 -0
  342. package/esri-compat/legend.d.ts +53 -0
  343. package/esri-compat/legend.d.ts.map +1 -0
  344. package/esri-compat/legend.js +254 -0
  345. package/esri-compat/map-image-layer.d.ts +162 -0
  346. package/esri-compat/map-image-layer.d.ts.map +1 -0
  347. package/esri-compat/map-image-layer.js +709 -0
  348. package/esri-compat/map-view.d.ts +323 -0
  349. package/esri-compat/map-view.d.ts.map +1 -0
  350. package/esri-compat/map-view.js +1175 -0
  351. package/esri-compat/map.d.ts +47 -0
  352. package/esri-compat/map.d.ts.map +1 -0
  353. package/esri-compat/map.js +209 -0
  354. package/esri-compat/measurement-2d.d.ts +61 -0
  355. package/esri-compat/measurement-2d.d.ts.map +1 -0
  356. package/esri-compat/measurement-2d.js +184 -0
  357. package/esri-compat/measurement.d.ts +45 -0
  358. package/esri-compat/measurement.d.ts.map +1 -0
  359. package/esri-compat/measurement.js +193 -0
  360. package/esri-compat/oauth-info.d.ts +50 -0
  361. package/esri-compat/oauth-info.d.ts.map +1 -0
  362. package/esri-compat/oauth-info.js +142 -0
  363. package/esri-compat/picture-marker-symbol.d.ts +35 -0
  364. package/esri-compat/picture-marker-symbol.d.ts.map +1 -0
  365. package/esri-compat/picture-marker-symbol.js +126 -0
  366. package/esri-compat/point.d.ts +31 -0
  367. package/esri-compat/point.d.ts.map +1 -0
  368. package/esri-compat/point.js +102 -0
  369. package/esri-compat/polygon.d.ts +31 -0
  370. package/esri-compat/polygon.d.ts.map +1 -0
  371. package/esri-compat/polygon.js +107 -0
  372. package/esri-compat/polyline.d.ts +31 -0
  373. package/esri-compat/polyline.d.ts.map +1 -0
  374. package/esri-compat/polyline.js +107 -0
  375. package/esri-compat/popup-template.d.ts +55 -0
  376. package/esri-compat/popup-template.d.ts.map +1 -0
  377. package/esri-compat/popup-template.js +128 -0
  378. package/esri-compat/popup.d.ts +54 -0
  379. package/esri-compat/popup.d.ts.map +1 -0
  380. package/esri-compat/popup.js +312 -0
  381. package/esri-compat/print.d.ts +47 -0
  382. package/esri-compat/print.d.ts.map +1 -0
  383. package/esri-compat/print.js +105 -0
  384. package/esri-compat/query.d.ts +58 -0
  385. package/esri-compat/query.d.ts.map +1 -0
  386. package/esri-compat/query.js +128 -0
  387. package/esri-compat/reactive-utils.d.ts +24 -0
  388. package/esri-compat/reactive-utils.d.ts.map +1 -0
  389. package/esri-compat/reactive-utils.js +193 -0
  390. package/esri-compat/request.d.ts +41 -0
  391. package/esri-compat/request.d.ts.map +1 -0
  392. package/esri-compat/request.js +253 -0
  393. package/esri-compat/route-layer.d.ts +59 -0
  394. package/esri-compat/route-layer.d.ts.map +1 -0
  395. package/esri-compat/route-layer.js +223 -0
  396. package/esri-compat/route-task.d.ts +88 -0
  397. package/esri-compat/route-task.d.ts.map +1 -0
  398. package/esri-compat/route-task.js +225 -0
  399. package/esri-compat/scene-view.d.ts +41 -0
  400. package/esri-compat/scene-view.d.ts.map +1 -0
  401. package/esri-compat/scene-view.js +68 -0
  402. package/esri-compat/search.d.ts +112 -0
  403. package/esri-compat/search.d.ts.map +1 -0
  404. package/esri-compat/search.js +820 -0
  405. package/esri-compat/simple-fill-symbol.d.ts +27 -0
  406. package/esri-compat/simple-fill-symbol.d.ts.map +1 -0
  407. package/esri-compat/simple-fill-symbol.js +85 -0
  408. package/esri-compat/simple-line-symbol.d.ts +27 -0
  409. package/esri-compat/simple-line-symbol.d.ts.map +1 -0
  410. package/esri-compat/simple-line-symbol.js +85 -0
  411. package/esri-compat/simple-marker-symbol.d.ts +29 -0
  412. package/esri-compat/simple-marker-symbol.d.ts.map +1 -0
  413. package/esri-compat/simple-marker-symbol.js +92 -0
  414. package/esri-compat/simple-renderer.d.ts +29 -0
  415. package/esri-compat/simple-renderer.d.ts.map +1 -0
  416. package/esri-compat/simple-renderer.js +92 -0
  417. package/esri-compat/sketch.d.ts +64 -0
  418. package/esri-compat/sketch.d.ts.map +1 -0
  419. package/esri-compat/sketch.js +227 -0
  420. package/esri-compat/spatial-reference.d.ts +31 -0
  421. package/esri-compat/spatial-reference.d.ts.map +1 -0
  422. package/esri-compat/spatial-reference.js +102 -0
  423. package/esri-compat/swipe.d.ts +34 -0
  424. package/esri-compat/swipe.d.ts.map +1 -0
  425. package/esri-compat/swipe.js +93 -0
  426. package/esri-compat/table-list.d.ts +36 -0
  427. package/esri-compat/table-list.d.ts.map +1 -0
  428. package/esri-compat/table-list.js +126 -0
  429. package/esri-compat/text-symbol.d.ts +37 -0
  430. package/esri-compat/text-symbol.d.ts.map +1 -0
  431. package/esri-compat/text-symbol.js +123 -0
  432. package/esri-compat/tile-layer.d.ts +52 -0
  433. package/esri-compat/tile-layer.d.ts.map +1 -0
  434. package/esri-compat/tile-layer.js +168 -0
  435. package/esri-compat/time-slider.d.ts +70 -0
  436. package/esri-compat/time-slider.d.ts.map +1 -0
  437. package/esri-compat/time-slider.js +208 -0
  438. package/esri-compat/track.d.ts +51 -0
  439. package/esri-compat/track.d.ts.map +1 -0
  440. package/esri-compat/track.js +174 -0
  441. package/esri-compat/unique-value-renderer.d.ts +41 -0
  442. package/esri-compat/unique-value-renderer.d.ts.map +1 -0
  443. package/esri-compat/unique-value-renderer.js +127 -0
  444. package/esri-compat/url.d.ts +13 -0
  445. package/esri-compat/url.d.ts.map +1 -0
  446. package/esri-compat/url.js +68 -0
  447. package/esri-compat/vector-tile-layer.d.ts +47 -0
  448. package/esri-compat/vector-tile-layer.d.ts.map +1 -0
  449. package/esri-compat/vector-tile-layer.js +130 -0
  450. package/esri-compat/web-map.d.ts +14 -0
  451. package/esri-compat/web-map.d.ts.map +1 -0
  452. package/esri-compat/web-map.js +24 -0
  453. package/esri-compat/wfs-layer.d.ts +64 -0
  454. package/esri-compat/wfs-layer.d.ts.map +1 -0
  455. package/esri-compat/wfs-layer.js +145 -0
  456. package/esri-compat/wms-layer.d.ts +76 -0
  457. package/esri-compat/wms-layer.d.ts.map +1 -0
  458. package/esri-compat/wms-layer.js +157 -0
  459. package/exploration/context.d.ts +25 -0
  460. package/exploration/context.d.ts.map +1 -0
  461. package/exploration/context.js +396 -0
  462. package/exploration/index.d.ts +27 -0
  463. package/exploration/index.d.ts.map +1 -0
  464. package/exploration/index.js +24 -0
  465. package/exploration/presets.d.ts +27 -0
  466. package/exploration/presets.d.ts.map +1 -0
  467. package/exploration/presets.js +114 -0
  468. package/exploration/reducer.d.ts +23 -0
  469. package/exploration/reducer.d.ts.map +1 -0
  470. package/exploration/reducer.js +332 -0
  471. package/exploration/selection.d.ts +25 -0
  472. package/exploration/selection.d.ts.map +1 -0
  473. package/exploration/selection.js +34 -0
  474. package/exploration/selectors.d.ts +56 -0
  475. package/exploration/selectors.d.ts.map +1 -0
  476. package/exploration/selectors.js +110 -0
  477. package/exploration/types.d.ts +294 -0
  478. package/exploration/types.d.ts.map +1 -0
  479. package/exploration/types.js +33 -0
  480. package/expr/expression.d.ts +457 -0
  481. package/expr/expression.d.ts.map +1 -0
  482. package/expr/expression.js +663 -0
  483. package/expr/index.d.ts +32 -0
  484. package/expr/index.d.ts.map +1 -0
  485. package/expr/index.js +30 -0
  486. package/filter-registry/index.d.ts +145 -0
  487. package/filter-registry/index.d.ts.map +1 -0
  488. package/filter-registry/index.js +531 -0
  489. package/gen/honua/v1/feature_service_pb.d.ts +918 -0
  490. package/gen/honua/v1/feature_service_pb.d.ts.map +1 -0
  491. package/gen/honua/v1/feature_service_pb.js +375 -0
  492. package/generated-app/errors.d.ts +41 -0
  493. package/generated-app/errors.d.ts.map +1 -0
  494. package/generated-app/errors.js +41 -0
  495. package/generated-app/index.d.ts +17 -0
  496. package/generated-app/index.d.ts.map +1 -0
  497. package/generated-app/index.js +12 -0
  498. package/generated-app/manifest.d.ts +183 -0
  499. package/generated-app/manifest.d.ts.map +1 -0
  500. package/generated-app/manifest.js +14 -0
  501. package/generated-app/projection.d.ts +44 -0
  502. package/generated-app/projection.d.ts.map +1 -0
  503. package/generated-app/projection.js +234 -0
  504. package/generated-app/runtime.d.ts +215 -0
  505. package/generated-app/runtime.d.ts.map +1 -0
  506. package/generated-app/runtime.js +1196 -0
  507. package/geocoding/index.d.ts +106 -0
  508. package/geocoding/index.d.ts.map +1 -0
  509. package/geocoding/index.js +278 -0
  510. package/interactions/detail-model.d.ts +54 -0
  511. package/interactions/detail-model.d.ts.map +1 -0
  512. package/interactions/detail-model.js +105 -0
  513. package/interactions/exploration-bindings.d.ts +120 -0
  514. package/interactions/exploration-bindings.d.ts.map +1 -0
  515. package/interactions/exploration-bindings.js +218 -0
  516. package/interactions/feature-state.d.ts +144 -0
  517. package/interactions/feature-state.d.ts.map +1 -0
  518. package/interactions/feature-state.js +169 -0
  519. package/interactions/hit-test.d.ts +112 -0
  520. package/interactions/hit-test.d.ts.map +1 -0
  521. package/interactions/hit-test.js +291 -0
  522. package/interactions/index.d.ts +31 -0
  523. package/interactions/index.d.ts.map +1 -0
  524. package/interactions/index.js +24 -0
  525. package/interactions/share-state.d.ts +36 -0
  526. package/interactions/share-state.d.ts.map +1 -0
  527. package/interactions/share-state.js +123 -0
  528. package/map/feature-service-adapter.d.ts +138 -0
  529. package/map/feature-service-adapter.d.ts.map +1 -0
  530. package/map/feature-service-adapter.js +279 -0
  531. package/map/honua-map.d.ts +203 -0
  532. package/map/honua-map.d.ts.map +1 -0
  533. package/map/honua-map.js +347 -0
  534. package/map/index.d.ts +27 -0
  535. package/map/index.d.ts.map +1 -0
  536. package/map/index.js +22 -0
  537. package/map/maplibre-target.d.ts +103 -0
  538. package/map/maplibre-target.d.ts.map +1 -0
  539. package/map/maplibre-target.js +164 -0
  540. package/map/webmap-maplibre.d.ts +60 -0
  541. package/map/webmap-maplibre.d.ts.map +1 -0
  542. package/map/webmap-maplibre.js +212 -0
  543. package/operate/client.d.ts +94 -0
  544. package/operate/client.d.ts.map +1 -0
  545. package/operate/client.js +361 -0
  546. package/operate/index.d.ts +22 -0
  547. package/operate/index.d.ts.map +1 -0
  548. package/operate/index.js +19 -0
  549. package/operate/types.d.ts +397 -0
  550. package/operate/types.d.ts.map +1 -0
  551. package/operate/types.js +17 -0
  552. package/operator/client.d.ts +60 -0
  553. package/operator/client.d.ts.map +1 -0
  554. package/operator/client.js +20 -0
  555. package/operator/controllers/approval.d.ts +52 -0
  556. package/operator/controllers/approval.d.ts.map +1 -0
  557. package/operator/controllers/approval.js +123 -0
  558. package/operator/controllers/base.d.ts +27 -0
  559. package/operator/controllers/base.d.ts.map +1 -0
  560. package/operator/controllers/base.js +53 -0
  561. package/operator/controllers/builder-workspace.d.ts +55 -0
  562. package/operator/controllers/builder-workspace.d.ts.map +1 -0
  563. package/operator/controllers/builder-workspace.js +108 -0
  564. package/operator/controllers/chat.d.ts +61 -0
  565. package/operator/controllers/chat.d.ts.map +1 -0
  566. package/operator/controllers/chat.js +154 -0
  567. package/operator/controllers/clarification.d.ts +52 -0
  568. package/operator/controllers/clarification.d.ts.map +1 -0
  569. package/operator/controllers/clarification.js +121 -0
  570. package/operator/controllers/execution.d.ts +60 -0
  571. package/operator/controllers/execution.d.ts.map +1 -0
  572. package/operator/controllers/execution.js +286 -0
  573. package/operator/controllers/index.d.ts +23 -0
  574. package/operator/controllers/index.d.ts.map +1 -0
  575. package/operator/controllers/index.js +15 -0
  576. package/operator/controllers/map-workspace.d.ts +85 -0
  577. package/operator/controllers/map-workspace.d.ts.map +1 -0
  578. package/operator/controllers/map-workspace.js +296 -0
  579. package/operator/controllers/plan-review.d.ts +66 -0
  580. package/operator/controllers/plan-review.d.ts.map +1 -0
  581. package/operator/controllers/plan-review.js +124 -0
  582. package/operator/errors.d.ts +62 -0
  583. package/operator/errors.d.ts.map +1 -0
  584. package/operator/errors.js +75 -0
  585. package/operator/i18n/index.d.ts +10 -0
  586. package/operator/i18n/index.d.ts.map +1 -0
  587. package/operator/i18n/index.js +8 -0
  588. package/operator/i18n/messages.d.ts +19 -0
  589. package/operator/i18n/messages.d.ts.map +1 -0
  590. package/operator/i18n/messages.js +54 -0
  591. package/operator/index.d.ts +19 -0
  592. package/operator/index.d.ts.map +1 -0
  593. package/operator/index.js +15 -0
  594. package/operator/telemetry.d.ts +26 -0
  595. package/operator/telemetry.d.ts.map +1 -0
  596. package/operator/telemetry.js +9 -0
  597. package/operator/theming/index.d.ts +12 -0
  598. package/operator/theming/index.d.ts.map +1 -0
  599. package/operator/theming/index.js +9 -0
  600. package/operator/theming/provider.d.ts +27 -0
  601. package/operator/theming/provider.d.ts.map +1 -0
  602. package/operator/theming/provider.js +26 -0
  603. package/operator/theming/tokens.d.ts +28 -0
  604. package/operator/theming/tokens.d.ts.map +1 -0
  605. package/operator/theming/tokens.js +65 -0
  606. package/operator/workspace/events.d.ts +70 -0
  607. package/operator/workspace/events.d.ts.map +1 -0
  608. package/operator/workspace/events.js +9 -0
  609. package/operator/workspace/index.d.ts +12 -0
  610. package/operator/workspace/index.d.ts.map +1 -0
  611. package/operator/workspace/index.js +8 -0
  612. package/operator/workspace/types.d.ts +178 -0
  613. package/operator/workspace/types.d.ts.map +1 -0
  614. package/operator/workspace/types.js +47 -0
  615. package/operator/workspace/workspace.d.ts +58 -0
  616. package/operator/workspace/workspace.d.ts.map +1 -0
  617. package/operator/workspace/workspace.js +339 -0
  618. package/package.json +105 -0
  619. package/realtime/exploration.d.ts +16 -0
  620. package/realtime/exploration.d.ts.map +1 -0
  621. package/realtime/exploration.js +32 -0
  622. package/realtime/honua-server.d.ts +123 -0
  623. package/realtime/honua-server.d.ts.map +1 -0
  624. package/realtime/honua-server.js +188 -0
  625. package/realtime/index.d.ts +20 -0
  626. package/realtime/index.d.ts.map +1 -0
  627. package/realtime/index.js +14 -0
  628. package/realtime/projections.d.ts +30 -0
  629. package/realtime/projections.d.ts.map +1 -0
  630. package/realtime/projections.js +51 -0
  631. package/realtime/reducer.d.ts +14 -0
  632. package/realtime/reducer.d.ts.map +1 -0
  633. package/realtime/reducer.js +351 -0
  634. package/realtime/sse.d.ts +23 -0
  635. package/realtime/sse.d.ts.map +1 -0
  636. package/realtime/sse.js +143 -0
  637. package/realtime/store.d.ts +18 -0
  638. package/realtime/store.d.ts.map +1 -0
  639. package/realtime/store.js +63 -0
  640. package/realtime/types.d.ts +190 -0
  641. package/realtime/types.d.ts.map +1 -0
  642. package/realtime/types.js +10 -0
  643. package/replica-sync/client.d.ts +32 -0
  644. package/replica-sync/client.d.ts.map +1 -0
  645. package/replica-sync/client.js +52 -0
  646. package/replica-sync/errors.d.ts +22 -0
  647. package/replica-sync/errors.d.ts.map +1 -0
  648. package/replica-sync/errors.js +29 -0
  649. package/replica-sync/fixture.d.ts +40 -0
  650. package/replica-sync/fixture.d.ts.map +1 -0
  651. package/replica-sync/fixture.js +364 -0
  652. package/replica-sync/index.d.ts +22 -0
  653. package/replica-sync/index.d.ts.map +1 -0
  654. package/replica-sync/index.js +17 -0
  655. package/replica-sync/types.d.ts +270 -0
  656. package/replica-sync/types.d.ts.map +1 -0
  657. package/replica-sync/types.js +13 -0
  658. package/runtime/diff.d.ts +31 -0
  659. package/runtime/diff.d.ts.map +1 -0
  660. package/runtime/diff.js +143 -0
  661. package/runtime/errors.d.ts +40 -0
  662. package/runtime/errors.d.ts.map +1 -0
  663. package/runtime/errors.js +35 -0
  664. package/runtime/index.d.ts +59 -0
  665. package/runtime/index.d.ts.map +1 -0
  666. package/runtime/index.js +40 -0
  667. package/runtime/legend.d.ts +23 -0
  668. package/runtime/legend.d.ts.map +1 -0
  669. package/runtime/legend.js +38 -0
  670. package/runtime/load-package.d.ts +125 -0
  671. package/runtime/load-package.d.ts.map +1 -0
  672. package/runtime/load-package.js +272 -0
  673. package/runtime/map-package-fetch.d.ts +107 -0
  674. package/runtime/map-package-fetch.d.ts.map +1 -0
  675. package/runtime/map-package-fetch.js +336 -0
  676. package/runtime/map-package-realtime.d.ts +169 -0
  677. package/runtime/map-package-realtime.d.ts.map +1 -0
  678. package/runtime/map-package-realtime.js +350 -0
  679. package/runtime/map-package-validation.d.ts +30 -0
  680. package/runtime/map-package-validation.d.ts.map +1 -0
  681. package/runtime/map-package-validation.js +257 -0
  682. package/runtime/map-package-watch.d.ts +78 -0
  683. package/runtime/map-package-watch.d.ts.map +1 -0
  684. package/runtime/map-package-watch.js +695 -0
  685. package/runtime/map-package.d.ts +167 -0
  686. package/runtime/map-package.d.ts.map +1 -0
  687. package/runtime/map-package.js +15 -0
  688. package/runtime/ogc-styles.d.ts +110 -0
  689. package/runtime/ogc-styles.d.ts.map +1 -0
  690. package/runtime/ogc-styles.js +195 -0
  691. package/runtime/pmtiles-protocol.d.ts +77 -0
  692. package/runtime/pmtiles-protocol.d.ts.map +1 -0
  693. package/runtime/pmtiles-protocol.js +120 -0
  694. package/runtime/popups.d.ts +62 -0
  695. package/runtime/popups.d.ts.map +1 -0
  696. package/runtime/popups.js +95 -0
  697. package/runtime/query-tiles.d.ts +217 -0
  698. package/runtime/query-tiles.d.ts.map +1 -0
  699. package/runtime/query-tiles.js +801 -0
  700. package/runtime/runtime.d.ts +243 -0
  701. package/runtime/runtime.d.ts.map +1 -0
  702. package/runtime/runtime.js +1147 -0
  703. package/runtime/source-bridge.d.ts +99 -0
  704. package/runtime/source-bridge.d.ts.map +1 -0
  705. package/runtime/source-bridge.js +428 -0
  706. package/runtime/style-compose.d.ts +46 -0
  707. package/runtime/style-compose.d.ts.map +1 -0
  708. package/runtime/style-compose.js +144 -0
  709. package/runtime/style-interactions.d.ts +141 -0
  710. package/runtime/style-interactions.d.ts.map +1 -0
  711. package/runtime/style-interactions.js +574 -0
  712. package/runtime/style-spec-validation.d.ts +23 -0
  713. package/runtime/style-spec-validation.d.ts.map +1 -0
  714. package/runtime/style-spec-validation.js +357 -0
  715. package/scene-workspace/analysis-widgets.d.ts +334 -0
  716. package/scene-workspace/analysis-widgets.d.ts.map +1 -0
  717. package/scene-workspace/analysis-widgets.js +424 -0
  718. package/scene-workspace/cesium-adapter.d.ts +438 -0
  719. package/scene-workspace/cesium-adapter.d.ts.map +1 -0
  720. package/scene-workspace/cesium-adapter.js +493 -0
  721. package/scene-workspace/index.d.ts +21 -0
  722. package/scene-workspace/index.d.ts.map +1 -0
  723. package/scene-workspace/index.js +14 -0
  724. package/scene-workspace/primitives.d.ts +162 -0
  725. package/scene-workspace/primitives.d.ts.map +1 -0
  726. package/scene-workspace/primitives.js +255 -0
  727. package/scene-workspace/scene-discovery.d.ts +196 -0
  728. package/scene-workspace/scene-discovery.d.ts.map +1 -0
  729. package/scene-workspace/scene-discovery.js +228 -0
  730. package/scene-workspace/scene-view.d.ts +209 -0
  731. package/scene-workspace/scene-view.d.ts.map +1 -0
  732. package/scene-workspace/scene-view.js +267 -0
  733. package/scene-workspace/types.d.ts +229 -0
  734. package/scene-workspace/types.d.ts.map +1 -0
  735. package/scene-workspace/types.js +23 -0
  736. package/scene-workspace/workspace.d.ts +13 -0
  737. package/scene-workspace/workspace.d.ts.map +1 -0
  738. package/scene-workspace/workspace.js +391 -0
  739. package/share/denial.d.ts +78 -0
  740. package/share/denial.d.ts.map +1 -0
  741. package/share/denial.js +61 -0
  742. package/share/embed-token.d.ts +71 -0
  743. package/share/embed-token.d.ts.map +1 -0
  744. package/share/embed-token.js +99 -0
  745. package/share/index.d.ts +35 -0
  746. package/share/index.d.ts.map +1 -0
  747. package/share/index.js +30 -0
  748. package/share/open-data.d.ts +114 -0
  749. package/share/open-data.d.ts.map +1 -0
  750. package/share/open-data.js +81 -0
  751. package/share/types.d.ts +163 -0
  752. package/share/types.d.ts.map +1 -0
  753. package/share/types.js +17 -0
  754. package/studio/capability-manifest.d.ts +285 -0
  755. package/studio/capability-manifest.d.ts.map +1 -0
  756. package/studio/capability-manifest.js +59 -0
  757. package/studio/chart-spec.d.ts +85 -0
  758. package/studio/chart-spec.d.ts.map +1 -0
  759. package/studio/chart-spec.js +106 -0
  760. package/studio/index.d.ts +34 -0
  761. package/studio/index.d.ts.map +1 -0
  762. package/studio/index.js +27 -0
  763. package/studio/provenance.d.ts +131 -0
  764. package/studio/provenance.d.ts.map +1 -0
  765. package/studio/provenance.js +39 -0
  766. package/studio/publish.d.ts +64 -0
  767. package/studio/publish.d.ts.map +1 -0
  768. package/studio/publish.js +13 -0
  769. package/studio/types.d.ts +278 -0
  770. package/studio/types.d.ts.map +1 -0
  771. package/studio/types.js +71 -0
  772. package/studio/validate.d.ts +45 -0
  773. package/studio/validate.d.ts.map +1 -0
  774. package/studio/validate.js +255 -0
  775. package/studio/validation.d.ts +112 -0
  776. package/studio/validation.d.ts.map +1 -0
  777. package/studio/validation.js +42 -0
  778. package/style/factory.d.ts +30 -0
  779. package/style/factory.d.ts.map +1 -0
  780. package/style/factory.js +61 -0
  781. package/style/index.d.ts +25 -0
  782. package/style/index.d.ts.map +1 -0
  783. package/style/index.js +24 -0
  784. package/style/specification.d.ts +203 -0
  785. package/style/specification.d.ts.map +1 -0
  786. package/style/specification.js +178 -0
  787. package/style/wms-wmts-resolvers.d.ts +38 -0
  788. package/style/wms-wmts-resolvers.d.ts.map +1 -0
  789. package/style/wms-wmts-resolvers.js +92 -0
  790. package/web-components/controller.d.ts +39 -0
  791. package/web-components/controller.d.ts.map +1 -0
  792. package/web-components/controller.js +640 -0
  793. package/web-components/elements.d.ts +210 -0
  794. package/web-components/elements.d.ts.map +1 -0
  795. package/web-components/elements.js +1651 -0
  796. package/web-components/index.d.ts +24 -0
  797. package/web-components/index.d.ts.map +1 -0
  798. package/web-components/index.js +22 -0
  799. package/web-components/maplibre-renderer.d.ts +22 -0
  800. package/web-components/maplibre-renderer.d.ts.map +1 -0
  801. package/web-components/maplibre-renderer.js +474 -0
  802. package/web-components/types.d.ts +397 -0
  803. package/web-components/types.d.ts.map +1 -0
  804. package/web-components/types.js +1 -0
  805. package/webmap/contract.d.ts +28 -0
  806. package/webmap/contract.d.ts.map +1 -0
  807. package/webmap/contract.js +130 -0
  808. package/webmap/convert-basemap.d.ts +17 -0
  809. package/webmap/convert-basemap.d.ts.map +1 -0
  810. package/webmap/convert-basemap.js +78 -0
  811. package/webmap/convert-extent.d.ts +17 -0
  812. package/webmap/convert-extent.d.ts.map +1 -0
  813. package/webmap/convert-extent.js +114 -0
  814. package/webmap/convert-label.d.ts +13 -0
  815. package/webmap/convert-label.d.ts.map +1 -0
  816. package/webmap/convert-label.js +125 -0
  817. package/webmap/convert-layer.d.ts +22 -0
  818. package/webmap/convert-layer.d.ts.map +1 -0
  819. package/webmap/convert-layer.js +181 -0
  820. package/webmap/convert-popup.d.ts +34 -0
  821. package/webmap/convert-popup.d.ts.map +1 -0
  822. package/webmap/convert-popup.js +68 -0
  823. package/webmap/convert-renderer.d.ts +17 -0
  824. package/webmap/convert-renderer.d.ts.map +1 -0
  825. package/webmap/convert-renderer.js +161 -0
  826. package/webmap/convert-symbol.d.ts +17 -0
  827. package/webmap/convert-symbol.d.ts.map +1 -0
  828. package/webmap/convert-symbol.js +122 -0
  829. package/webmap/index.d.ts +44 -0
  830. package/webmap/index.d.ts.map +1 -0
  831. package/webmap/index.js +33 -0
  832. package/webmap/parse.d.ts +25 -0
  833. package/webmap/parse.d.ts.map +1 -0
  834. package/webmap/parse.js +83 -0
  835. package/webmap/types.d.ts +264 -0
  836. package/webmap/types.d.ts.map +1 -0
  837. package/webmap/types.js +13 -0
  838. package/webmap/warnings.d.ts +30 -0
  839. package/webmap/warnings.d.ts.map +1 -0
  840. package/webmap/warnings.js +37 -0
@@ -0,0 +1,1651 @@
1
+ import { createHonuaWebComponentController } from "./controller.js";
2
+ import { HonuaMapLibreRenderer } from "./maplibre-renderer.js";
3
+ const globalDom = globalThis;
4
+ const HTMLElementBase = globalDom.HTMLElement ?? class {
5
+ };
6
+ class HonuaElementBase extends HTMLElementBase {
7
+ #controller;
8
+ #unsubscribe;
9
+ #controllerReadyListener;
10
+ state;
11
+ get controller() {
12
+ return this.#controller;
13
+ }
14
+ set controller(controller) {
15
+ if (this.#controller === controller)
16
+ return;
17
+ this.#unsubscribe?.remove();
18
+ this.#unsubscribe = undefined;
19
+ this.#controller = controller;
20
+ this.state = controller?.getState();
21
+ if (controller) {
22
+ this.#unsubscribe = controller.subscribe((state) => {
23
+ this.state = state;
24
+ this.stateChanged(state);
25
+ this.render();
26
+ });
27
+ }
28
+ this.controllerChanged(controller);
29
+ this.render();
30
+ }
31
+ connectedCallback() {
32
+ this.ensureShadowRoot();
33
+ this.listenForControllerReady();
34
+ this.resolveControllerFromContext();
35
+ this.render();
36
+ }
37
+ disconnectedCallback() {
38
+ this.#unsubscribe?.remove();
39
+ this.#unsubscribe = undefined;
40
+ if (this.#controllerReadyListener) {
41
+ this.getRootEventTarget()?.removeEventListener("honua-controller-ready", this.#controllerReadyListener);
42
+ this.#controllerReadyListener = undefined;
43
+ }
44
+ }
45
+ controllerChanged(_controller) { }
46
+ stateChanged(_state) { }
47
+ ensureShadowRoot() {
48
+ if (!this.shadowRoot && typeof this.attachShadow === "function") {
49
+ this.attachShadow({ mode: "open" });
50
+ }
51
+ }
52
+ setShadowHtml(html) {
53
+ this.ensureShadowRoot();
54
+ const root = this.shadowRoot ?? this;
55
+ const focus = captureFocus(root);
56
+ root.innerHTML = html;
57
+ restoreFocus(root, focus);
58
+ }
59
+ resolveControllerFromContext() {
60
+ if (this.controller)
61
+ return;
62
+ const mapId = this.getAttribute("for");
63
+ const root = this.getRootNode?.();
64
+ const map = mapId
65
+ ? getElementById(root, mapId)
66
+ : typeof root?.querySelector === "function"
67
+ ? root.querySelector("honua-map")
68
+ : undefined;
69
+ const controller = map?.controller;
70
+ if (controller)
71
+ this.controller = controller;
72
+ }
73
+ listenForControllerReady() {
74
+ if (this.#controllerReadyListener)
75
+ return;
76
+ const target = this.getRootEventTarget();
77
+ if (!target)
78
+ return;
79
+ this.#controllerReadyListener = (event) => {
80
+ const detail = event.detail;
81
+ if (!detail?.controller)
82
+ return;
83
+ const mapId = this.getAttribute("for");
84
+ if (mapId && event.target?.id !== mapId)
85
+ return;
86
+ if (!mapId && this.controller)
87
+ return;
88
+ this.controller = detail.controller;
89
+ };
90
+ target.addEventListener("honua-controller-ready", this.#controllerReadyListener);
91
+ }
92
+ dispatchTypedEvent(name, detail) {
93
+ if (!globalDom.CustomEvent || typeof this.dispatchEvent !== "function")
94
+ return;
95
+ this.dispatchEvent(new globalDom.CustomEvent(name, { bubbles: true, composed: true, detail }));
96
+ }
97
+ getRootEventTarget() {
98
+ const root = this.getRootNode?.();
99
+ if (root && "addEventListener" in root)
100
+ return root;
101
+ return typeof document !== "undefined" ? document : undefined;
102
+ }
103
+ }
104
+ export class HonuaMapElement extends HonuaElementBase {
105
+ static get observedAttributes() {
106
+ return ["map-package", "package-url", "src", "label"];
107
+ }
108
+ #options = {};
109
+ #client;
110
+ #packageUrl;
111
+ #renderer;
112
+ #packageLoadToken = 0;
113
+ #packageLoading = false;
114
+ #packageLoadError;
115
+ get map() {
116
+ return this.#renderer?.map;
117
+ }
118
+ get runtime() {
119
+ return this.#renderer?.runtime;
120
+ }
121
+ get client() {
122
+ return this.#client;
123
+ }
124
+ set client(client) {
125
+ this.#client = client;
126
+ void this.syncRenderer();
127
+ }
128
+ get packageUrl() {
129
+ return this.#packageUrl;
130
+ }
131
+ set packageUrl(value) {
132
+ this.#packageUrl = value?.trim() || undefined;
133
+ this.#packageLoadError = undefined;
134
+ this.#packageLoading = Boolean(this.#packageUrl);
135
+ this.render();
136
+ if (this.#packageUrl)
137
+ void this.loadPackageFromUrl(this.#packageUrl);
138
+ }
139
+ get mapPackage() {
140
+ return this.#options.mapPackage;
141
+ }
142
+ set mapPackage(mapPackage) {
143
+ this.#options = { ...this.#options, ...(mapPackage ? { mapPackage } : { mapPackage: undefined }) };
144
+ if (mapPackage) {
145
+ this.#packageLoading = false;
146
+ this.#packageLoadError = undefined;
147
+ }
148
+ if (mapPackage) {
149
+ this.controller = createHonuaWebComponentController(this.#options);
150
+ }
151
+ else if (!this.controller) {
152
+ this.ensureController();
153
+ }
154
+ void this.syncRenderer();
155
+ this.render();
156
+ }
157
+ get featuresBySource() {
158
+ return this.#options.featuresBySource;
159
+ }
160
+ set featuresBySource(featuresBySource) {
161
+ this.#options = {
162
+ ...this.#options,
163
+ ...(featuresBySource ? { featuresBySource } : { featuresBySource: undefined }),
164
+ };
165
+ if (this.controller?.updateFeatures && featuresBySource) {
166
+ for (const [sourceId, features] of Object.entries(featuresBySource)) {
167
+ this.controller.updateFeatures(sourceId, features);
168
+ }
169
+ }
170
+ else if (!this.controller) {
171
+ this.ensureController();
172
+ }
173
+ this.render();
174
+ }
175
+ attributeChangedCallback(name, _oldValue, newValue) {
176
+ if (name === "map-package" && newValue) {
177
+ try {
178
+ this.mapPackage = JSON.parse(newValue);
179
+ }
180
+ catch {
181
+ this.#packageLoading = false;
182
+ this.#packageLoadError = "Invalid map-package JSON.";
183
+ this.dispatchTypedEvent("honua-map-error", {
184
+ error: new Error("Invalid map-package JSON."),
185
+ message: "Invalid map-package JSON.",
186
+ });
187
+ }
188
+ }
189
+ if ((name === "package-url" || name === "src") && newValue !== null) {
190
+ this.packageUrl = newValue;
191
+ }
192
+ this.render();
193
+ }
194
+ connectedCallback() {
195
+ super.connectedCallback();
196
+ this.ensureController();
197
+ if (this.#packageUrl && !this.state?.mapPackage)
198
+ void this.loadPackageFromUrl(this.#packageUrl);
199
+ void this.syncRenderer();
200
+ }
201
+ disconnectedCallback() {
202
+ this.#packageLoadToken += 1;
203
+ this.#renderer?.disconnect();
204
+ this.#renderer = undefined;
205
+ super.disconnectedCallback();
206
+ }
207
+ controllerChanged(controller) {
208
+ if (controller) {
209
+ this.dispatchTypedEvent("honua-controller-ready", { controller });
210
+ }
211
+ void this.syncRenderer();
212
+ }
213
+ stateChanged(state) {
214
+ void this.#renderer?.applyState(state);
215
+ }
216
+ render() {
217
+ const state = this.state ?? this.controller?.getState();
218
+ const layers = state?.layers ?? [];
219
+ const viewport = state?.viewport ?? {};
220
+ const visibleLayers = layers.filter((layer) => layer.visible);
221
+ const label = this.getAttribute("label") ?? state?.mapPackage?.mapPackageId ?? "Honua map";
222
+ const root = this.shadowRoot ?? this;
223
+ if (!root.querySelector?.(".map")) {
224
+ this.setShadowHtml(`
225
+ <style>${baseStyles()}${mapStyles()}</style>
226
+ <section part="map" class="map" role="region" aria-label="${escapeHtml(label)}" tabindex="0">
227
+ <div class="map__chrome">
228
+ <div class="map__title"></div>
229
+ <div class="map__controls" aria-label="Map controls">
230
+ <button type="button" class="icon-button" data-zoom="out" aria-label="Zoom out">-</button>
231
+ <output class="zoom" aria-label="Zoom">0</output>
232
+ <button type="button" class="icon-button" data-zoom="in" aria-label="Zoom in">+</button>
233
+ </div>
234
+ </div>
235
+ <div class="map__canvas" part="canvas">
236
+ <div class="map__renderer" part="renderer"></div>
237
+ <div class="map__status" aria-live="polite"></div>
238
+ </div>
239
+ <div class="map__footer">
240
+ <span data-visible-layers>0 visible</span>
241
+ <span data-center>No center</span>
242
+ </div>
243
+ </section>
244
+ `);
245
+ this.bindMapChrome();
246
+ }
247
+ const nextRoot = this.shadowRoot ?? this;
248
+ nextRoot.querySelector(".map")?.setAttribute("aria-label", label);
249
+ setText(nextRoot.querySelector(".map__title"), label);
250
+ setText(nextRoot.querySelector(".zoom"), String(viewport.zoom?.toFixed?.(1) ?? viewport.zoom ?? 0));
251
+ setText(nextRoot.querySelector("[data-visible-layers]"), `${String(visibleLayers.length)} visible`);
252
+ setText(nextRoot.querySelector("[data-center]"), viewport.center ? viewport.center.join(", ") : "No center");
253
+ setText(nextRoot.querySelector(".map__status"), this.mapStatusText(state));
254
+ void this.syncRenderer();
255
+ }
256
+ ensureController() {
257
+ if (this.controller)
258
+ return;
259
+ this.controller = createHonuaWebComponentController(this.#options);
260
+ }
261
+ bindMapChrome() {
262
+ this.shadowRoot?.querySelectorAll("[data-zoom]").forEach((button) => {
263
+ button.addEventListener("click", () => {
264
+ const direction = button.dataset.zoom === "in" ? 1 : -1;
265
+ const nextZoom = (this.controller?.getState().viewport.zoom ?? 0) + direction;
266
+ this.controller?.setViewport({ zoom: nextZoom });
267
+ this.dispatchTypedEvent("honua-viewport-change", { zoom: nextZoom });
268
+ });
269
+ });
270
+ }
271
+ async syncRenderer() {
272
+ if (!this.isConnected || !this.controller)
273
+ return;
274
+ const container = this.shadowRoot?.querySelector(".map__renderer");
275
+ if (!container)
276
+ return;
277
+ if (!this.#renderer) {
278
+ this.#renderer = new HonuaMapLibreRenderer({
279
+ container,
280
+ getClient: () => this.#client,
281
+ getController: () => this.controller,
282
+ onReady: (detail) => {
283
+ this.dispatchTypedEvent("honua-map-ready", detail);
284
+ this.render();
285
+ },
286
+ onError: (detail) => {
287
+ this.dispatchTypedEvent("honua-map-error", detail);
288
+ setText(this.shadowRoot?.querySelector(".map__status"), detail.message);
289
+ },
290
+ onViewport: (detail) => {
291
+ this.dispatchTypedEvent("honua-viewport-change", detail);
292
+ this.render();
293
+ },
294
+ onClick: (detail) => this.dispatchTypedEvent("honua-map-click", detail),
295
+ onHover: (detail) => this.dispatchTypedEvent("honua-map-hover", detail),
296
+ onSelection: (detail) => this.dispatchTypedEvent("honua-selection-change", detail),
297
+ });
298
+ }
299
+ const state = this.controller.getState();
300
+ this.state = state;
301
+ await this.#renderer.applyState(state);
302
+ }
303
+ async loadPackageFromUrl(locator) {
304
+ const token = ++this.#packageLoadToken;
305
+ this.#packageLoading = true;
306
+ this.#packageLoadError = undefined;
307
+ this.render();
308
+ try {
309
+ const [{ fetchMapPackage }, { HonuaClient }] = await Promise.all([
310
+ import("../runtime/index.js"),
311
+ import("../core/client.js"),
312
+ ]);
313
+ if (token !== this.#packageLoadToken)
314
+ return;
315
+ const client = this.#client ?? new HonuaClient({ baseUrl: browserOrigin() });
316
+ const result = await fetchMapPackage(locator, {
317
+ client,
318
+ requireStyleRefResolution: false,
319
+ allowInvalid: false,
320
+ });
321
+ if (token !== this.#packageLoadToken)
322
+ return;
323
+ this.mapPackage = result.mapPackage;
324
+ this.#packageLoading = false;
325
+ this.#packageLoadError = undefined;
326
+ await this.syncRenderer();
327
+ this.render();
328
+ }
329
+ catch (error) {
330
+ if (token !== this.#packageLoadToken)
331
+ return;
332
+ this.#packageLoading = false;
333
+ this.#packageLoadError = error instanceof Error ? error.message : String(error);
334
+ this.dispatchTypedEvent("honua-map-error", {
335
+ error,
336
+ message: this.#packageLoadError,
337
+ });
338
+ this.render();
339
+ }
340
+ }
341
+ mapStatusText(state) {
342
+ if (this.#packageLoadError)
343
+ return this.#packageLoadError;
344
+ if (state?.mapPackage)
345
+ return "";
346
+ if (this.#packageLoading || this.#packageUrl)
347
+ return "Loading map package";
348
+ return "No map package";
349
+ }
350
+ }
351
+ export class HonuaLayerListElement extends HonuaElementBase {
352
+ static get observedAttributes() {
353
+ return ["for", "label"];
354
+ }
355
+ attributeChangedCallback() {
356
+ this.resolveControllerFromContext();
357
+ this.render();
358
+ }
359
+ render() {
360
+ const layers = this.state?.layers ?? [];
361
+ const label = this.getAttribute("label") ?? "Layers";
362
+ this.setShadowHtml(`
363
+ <style>${baseStyles()}${listStyles()}</style>
364
+ <fieldset class="panel" part="panel">
365
+ <legend>${escapeHtml(label)}</legend>
366
+ <div class="stack" role="list">
367
+ ${layers.length === 0
368
+ ? `<p class="empty">No layers</p>`
369
+ : layers
370
+ .map((layer) => `
371
+ <label class="check-row" role="listitem">
372
+ <input type="checkbox" data-layer-id="${escapeHtml(layer.id)}" ${layer.visible ? "checked" : ""} />
373
+ <span>${escapeHtml(layer.title)}</span>
374
+ </label>
375
+ `)
376
+ .join("")}
377
+ </div>
378
+ </fieldset>
379
+ `);
380
+ this.shadowRoot?.querySelectorAll("input[data-layer-id]").forEach((input) => {
381
+ input.addEventListener("change", () => {
382
+ const layerId = input.dataset.layerId;
383
+ if (!layerId)
384
+ return;
385
+ this.controller?.setLayerVisibility(layerId, input.checked);
386
+ this.dispatchTypedEvent("honua-layer-visibility-change", {
387
+ layerId,
388
+ visible: input.checked,
389
+ });
390
+ });
391
+ });
392
+ }
393
+ }
394
+ export class HonuaLegendElement extends HonuaElementBase {
395
+ static get observedAttributes() {
396
+ return ["for", "label"];
397
+ }
398
+ attributeChangedCallback() {
399
+ this.resolveControllerFromContext();
400
+ this.render();
401
+ }
402
+ render() {
403
+ const legend = this.state?.legend ?? [];
404
+ const label = this.getAttribute("label") ?? "Legend";
405
+ this.setShadowHtml(`
406
+ <style>${baseStyles()}${listStyles()}</style>
407
+ <section class="panel" part="panel" aria-label="${escapeHtml(label)}">
408
+ <h2>${escapeHtml(label)}</h2>
409
+ <ul class="legend">
410
+ ${legend.length === 0
411
+ ? `<li class="empty">No legend</li>`
412
+ : legend
413
+ .map((item) => `
414
+ <li>
415
+ ${item.iconUrl
416
+ ? `<img class="swatch" alt="" src="${escapeAttribute(item.iconUrl)}" />`
417
+ : `<span class="swatch" style="--swatch:${escapeAttribute(item.color ?? "#64748b")}"></span>`}
418
+ <span>${escapeHtml(item.label)}</span>
419
+ </li>
420
+ `)
421
+ .join("")}
422
+ </ul>
423
+ </section>
424
+ `);
425
+ }
426
+ }
427
+ export class HonuaFeatureTableElement extends HonuaElementBase {
428
+ static get observedAttributes() {
429
+ return ["for", "source", "fields", "page-size", "filter-text", "label"];
430
+ }
431
+ #model;
432
+ #refreshToken = 0;
433
+ attributeChangedCallback(name, _oldValue, newValue) {
434
+ this.resolveControllerFromContext();
435
+ if (name === "filter-text") {
436
+ const detail = {
437
+ sourceId: this.sourceId(),
438
+ text: newValue ?? "",
439
+ };
440
+ this.controller?.setFilter(detail);
441
+ this.dispatchTypedEvent("honua-filter-change", detail);
442
+ }
443
+ void this.refresh();
444
+ }
445
+ connectedCallback() {
446
+ super.connectedCallback();
447
+ void this.refresh();
448
+ }
449
+ stateChanged() {
450
+ void this.refresh();
451
+ }
452
+ async refresh() {
453
+ const controller = this.controller;
454
+ if (!controller)
455
+ return undefined;
456
+ const token = ++this.#refreshToken;
457
+ const model = await controller.queryFeatures(this.sourceId(), {
458
+ fields: this.fields(),
459
+ pagination: { limit: this.pageSize() },
460
+ });
461
+ if (token !== this.#refreshToken)
462
+ return this.#model;
463
+ this.#model = model;
464
+ this.render();
465
+ return model;
466
+ }
467
+ render() {
468
+ const state = this.state;
469
+ const model = this.#model ?? tableModelFromState(state, this.sourceId(), this.fields(), this.pageSize());
470
+ const selectedId = state?.selection?.featureId;
471
+ const label = this.getAttribute("label") ?? "Features";
472
+ this.setShadowHtml(`
473
+ <style>${baseStyles()}${tableStyles()}</style>
474
+ <section class="table-panel" part="panel" aria-label="${escapeHtml(label)}">
475
+ <div class="table-panel__bar">
476
+ <h2>${escapeHtml(label)}</h2>
477
+ <span>${escapeHtml(String(model.totalCount))}</span>
478
+ </div>
479
+ <div class="table-wrap">
480
+ <table role="grid" aria-rowcount="${escapeHtml(String(model.rows.length))}">
481
+ <thead>
482
+ <tr>${model.fields.map((field) => `<th scope="col">${escapeHtml(field)}</th>`).join("")}</tr>
483
+ </thead>
484
+ <tbody>
485
+ ${model.rows.length === 0
486
+ ? `<tr><td colspan="${Math.max(1, model.fields.length)}" class="empty">No rows</td></tr>`
487
+ : model.rows
488
+ .map((row) => `
489
+ <tr tabindex="0" data-source-id="${escapeHtml(row.sourceId)}" data-feature-id="${escapeHtml(String(row.id))}" aria-selected="${String(String(selectedId ?? "") === String(row.id))}">
490
+ ${model.fields.map((field) => `<td>${escapeHtml(formatCell(row.attributes[field]))}</td>`).join("")}
491
+ </tr>
492
+ `)
493
+ .join("")}
494
+ </tbody>
495
+ </table>
496
+ </div>
497
+ </section>
498
+ `);
499
+ this.shadowRoot?.querySelectorAll("tbody tr[data-feature-id]").forEach((row) => {
500
+ const select = () => this.selectRow(row);
501
+ row.addEventListener("click", select);
502
+ row.addEventListener("keydown", (event) => {
503
+ if (event.key !== "Enter" && event.key !== " ")
504
+ return;
505
+ event.preventDefault();
506
+ select();
507
+ });
508
+ });
509
+ }
510
+ selectRow(row) {
511
+ const sourceId = row.dataset.sourceId;
512
+ const featureId = row.dataset.featureId;
513
+ if (!sourceId || featureId === undefined)
514
+ return;
515
+ const feature = (this.#model?.rows ?? []).find((candidate) => String(candidate.id) === featureId);
516
+ this.controller?.selectFeature({ sourceId, featureId, ...(feature ? { feature } : {}) });
517
+ this.dispatchTypedEvent("honua-selection-change", {
518
+ sourceId,
519
+ featureId,
520
+ ...(feature ? { feature } : {}),
521
+ });
522
+ }
523
+ sourceId() {
524
+ return this.getAttribute("source") ?? undefined;
525
+ }
526
+ fields() {
527
+ const value = this.getAttribute("fields");
528
+ return value
529
+ ?.split(",")
530
+ .map((field) => field.trim())
531
+ .filter(Boolean);
532
+ }
533
+ pageSize() {
534
+ const parsed = Number(this.getAttribute("page-size"));
535
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
536
+ }
537
+ }
538
+ export class HonuaSearchElement extends HonuaElementBase {
539
+ static get observedAttributes() {
540
+ return ["for", "source", "placeholder", "label"];
541
+ }
542
+ #query = "";
543
+ #results = [];
544
+ attributeChangedCallback() {
545
+ this.resolveControllerFromContext();
546
+ this.render();
547
+ }
548
+ render() {
549
+ const label = this.getAttribute("label") ?? "Search";
550
+ const placeholder = this.getAttribute("placeholder") ?? "Search";
551
+ this.setShadowHtml(`
552
+ <style>${baseStyles()}${searchStyles()}</style>
553
+ <section class="search" part="panel" aria-label="${escapeHtml(label)}">
554
+ <form>
555
+ <label class="sr-only" for="honua-search-input">${escapeHtml(label)}</label>
556
+ <input id="honua-search-input" name="q" value="${escapeAttribute(this.#query)}" placeholder="${escapeAttribute(placeholder)}" autocomplete="off" />
557
+ <button type="submit">Search</button>
558
+ </form>
559
+ <ul class="results" aria-live="polite">
560
+ ${this.#results.map((result) => `<li><button type="button" data-result-id="${escapeHtml(result.id)}">${escapeHtml(result.label)}</button></li>`).join("")}
561
+ </ul>
562
+ </section>
563
+ `);
564
+ this.shadowRoot?.querySelector("form")?.addEventListener("submit", (event) => {
565
+ event.preventDefault();
566
+ const input = this.shadowRoot?.querySelector("input[name='q']");
567
+ void this.runSearch(input?.value ?? "");
568
+ });
569
+ this.shadowRoot?.querySelectorAll("button[data-result-id]").forEach((button) => {
570
+ button.addEventListener("click", () => {
571
+ const result = this.#results.find((candidate) => candidate.id === button.dataset.resultId);
572
+ if (!result?.featureId || !result.sourceId)
573
+ return;
574
+ this.controller?.selectFeature({
575
+ sourceId: result.sourceId,
576
+ featureId: result.featureId,
577
+ ...(result.feature ? { feature: result.feature } : {}),
578
+ });
579
+ this.dispatchTypedEvent("honua-selection-change", {
580
+ sourceId: result.sourceId,
581
+ featureId: result.featureId,
582
+ ...(result.feature ? { feature: result.feature } : {}),
583
+ });
584
+ });
585
+ });
586
+ }
587
+ async runSearch(query) {
588
+ this.#query = query;
589
+ const sourceId = this.getAttribute("source") ?? undefined;
590
+ this.#results = await (this.controller?.search(query, { sourceId }) ?? []);
591
+ this.dispatchTypedEvent("honua-search", { query, results: this.#results });
592
+ this.render();
593
+ }
594
+ }
595
+ export class HonuaEditorElement extends HonuaElementBase {
596
+ static get observedAttributes() {
597
+ return ["for", "source", "label"];
598
+ }
599
+ #model;
600
+ get editorModel() {
601
+ return this.#model ?? this.state?.editor;
602
+ }
603
+ set editorModel(model) {
604
+ this.#model = model;
605
+ this.render();
606
+ }
607
+ attributeChangedCallback() {
608
+ this.resolveControllerFromContext();
609
+ this.render();
610
+ }
611
+ render() {
612
+ const state = this.state;
613
+ const model = this.#model ?? state?.editor ?? defaultEditorModel(this.getAttribute("source") ?? undefined);
614
+ const selected = state?.selection?.feature;
615
+ const canUpdate = model.capabilities.canUpdate && !model.capabilities.readOnly;
616
+ const label = this.getAttribute("label") ?? "Editor";
617
+ this.setShadowHtml(`
618
+ <style>${baseStyles()}${editorStyles()}</style>
619
+ <section class="editor" part="panel" aria-label="${escapeHtml(label)}">
620
+ <div class="editor__bar">
621
+ <h2>${escapeHtml(label)}</h2>
622
+ <span data-status>${escapeHtml(model.status)}</span>
623
+ </div>
624
+ <p class="selection">${escapeHtml(selected?.title ?? "No selection")}</p>
625
+ <p class="muted">${escapeHtml(model.capabilities.readOnly ? (model.capabilities.reason ?? "Read-only") : "Editable")}</p>
626
+ <div class="editor__actions">
627
+ <button type="button" data-action="new" ${model.capabilities.canCreate && !model.capabilities.readOnly ? "" : "disabled"}>New</button>
628
+ <button type="button" data-action="save" ${canUpdate ? "" : "disabled"}>Save</button>
629
+ <button type="button" data-action="delete" ${model.capabilities.canDelete && !model.capabilities.readOnly ? "" : "disabled"}>Delete</button>
630
+ </div>
631
+ </section>
632
+ `);
633
+ this.shadowRoot?.querySelectorAll("button[data-action]").forEach((button) => {
634
+ button.addEventListener("click", () => {
635
+ void this.runEdit(button.dataset.action ?? "update", model);
636
+ });
637
+ });
638
+ }
639
+ async runEdit(action, model) {
640
+ const feature = this.state?.selection?.feature;
641
+ const sourceId = this.getAttribute("source") ?? model.sourceId ?? feature?.sourceId;
642
+ if (!feature || !sourceId)
643
+ return;
644
+ const operation = action === "new" ? "create" : action === "delete" ? "delete" : "update";
645
+ const request = { sourceId, feature, operation };
646
+ const next = await (this.controller?.applyEdit?.(request) ??
647
+ Promise.resolve({ ...model, status: "unsupported" }));
648
+ this.#model = next;
649
+ this.dispatchTypedEvent("honua-edit-change", {
650
+ status: next.status,
651
+ request,
652
+ model: next,
653
+ });
654
+ this.render();
655
+ }
656
+ }
657
+ export class HonuaChartElement extends HonuaElementBase {
658
+ static get observedAttributes() {
659
+ return ["for", "label"];
660
+ }
661
+ #model;
662
+ get chartModel() {
663
+ return this.#model ?? this.state?.chart;
664
+ }
665
+ set chartModel(model) {
666
+ this.#model = model;
667
+ this.render();
668
+ }
669
+ attributeChangedCallback() {
670
+ this.resolveControllerFromContext();
671
+ this.render();
672
+ }
673
+ render() {
674
+ const model = this.chartModel ?? defaultChartModel(this.getAttribute("label") ?? "Chart");
675
+ const max = Math.max(1, ...(model.data ?? []).map((datum) => datum.value));
676
+ this.setShadowHtml(`
677
+ <style>${baseStyles()}${chartStyles()}</style>
678
+ <section class="chart" part="panel" aria-label="${escapeHtml(model.title)}">
679
+ <h2>${escapeHtml(model.title)}</h2>
680
+ <div class="bars">
681
+ ${model.data?.length
682
+ ? model.data
683
+ .map((datum) => `
684
+ <div class="bar-row">
685
+ <span>${escapeHtml(datum.label)}</span>
686
+ <span class="bar" style="--bar:${(datum.value / max) * 100}%;--bar-color:${escapeAttribute(datum.color ?? "#2563eb")}"></span>
687
+ <strong>${escapeHtml(String(datum.value))}</strong>
688
+ </div>
689
+ `)
690
+ .join("")
691
+ : `<p class="empty">${escapeHtml(model.message ?? "No chart data")}</p>`}
692
+ </div>
693
+ </section>
694
+ `);
695
+ }
696
+ }
697
+ export class HonuaBasemapControlElement extends HonuaElementBase {
698
+ static get observedAttributes() {
699
+ return ["for", "label"];
700
+ }
701
+ #activeBasemapId;
702
+ attributeChangedCallback() {
703
+ this.resolveControllerFromContext();
704
+ this.render();
705
+ }
706
+ render() {
707
+ const label = this.getAttribute("label") ?? "Basemaps";
708
+ const basemaps = basemapsFromState(this.state);
709
+ const active = this.#activeBasemapId ?? basemaps.find((basemap) => basemap.visible)?.id ?? basemaps[0]?.id;
710
+ this.setShadowHtml(`
711
+ <style>${baseStyles()}${controlPanelStyles()}</style>
712
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
713
+ <div class="control-panel__bar">
714
+ <h2>${escapeHtml(label)}</h2>
715
+ <span>${escapeHtml(basemaps.length >= 2 ? "ready" : "unsupported")}</span>
716
+ </div>
717
+ ${basemaps.length < 2
718
+ ? `<p class="empty" role="status">At least two basemap layers are required.</p>`
719
+ : `<div class="segmented" role="group" aria-label="${escapeAttribute(label)}">
720
+ ${basemaps
721
+ .map((basemap) => `
722
+ <button type="button" data-basemap-id="${escapeAttribute(basemap.id)}" aria-pressed="${String(basemap.id === active)}">${escapeHtml(basemap.title)}</button>
723
+ `)
724
+ .join("")}
725
+ </div>`}
726
+ </section>
727
+ `);
728
+ this.shadowRoot?.querySelectorAll("button[data-basemap-id]").forEach((button) => {
729
+ button.addEventListener("click", () => this.selectBasemap(button.dataset.basemapId));
730
+ });
731
+ }
732
+ selectBasemap(basemapId) {
733
+ if (!basemapId)
734
+ return;
735
+ const previousBasemapId = this.#activeBasemapId;
736
+ this.#activeBasemapId = basemapId;
737
+ for (const basemap of basemapsFromState(this.state)) {
738
+ this.controller?.setLayerVisibility(basemap.id, basemap.id === basemapId);
739
+ }
740
+ this.dispatchTypedEvent("honua-basemap-change", {
741
+ basemapId,
742
+ ...(previousBasemapId ? { previousBasemapId } : {}),
743
+ status: "ready",
744
+ });
745
+ this.render();
746
+ }
747
+ }
748
+ export class HonuaBookmarksElement extends HonuaElementBase {
749
+ static get observedAttributes() {
750
+ return ["for", "label", "bookmarks"];
751
+ }
752
+ attributeChangedCallback() {
753
+ this.resolveControllerFromContext();
754
+ this.render();
755
+ }
756
+ render() {
757
+ const label = this.getAttribute("label") ?? "Bookmarks";
758
+ const bookmarks = this.bookmarks();
759
+ this.setShadowHtml(`
760
+ <style>${baseStyles()}${controlPanelStyles()}</style>
761
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
762
+ <div class="control-panel__bar">
763
+ <h2>${escapeHtml(label)}</h2>
764
+ <span>${escapeHtml(bookmarks.length > 0 ? "ready" : "unsupported")}</span>
765
+ </div>
766
+ ${bookmarks.length === 0
767
+ ? `<p class="empty" role="status">No initial view or bookmarks are available.</p>`
768
+ : `<div class="button-stack">
769
+ ${bookmarks
770
+ .map((bookmark) => `
771
+ <button type="button" data-bookmark-id="${escapeAttribute(bookmark.id)}">${escapeHtml(bookmark.label)}</button>
772
+ `)
773
+ .join("")}
774
+ </div>`}
775
+ </section>
776
+ `);
777
+ this.shadowRoot?.querySelectorAll("button[data-bookmark-id]").forEach((button) => {
778
+ button.addEventListener("click", () => {
779
+ const bookmark = this.bookmarks().find((candidate) => candidate.id === button.dataset.bookmarkId);
780
+ if (bookmark)
781
+ this.goToBookmark(bookmark);
782
+ });
783
+ });
784
+ }
785
+ bookmarks() {
786
+ const configured = parseBookmarks(this.getAttribute("bookmarks"));
787
+ const home = this.state?.mapPackage?.initialView;
788
+ return [...(home ? [{ id: "home", label: "Home", viewport: home }] : []), ...configured];
789
+ }
790
+ goToBookmark(bookmark) {
791
+ this.controller?.setViewport(bookmark.viewport);
792
+ this.dispatchTypedEvent("honua-bookmark-change", {
793
+ ...bookmark,
794
+ status: "ready",
795
+ });
796
+ this.dispatchTypedEvent("honua-viewport-change", bookmark.viewport);
797
+ }
798
+ }
799
+ export class HonuaLocateControlElement extends HonuaElementBase {
800
+ static get observedAttributes() {
801
+ return ["for", "label", "latitude", "longitude", "zoom"];
802
+ }
803
+ #status = "idle";
804
+ #message = "";
805
+ attributeChangedCallback() {
806
+ this.resolveControllerFromContext();
807
+ this.render();
808
+ }
809
+ render() {
810
+ const label = this.getAttribute("label") ?? "Locate";
811
+ const supported = this.hasConfiguredLocation() || Boolean(globalThis.navigator?.geolocation);
812
+ const status = supported ? this.#status : "unsupported";
813
+ this.setShadowHtml(`
814
+ <style>${baseStyles()}${controlPanelStyles()}</style>
815
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
816
+ <div class="control-panel__bar">
817
+ <h2>${escapeHtml(label)}</h2>
818
+ <span>${escapeHtml(status)}</span>
819
+ </div>
820
+ <button type="button" data-locate ${supported ? "" : "disabled"}>Use location</button>
821
+ <p class="empty" role="status">${escapeHtml(supported ? this.#message || "Centers the shared map controller." : "Geolocation is unavailable.")}</p>
822
+ </section>
823
+ `);
824
+ this.shadowRoot?.querySelector("button[data-locate]")?.addEventListener("click", () => {
825
+ void this.locate();
826
+ });
827
+ }
828
+ async locate() {
829
+ const configured = this.configuredViewport();
830
+ if (configured) {
831
+ this.applyLocation(configured);
832
+ return;
833
+ }
834
+ const geolocation = globalThis.navigator?.geolocation;
835
+ if (!geolocation) {
836
+ this.#status = "unsupported";
837
+ this.#message = "Geolocation is unavailable.";
838
+ this.dispatchTypedEvent("honua-locate-change", {
839
+ status: "unsupported",
840
+ message: this.#message,
841
+ });
842
+ this.render();
843
+ return;
844
+ }
845
+ this.#status = "loading";
846
+ this.#message = "Requesting location.";
847
+ this.render();
848
+ geolocation.getCurrentPosition((position) => {
849
+ this.applyLocation({
850
+ center: [position.coords.longitude, position.coords.latitude],
851
+ zoom: this.zoom(),
852
+ });
853
+ }, (error) => {
854
+ this.#status = "error";
855
+ this.#message = error.message;
856
+ this.dispatchTypedEvent("honua-locate-change", {
857
+ status: "error",
858
+ error,
859
+ message: error.message,
860
+ });
861
+ this.render();
862
+ });
863
+ }
864
+ applyLocation(viewport) {
865
+ this.#status = "ready";
866
+ this.#message = "Location applied.";
867
+ this.controller?.setViewport(viewport);
868
+ this.dispatchTypedEvent("honua-locate-change", { status: "ready", viewport });
869
+ this.dispatchTypedEvent("honua-viewport-change", viewport);
870
+ this.render();
871
+ }
872
+ hasConfiguredLocation() {
873
+ return this.configuredViewport() !== undefined;
874
+ }
875
+ configuredViewport() {
876
+ const latitude = Number(this.getAttribute("latitude"));
877
+ const longitude = Number(this.getAttribute("longitude"));
878
+ if (!Number.isFinite(latitude) || !Number.isFinite(longitude))
879
+ return undefined;
880
+ return { center: [longitude, latitude], zoom: this.zoom() };
881
+ }
882
+ zoom() {
883
+ const zoom = Number(this.getAttribute("zoom"));
884
+ return Number.isFinite(zoom) ? zoom : 14;
885
+ }
886
+ }
887
+ /**
888
+ * `<honua-measure-control>` renders distance/area measuring modes.
889
+ *
890
+ * The control is only interactive when the controller has a measurement
891
+ * geometry provider configured (`measurementGeometry` on
892
+ * {@link CreateHonuaWebComponentControllerOptions}). Without one — for example
893
+ * the bare in-memory controller — the modes render disabled with a "configure
894
+ * a provider" affordance, by design: the SDK does not bundle a drawing backend.
895
+ */
896
+ export class HonuaMeasureControlElement extends HonuaElementBase {
897
+ static get observedAttributes() {
898
+ return ["for", "label"];
899
+ }
900
+ #mode = "off";
901
+ attributeChangedCallback() {
902
+ this.resolveControllerFromContext();
903
+ this.render();
904
+ }
905
+ controllerChanged() {
906
+ this.render();
907
+ }
908
+ render() {
909
+ const label = this.getAttribute("label") ?? "Measure";
910
+ const enabled = this.controller?.canMeasure() ?? false;
911
+ this.setShadowHtml(`
912
+ <style>${baseStyles()}${controlPanelStyles()}</style>
913
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
914
+ <div class="control-panel__bar">
915
+ <h2>${escapeHtml(label)}</h2>
916
+ <span>${escapeHtml(enabled ? "ready" : "unsupported")}</span>
917
+ </div>
918
+ <div class="segmented" role="group" aria-label="${escapeAttribute(label)}">
919
+ ${["off", "distance", "area"]
920
+ .map((mode) => `
921
+ <button type="button" data-measure-mode="${mode}" aria-pressed="${String(this.#mode === mode)}"${enabled ? "" : ' aria-disabled="true" disabled'}>${escapeHtml(modeLabel(mode))}</button>
922
+ `)
923
+ .join("")}
924
+ </div>
925
+ ${enabled
926
+ ? ""
927
+ : `<p class="empty" role="status">Measurement is disabled because no geometry provider is configured. Pass a \`measurementGeometry\` provider to the controller to enable distance and area measuring.</p>`}
928
+ </section>
929
+ `);
930
+ if (!enabled)
931
+ return;
932
+ this.shadowRoot?.querySelectorAll("button[data-measure-mode]").forEach((button) => {
933
+ button.addEventListener("click", () => {
934
+ void this.setMode((button.dataset.measureMode ?? "off"));
935
+ });
936
+ });
937
+ }
938
+ async setMode(mode) {
939
+ this.#mode = mode;
940
+ const detail = this.controller
941
+ ? await this.controller.setMeasureMode(mode)
942
+ : {
943
+ mode,
944
+ status: "unsupported",
945
+ message: "Measurement requires a geometry provider. Configure `measurementGeometry` on the controller to enable measuring.",
946
+ };
947
+ this.dispatchTypedEvent("honua-measure-change", detail);
948
+ this.render();
949
+ }
950
+ }
951
+ /**
952
+ * `<honua-sketch-control>` renders point/line/polygon drawing modes.
953
+ *
954
+ * Like {@link HonuaMeasureControlElement}, the control is only interactive when
955
+ * the controller has a sketch geometry provider configured (`sketchGeometry` on
956
+ * {@link CreateHonuaWebComponentControllerOptions}). Without one the modes
957
+ * render disabled with a "configure a provider" affordance.
958
+ */
959
+ export class HonuaSketchControlElement extends HonuaElementBase {
960
+ static get observedAttributes() {
961
+ return ["for", "label"];
962
+ }
963
+ #mode = "off";
964
+ attributeChangedCallback() {
965
+ this.resolveControllerFromContext();
966
+ this.render();
967
+ }
968
+ controllerChanged() {
969
+ this.render();
970
+ }
971
+ render() {
972
+ const label = this.getAttribute("label") ?? "Sketch";
973
+ const enabled = this.controller?.canSketch() ?? false;
974
+ this.setShadowHtml(`
975
+ <style>${baseStyles()}${controlPanelStyles()}</style>
976
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
977
+ <div class="control-panel__bar">
978
+ <h2>${escapeHtml(label)}</h2>
979
+ <span>${escapeHtml(enabled ? "ready" : "unsupported")}</span>
980
+ </div>
981
+ <div class="segmented" role="group" aria-label="${escapeAttribute(label)}">
982
+ ${["off", "point", "line", "polygon"]
983
+ .map((mode) => `
984
+ <button type="button" data-sketch-mode="${mode}" aria-pressed="${String(this.#mode === mode)}"${enabled ? "" : ' aria-disabled="true" disabled'}>${escapeHtml(modeLabel(mode))}</button>
985
+ `)
986
+ .join("")}
987
+ </div>
988
+ ${enabled
989
+ ? ""
990
+ : `<p class="empty" role="status">Sketching is disabled because no geometry provider is configured. Pass a \`sketchGeometry\` provider to the controller to enable point, line, and polygon drawing.</p>`}
991
+ </section>
992
+ `);
993
+ if (!enabled)
994
+ return;
995
+ this.shadowRoot?.querySelectorAll("button[data-sketch-mode]").forEach((button) => {
996
+ button.addEventListener("click", () => {
997
+ void this.setMode((button.dataset.sketchMode ?? "off"));
998
+ });
999
+ });
1000
+ }
1001
+ async setMode(mode) {
1002
+ this.#mode = mode;
1003
+ const detail = this.controller
1004
+ ? await this.controller.setSketchMode(mode)
1005
+ : {
1006
+ mode,
1007
+ status: "unsupported",
1008
+ message: "Sketching requires a geometry provider. Configure `sketchGeometry` on the controller to enable drawing.",
1009
+ };
1010
+ this.dispatchTypedEvent("honua-sketch-change", detail);
1011
+ this.render();
1012
+ }
1013
+ }
1014
+ export class HonuaPrintExportElement extends HonuaElementBase {
1015
+ static get observedAttributes() {
1016
+ return ["for", "label", "title"];
1017
+ }
1018
+ attributeChangedCallback() {
1019
+ this.resolveControllerFromContext();
1020
+ this.render();
1021
+ }
1022
+ render() {
1023
+ const label = this.getAttribute("label") ?? "Print and export";
1024
+ this.setShadowHtml(`
1025
+ <style>${baseStyles()}${controlPanelStyles()}</style>
1026
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
1027
+ <div class="control-panel__bar">
1028
+ <h2>${escapeHtml(label)}</h2>
1029
+ <span>${escapeHtml(typeof window !== "undefined" && typeof window.print === "function" ? "ready" : "unsupported")}</span>
1030
+ </div>
1031
+ <div class="button-stack">
1032
+ <button type="button" data-export-format="print">Print</button>
1033
+ <button type="button" data-export-format="png">Snapshot</button>
1034
+ <button type="button" data-export-format="json">State JSON</button>
1035
+ </div>
1036
+ </section>
1037
+ `);
1038
+ this.shadowRoot?.querySelectorAll("button[data-export-format]").forEach((button) => {
1039
+ button.addEventListener("click", () => this.export(button.dataset.exportFormat));
1040
+ });
1041
+ }
1042
+ export(format) {
1043
+ const title = this.getAttribute("title") ?? this.state?.packageId ?? undefined;
1044
+ if (format === "print" && typeof window !== "undefined" && typeof window.print === "function") {
1045
+ this.dispatchTypedEvent("honua-export", {
1046
+ format,
1047
+ status: "ready",
1048
+ ...(title ? { title } : {}),
1049
+ });
1050
+ window.print();
1051
+ return;
1052
+ }
1053
+ const message = format === "print"
1054
+ ? "Window printing is unavailable."
1055
+ : "Snapshot export requires an application adapter to avoid leaking private map credentials.";
1056
+ this.dispatchTypedEvent("honua-export", {
1057
+ format,
1058
+ status: "unsupported",
1059
+ ...(title ? { title } : {}),
1060
+ message,
1061
+ });
1062
+ }
1063
+ }
1064
+ export class HonuaMapStatusElement extends HonuaElementBase {
1065
+ static get observedAttributes() {
1066
+ return ["for", "label", "attribution"];
1067
+ }
1068
+ attributeChangedCallback() {
1069
+ this.resolveControllerFromContext();
1070
+ this.render();
1071
+ }
1072
+ render() {
1073
+ const label = this.getAttribute("label") ?? "Map status";
1074
+ const attribution = this.getAttribute("attribution") ?? this.state?.mapPackage?.mapPackageId ?? "Honua";
1075
+ this.setShadowHtml(`
1076
+ <style>${baseStyles()}${mapStatusStyles()}</style>
1077
+ <section class="map-status" part="panel" aria-label="${escapeHtml(label)}">
1078
+ <span aria-label="Approximate scale">${escapeHtml(approximateScale(this.state?.viewport))}</span>
1079
+ <span aria-label="Attribution">${escapeHtml(attribution)}</span>
1080
+ <button type="button" data-fullscreen>Fullscreen</button>
1081
+ </section>
1082
+ `);
1083
+ this.shadowRoot?.querySelector("button[data-fullscreen]")?.addEventListener("click", () => {
1084
+ void this.toggleFullscreen();
1085
+ });
1086
+ }
1087
+ async toggleFullscreen() {
1088
+ const root = this.getRootNode?.();
1089
+ const mapId = this.getAttribute("for");
1090
+ const target = mapId ? getElementById(root, mapId) : this;
1091
+ const requestFullscreen = target?.requestFullscreen;
1092
+ if (!requestFullscreen) {
1093
+ this.dispatchTypedEvent("honua-fullscreen-change", {
1094
+ fullscreen: false,
1095
+ status: "unsupported",
1096
+ message: "Fullscreen is unavailable.",
1097
+ });
1098
+ return;
1099
+ }
1100
+ await requestFullscreen.call(target);
1101
+ this.dispatchTypedEvent("honua-fullscreen-change", {
1102
+ fullscreen: true,
1103
+ status: "ready",
1104
+ });
1105
+ }
1106
+ }
1107
+ export class HonuaActionPanelElement extends HonuaElementBase {
1108
+ static get observedAttributes() {
1109
+ return ["for", "label", "actions"];
1110
+ }
1111
+ attributeChangedCallback() {
1112
+ this.resolveControllerFromContext();
1113
+ this.render();
1114
+ }
1115
+ render() {
1116
+ const label = this.getAttribute("label") ?? "Actions";
1117
+ const actions = parseActions(this.getAttribute("actions"));
1118
+ this.setShadowHtml(`
1119
+ <style>${baseStyles()}${controlPanelStyles()}</style>
1120
+ <section class="control-panel" part="panel" aria-label="${escapeHtml(label)}">
1121
+ <div class="control-panel__bar">
1122
+ <h2>${escapeHtml(label)}</h2>
1123
+ <span>${escapeHtml(actions.length > 0 ? "ready" : "unsupported")}</span>
1124
+ </div>
1125
+ ${actions.length === 0
1126
+ ? `<p class="empty" role="status">No actions are configured.</p>`
1127
+ : `<div class="button-stack">
1128
+ ${actions
1129
+ .map((action) => `
1130
+ <button type="button" data-action-id="${escapeAttribute(action.id)}" ${action.disabled ? "disabled" : ""}>${escapeHtml(action.label)}</button>
1131
+ `)
1132
+ .join("")}
1133
+ </div>`}
1134
+ </section>
1135
+ `);
1136
+ this.shadowRoot?.querySelectorAll("button[data-action-id]").forEach((button) => {
1137
+ button.addEventListener("click", () => {
1138
+ const action = actions.find((candidate) => candidate.id === button.dataset.actionId);
1139
+ if (!action)
1140
+ return;
1141
+ this.dispatchTypedEvent("honua-action", {
1142
+ ...action,
1143
+ status: action.disabled ? "unsupported" : "ready",
1144
+ });
1145
+ });
1146
+ });
1147
+ }
1148
+ }
1149
+ export function defineHonuaWebComponents(registry = globalDom.customElements) {
1150
+ if (!registry)
1151
+ return;
1152
+ defineIfMissing(registry, "honua-map", HonuaMapElement);
1153
+ defineIfMissing(registry, "honua-layer-list", HonuaLayerListElement);
1154
+ defineIfMissing(registry, "honua-legend", HonuaLegendElement);
1155
+ defineIfMissing(registry, "honua-feature-table", HonuaFeatureTableElement);
1156
+ defineIfMissing(registry, "honua-search", HonuaSearchElement);
1157
+ defineIfMissing(registry, "honua-editor", HonuaEditorElement);
1158
+ defineIfMissing(registry, "honua-chart", HonuaChartElement);
1159
+ defineIfMissing(registry, "honua-basemap-control", HonuaBasemapControlElement);
1160
+ defineIfMissing(registry, "honua-bookmarks", HonuaBookmarksElement);
1161
+ defineIfMissing(registry, "honua-locate-control", HonuaLocateControlElement);
1162
+ defineIfMissing(registry, "honua-measure-control", HonuaMeasureControlElement);
1163
+ defineIfMissing(registry, "honua-sketch-control", HonuaSketchControlElement);
1164
+ defineIfMissing(registry, "honua-print-export", HonuaPrintExportElement);
1165
+ defineIfMissing(registry, "honua-map-status", HonuaMapStatusElement);
1166
+ defineIfMissing(registry, "honua-action-panel", HonuaActionPanelElement);
1167
+ }
1168
+ function defineIfMissing(registry, tagName, ctor) {
1169
+ if (!registry.get(tagName))
1170
+ registry.define(tagName, ctor);
1171
+ }
1172
+ if (globalDom.customElements) {
1173
+ defineHonuaWebComponents(globalDom.customElements);
1174
+ }
1175
+ function tableModelFromState(state, sourceId, fields, pageSize) {
1176
+ const resolvedSourceId = sourceId ?? Object.keys(state?.featuresBySource ?? {})[0];
1177
+ const rows = resolvedSourceId ? [...(state?.featuresBySource[resolvedSourceId] ?? [])] : [];
1178
+ const modelFields = fields ?? inferFields(rows);
1179
+ return {
1180
+ sourceId: resolvedSourceId,
1181
+ status: state?.status ?? "idle",
1182
+ fields: modelFields,
1183
+ rows: pageSize ? rows.slice(0, pageSize) : rows,
1184
+ totalCount: rows.length,
1185
+ };
1186
+ }
1187
+ function defaultEditorModel(sourceId) {
1188
+ return {
1189
+ sourceId,
1190
+ status: "idle",
1191
+ capabilities: {
1192
+ canCreate: false,
1193
+ canUpdate: false,
1194
+ canDelete: false,
1195
+ readOnly: true,
1196
+ reason: "Editing is not enabled for this source.",
1197
+ },
1198
+ };
1199
+ }
1200
+ function defaultChartModel(title) {
1201
+ return {
1202
+ id: "placeholder",
1203
+ title,
1204
+ kind: "placeholder",
1205
+ status: "idle",
1206
+ message: "No chart data",
1207
+ };
1208
+ }
1209
+ function basemapsFromState(state) {
1210
+ return (state?.layers ?? [])
1211
+ .filter((layer) => layer.type === "background" || layer.metadata?.basemap === true)
1212
+ .map((layer) => ({ id: layer.id, title: layer.title, visible: layer.visible }));
1213
+ }
1214
+ function parseBookmarks(value) {
1215
+ if (!value)
1216
+ return [];
1217
+ try {
1218
+ const parsed = JSON.parse(value);
1219
+ if (!Array.isArray(parsed))
1220
+ return [];
1221
+ return parsed.flatMap((item) => {
1222
+ if (!item || typeof item !== "object")
1223
+ return [];
1224
+ const candidate = item;
1225
+ if (!candidate.id || !candidate.label || !candidate.viewport)
1226
+ return [];
1227
+ return [{ id: String(candidate.id), label: String(candidate.label), viewport: candidate.viewport }];
1228
+ });
1229
+ }
1230
+ catch {
1231
+ return [];
1232
+ }
1233
+ }
1234
+ function parseActions(value) {
1235
+ if (!value)
1236
+ return [];
1237
+ try {
1238
+ const parsed = JSON.parse(value);
1239
+ if (!Array.isArray(parsed))
1240
+ return [];
1241
+ return parsed.flatMap((item) => {
1242
+ if (!item || typeof item !== "object")
1243
+ return [];
1244
+ const candidate = item;
1245
+ if (!candidate.id || !candidate.label)
1246
+ return [];
1247
+ return [
1248
+ {
1249
+ id: String(candidate.id),
1250
+ label: String(candidate.label),
1251
+ ...(candidate.disabled ? { disabled: true } : {}),
1252
+ },
1253
+ ];
1254
+ });
1255
+ }
1256
+ catch {
1257
+ return [];
1258
+ }
1259
+ }
1260
+ function inferFields(rows) {
1261
+ const fields = new Set();
1262
+ for (const row of rows) {
1263
+ for (const field of Object.keys(row.attributes))
1264
+ fields.add(field);
1265
+ }
1266
+ return [...fields];
1267
+ }
1268
+ function getElementById(root, id) {
1269
+ if (root && "getElementById" in root)
1270
+ return root.getElementById(id);
1271
+ return typeof document !== "undefined" ? document.getElementById(id) : null;
1272
+ }
1273
+ function formatCell(value) {
1274
+ if (value === null || value === undefined)
1275
+ return "";
1276
+ if (typeof value === "object")
1277
+ return JSON.stringify(value);
1278
+ return String(value);
1279
+ }
1280
+ function modeLabel(mode) {
1281
+ return mode.charAt(0).toUpperCase() + mode.slice(1);
1282
+ }
1283
+ function approximateScale(viewport) {
1284
+ const zoom = viewport?.zoom;
1285
+ if (!Number.isFinite(zoom))
1286
+ return "Scale unavailable";
1287
+ const latitude = viewport?.center?.[1] ?? 0;
1288
+ const metersPerPixel = (156543.03392 * Math.cos((latitude * Math.PI) / 180)) / 2 ** Number(zoom);
1289
+ const scale = Math.max(1, Math.round(metersPerPixel * 96 * 39.37));
1290
+ return `1:${scale.toLocaleString("en-US")}`;
1291
+ }
1292
+ function setText(element, value) {
1293
+ if (element)
1294
+ element.textContent = value;
1295
+ }
1296
+ function captureFocus(root) {
1297
+ if (!("activeElement" in root))
1298
+ return undefined;
1299
+ const active = root.activeElement;
1300
+ if (!active || !("localName" in active))
1301
+ return undefined;
1302
+ const selector = focusSelector(active);
1303
+ if (!selector)
1304
+ return undefined;
1305
+ const textControl = isTextControl(active) ? active : undefined;
1306
+ return {
1307
+ selector,
1308
+ ...(textControl ? { value: textControl.value } : {}),
1309
+ ...(typeof textControl?.selectionStart === "number" ? { selectionStart: textControl.selectionStart } : {}),
1310
+ ...(typeof textControl?.selectionEnd === "number" ? { selectionEnd: textControl.selectionEnd } : {}),
1311
+ ...(textControl?.selectionDirection ? { selectionDirection: textControl.selectionDirection } : {}),
1312
+ };
1313
+ }
1314
+ function restoreFocus(root, snapshot) {
1315
+ if (!snapshot || typeof root.querySelector !== "function")
1316
+ return;
1317
+ const target = root.querySelector(snapshot.selector);
1318
+ if (!target || !("focus" in target) || typeof target.focus !== "function")
1319
+ return;
1320
+ target.focus({ preventScroll: true });
1321
+ if (snapshot.value === undefined ||
1322
+ snapshot.selectionStart === undefined ||
1323
+ snapshot.selectionEnd === undefined ||
1324
+ !isTextControl(target) ||
1325
+ target.value !== snapshot.value) {
1326
+ return;
1327
+ }
1328
+ target.setSelectionRange(snapshot.selectionStart, snapshot.selectionEnd, snapshot.selectionDirection ?? "none");
1329
+ }
1330
+ function focusSelector(element) {
1331
+ const tagName = element.localName;
1332
+ for (const name of ["id", "name"]) {
1333
+ const value = element.getAttribute(name);
1334
+ if (value)
1335
+ return `${tagName}[${name}="${cssAttribute(value)}"]`;
1336
+ }
1337
+ for (const name of element
1338
+ .getAttributeNames()
1339
+ .filter((attribute) => attribute.startsWith("data-"))
1340
+ .sort()) {
1341
+ const value = element.getAttribute(name);
1342
+ if (value)
1343
+ return `${tagName}[${name}="${cssAttribute(value)}"]`;
1344
+ }
1345
+ return undefined;
1346
+ }
1347
+ function isTextControl(element) {
1348
+ return ((element.localName === "input" || element.localName === "textarea") &&
1349
+ "value" in element &&
1350
+ "setSelectionRange" in element);
1351
+ }
1352
+ function cssAttribute(value) {
1353
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1354
+ }
1355
+ function browserOrigin() {
1356
+ return typeof window !== "undefined" && window.location?.origin ? window.location.origin : "http://localhost";
1357
+ }
1358
+ function escapeHtml(value) {
1359
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1360
+ }
1361
+ function escapeAttribute(value) {
1362
+ return escapeHtml(value).replace(/'/g, "&#39;");
1363
+ }
1364
+ function baseStyles() {
1365
+ return `
1366
+ :host {
1367
+ --honua-ui-bg: #ffffff;
1368
+ --honua-ui-fg: #172033;
1369
+ --honua-ui-muted: #667085;
1370
+ --honua-ui-border: #d0d5dd;
1371
+ --honua-ui-accent: #1d4ed8;
1372
+ --honua-ui-accent-fg: #ffffff;
1373
+ --honua-ui-surface: #f8fafc;
1374
+ box-sizing: border-box;
1375
+ color: var(--honua-ui-fg);
1376
+ display: block;
1377
+ font: 14px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
1378
+ }
1379
+ *, *::before, *::after { box-sizing: inherit; }
1380
+ button, input, select { font: inherit; }
1381
+ button {
1382
+ border: 1px solid var(--honua-ui-border);
1383
+ background: var(--honua-ui-bg);
1384
+ border-radius: 6px;
1385
+ color: inherit;
1386
+ cursor: pointer;
1387
+ min-height: 32px;
1388
+ padding: 0 10px;
1389
+ }
1390
+ button:disabled { cursor: not-allowed; opacity: 0.55; }
1391
+ h2 { font-size: 14px; margin: 0; }
1392
+ .empty, .muted { color: var(--honua-ui-muted); }
1393
+ .sr-only {
1394
+ border: 0;
1395
+ clip: rect(0 0 0 0);
1396
+ height: 1px;
1397
+ margin: -1px;
1398
+ overflow: hidden;
1399
+ padding: 0;
1400
+ position: absolute;
1401
+ width: 1px;
1402
+ }
1403
+ `;
1404
+ }
1405
+ function mapStyles() {
1406
+ return `
1407
+ .map {
1408
+ background: #dbeafe;
1409
+ border: 1px solid var(--honua-ui-border);
1410
+ border-radius: 8px;
1411
+ display: grid;
1412
+ grid-template-rows: auto minmax(220px, 1fr) auto;
1413
+ min-height: 320px;
1414
+ overflow: hidden;
1415
+ }
1416
+ .map__chrome, .map__footer {
1417
+ align-items: center;
1418
+ background: rgba(255, 255, 255, 0.9);
1419
+ display: flex;
1420
+ gap: 8px;
1421
+ justify-content: space-between;
1422
+ padding: 8px 10px;
1423
+ }
1424
+ .map__controls { align-items: center; display: flex; gap: 6px; }
1425
+ .icon-button { min-width: 32px; padding: 0; }
1426
+ .zoom { min-width: 32px; text-align: center; }
1427
+ .map__canvas {
1428
+ background:
1429
+ linear-gradient(90deg, rgba(255,255,255,0.32) 1px, transparent 1px),
1430
+ linear-gradient(0deg, rgba(255,255,255,0.32) 1px, transparent 1px),
1431
+ #bfdbfe;
1432
+ background-size: 40px 40px;
1433
+ min-height: 220px;
1434
+ overflow: hidden;
1435
+ position: relative;
1436
+ }
1437
+ .map__renderer {
1438
+ height: 100%;
1439
+ inset: 0;
1440
+ min-height: inherit;
1441
+ position: absolute;
1442
+ width: 100%;
1443
+ }
1444
+ .map__renderer.maplibregl-map,
1445
+ .map__renderer .maplibregl-map,
1446
+ .map__renderer .maplibregl-canvas-container,
1447
+ .map__renderer .maplibregl-canvas {
1448
+ height: 100%;
1449
+ width: 100%;
1450
+ }
1451
+ .map__renderer .maplibregl-canvas-container {
1452
+ inset: 0;
1453
+ position: absolute;
1454
+ }
1455
+ .map__renderer .maplibregl-canvas {
1456
+ left: 0;
1457
+ position: absolute;
1458
+ top: 0;
1459
+ }
1460
+ .map__status {
1461
+ background: rgba(255,255,255,0.86);
1462
+ border-radius: 6px;
1463
+ color: var(--honua-ui-muted);
1464
+ left: 10px;
1465
+ padding: 4px 7px;
1466
+ position: absolute;
1467
+ top: 10px;
1468
+ z-index: 1;
1469
+ }
1470
+ .map__status:empty { display: none; }
1471
+ .maplibregl-ctrl-attrib,
1472
+ .maplibregl-control-container {
1473
+ display: none;
1474
+ }
1475
+ `;
1476
+ }
1477
+ function listStyles() {
1478
+ return `
1479
+ .panel {
1480
+ background: var(--honua-ui-bg);
1481
+ border: 1px solid var(--honua-ui-border);
1482
+ border-radius: 8px;
1483
+ margin: 0;
1484
+ padding: 10px;
1485
+ }
1486
+ legend { font-weight: 650; padding: 0 4px; }
1487
+ .stack { display: grid; gap: 8px; }
1488
+ .check-row { align-items: center; display: flex; gap: 8px; min-height: 28px; }
1489
+ .legend { display: grid; gap: 8px; list-style: none; margin: 10px 0 0; padding: 0; }
1490
+ .legend li { align-items: center; display: flex; gap: 8px; min-height: 24px; }
1491
+ .swatch {
1492
+ background: var(--swatch);
1493
+ border: 1px solid rgba(15, 23, 42, 0.18);
1494
+ border-radius: 3px;
1495
+ display: inline-block;
1496
+ height: 16px;
1497
+ width: 24px;
1498
+ }
1499
+ img.swatch { object-fit: cover; }
1500
+ `;
1501
+ }
1502
+ function tableStyles() {
1503
+ return `
1504
+ .table-panel {
1505
+ border: 1px solid var(--honua-ui-border);
1506
+ border-radius: 8px;
1507
+ overflow: hidden;
1508
+ }
1509
+ .table-panel__bar {
1510
+ align-items: center;
1511
+ background: var(--honua-ui-surface);
1512
+ display: flex;
1513
+ justify-content: space-between;
1514
+ padding: 8px 10px;
1515
+ }
1516
+ .table-wrap { max-height: 300px; overflow: auto; }
1517
+ table { border-collapse: collapse; min-width: 100%; table-layout: fixed; }
1518
+ th, td {
1519
+ border-top: 1px solid var(--honua-ui-border);
1520
+ overflow: hidden;
1521
+ padding: 7px 9px;
1522
+ text-align: left;
1523
+ text-overflow: ellipsis;
1524
+ white-space: nowrap;
1525
+ }
1526
+ th { background: #f8fafc; font-weight: 650; }
1527
+ tr[aria-selected="true"] td { background: #dbeafe; }
1528
+ tbody tr[data-feature-id] { cursor: pointer; }
1529
+ tbody tr[data-feature-id]:focus { outline: 2px solid var(--honua-ui-accent); outline-offset: -2px; }
1530
+ `;
1531
+ }
1532
+ function searchStyles() {
1533
+ return `
1534
+ .search {
1535
+ border: 1px solid var(--honua-ui-border);
1536
+ border-radius: 8px;
1537
+ padding: 10px;
1538
+ }
1539
+ form { display: grid; gap: 8px; grid-template-columns: minmax(120px, 1fr) auto; }
1540
+ input {
1541
+ border: 1px solid var(--honua-ui-border);
1542
+ border-radius: 6px;
1543
+ min-height: 32px;
1544
+ min-width: 0;
1545
+ padding: 0 9px;
1546
+ }
1547
+ .results { display: grid; gap: 6px; list-style: none; margin: 10px 0 0; padding: 0; }
1548
+ .results button { text-align: left; width: 100%; }
1549
+ `;
1550
+ }
1551
+ function editorStyles() {
1552
+ return `
1553
+ .editor {
1554
+ border: 1px solid var(--honua-ui-border);
1555
+ border-radius: 8px;
1556
+ padding: 10px;
1557
+ }
1558
+ .editor__bar, .editor__actions { align-items: center; display: flex; gap: 8px; justify-content: space-between; }
1559
+ .editor__actions { justify-content: flex-start; }
1560
+ .selection { margin: 10px 0 4px; }
1561
+ .muted { margin: 0 0 10px; }
1562
+ `;
1563
+ }
1564
+ function chartStyles() {
1565
+ return `
1566
+ .chart {
1567
+ border: 1px solid var(--honua-ui-border);
1568
+ border-radius: 8px;
1569
+ padding: 10px;
1570
+ }
1571
+ .bars { display: grid; gap: 8px; margin-top: 10px; }
1572
+ .bar-row { align-items: center; display: grid; gap: 8px; grid-template-columns: minmax(70px, 1fr) 3fr auto; }
1573
+ .bar { background: #e5e7eb; border-radius: 999px; height: 10px; overflow: hidden; position: relative; }
1574
+ .bar::before {
1575
+ background: var(--bar-color);
1576
+ border-radius: inherit;
1577
+ content: "";
1578
+ inset: 0 auto 0 0;
1579
+ position: absolute;
1580
+ width: var(--bar);
1581
+ }
1582
+ `;
1583
+ }
1584
+ function controlPanelStyles() {
1585
+ return `
1586
+ .control-panel {
1587
+ background: var(--honua-ui-bg);
1588
+ border: 1px solid var(--honua-ui-border);
1589
+ border-radius: 8px;
1590
+ display: grid;
1591
+ gap: 10px;
1592
+ min-width: 180px;
1593
+ padding: 10px;
1594
+ }
1595
+ .control-panel__bar {
1596
+ align-items: center;
1597
+ display: flex;
1598
+ gap: 8px;
1599
+ justify-content: space-between;
1600
+ }
1601
+ .control-panel__bar span {
1602
+ color: var(--honua-ui-muted);
1603
+ font-size: 12px;
1604
+ }
1605
+ .button-stack {
1606
+ display: grid;
1607
+ gap: 6px;
1608
+ }
1609
+ .button-stack button {
1610
+ justify-content: flex-start;
1611
+ text-align: left;
1612
+ }
1613
+ .segmented {
1614
+ display: grid;
1615
+ gap: 6px;
1616
+ grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
1617
+ }
1618
+ .segmented button {
1619
+ min-width: 0;
1620
+ padding: 0 8px;
1621
+ }
1622
+ button[aria-pressed="true"] {
1623
+ background: var(--honua-ui-accent);
1624
+ border-color: var(--honua-ui-accent);
1625
+ color: var(--honua-ui-accent-fg);
1626
+ }
1627
+ p {
1628
+ margin: 0;
1629
+ }
1630
+ `;
1631
+ }
1632
+ function mapStatusStyles() {
1633
+ return `
1634
+ .map-status {
1635
+ align-items: center;
1636
+ background: var(--honua-ui-bg);
1637
+ border: 1px solid var(--honua-ui-border);
1638
+ border-radius: 8px;
1639
+ display: flex;
1640
+ flex-wrap: wrap;
1641
+ gap: 8px;
1642
+ justify-content: space-between;
1643
+ min-height: 42px;
1644
+ padding: 6px 8px;
1645
+ }
1646
+ span {
1647
+ color: var(--honua-ui-muted);
1648
+ min-width: 0;
1649
+ }
1650
+ `;
1651
+ }