@honua/app-platform 0.1.0-beta.0 → 0.1.1-beta.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.
- package/contract/discovery.d.ts +231 -0
- package/contract/discovery.d.ts.map +1 -0
- package/contract/discovery.js +554 -0
- package/contract/edit-sketch.d.ts +8 -0
- package/contract/edit-sketch.d.ts.map +1 -1
- package/contract/edit-sketch.js +15 -0
- package/contract/edit-snapping.d.ts +160 -0
- package/contract/edit-snapping.d.ts.map +1 -0
- package/contract/edit-snapping.js +675 -0
- package/contract/generated/projjson-v0.7-crs-validator.d.ts +35 -0
- package/contract/generated/projjson-v0.7-crs-validator.d.ts.map +1 -0
- package/contract/generated/projjson-v0.7-crs-validator.js +3941 -0
- package/contract/index.d.ts +11 -2
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +4 -1
- package/contract/pmtiles.d.ts +31 -0
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +60 -20
- package/contract/protocol-module.d.ts +70 -0
- package/contract/protocol-module.d.ts.map +1 -0
- package/contract/protocol-module.js +1 -0
- package/contract/schema-envelope.d.ts +26 -0
- package/contract/schema-envelope.d.ts.map +1 -0
- package/contract/schema-envelope.js +25 -0
- package/contract/schema.d.ts +582 -0
- package/contract/schema.d.ts.map +1 -0
- package/contract/schema.js +2483 -0
- package/contract/source-capability-support.d.ts +6 -0
- package/contract/source-capability-support.d.ts.map +1 -0
- package/contract/source-capability-support.js +154 -0
- package/contract/source.d.ts +35 -17
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +267 -71
- package/contract/types.d.ts +140 -4
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +6 -14
- package/core/bounded-json.d.ts +4 -0
- package/core/bounded-json.d.ts.map +1 -0
- package/core/bounded-json.js +38 -0
- package/core/cache-state.d.ts +9 -0
- package/core/cache-state.d.ts.map +1 -1
- package/core/cache-state.js +10 -0
- package/core/capabilities-xml.d.ts +33 -0
- package/core/capabilities-xml.d.ts.map +1 -0
- package/core/capabilities-xml.js +331 -0
- package/core/client.d.ts +4 -1
- package/core/client.d.ts.map +1 -1
- package/core/client.js +115 -29
- package/core/error-classifications.d.ts +153 -0
- package/core/error-classifications.d.ts.map +1 -0
- package/core/error-classifications.js +140 -0
- package/core/error-code-registry.d.ts +158 -0
- package/core/error-code-registry.d.ts.map +1 -0
- package/core/error-code-registry.js +143 -0
- package/core/error-envelope.d.ts +68 -0
- package/core/error-envelope.d.ts.map +1 -0
- package/core/error-envelope.js +357 -0
- package/core/errors.d.ts +45 -29
- package/core/errors.d.ts.map +1 -1
- package/core/errors.js +97 -50
- package/core/geoparquet-sql.d.ts +30 -2
- package/core/geoparquet-sql.d.ts.map +1 -1
- package/core/geoparquet-sql.js +38 -3
- package/core/odata-key-path.d.ts +12 -0
- package/core/odata-key-path.d.ts.map +1 -0
- package/core/odata-key-path.js +28 -0
- package/core/odata-write-codec.d.ts +66 -0
- package/core/odata-write-codec.d.ts.map +1 -0
- package/core/odata-write-codec.js +1083 -0
- package/core/odata.d.ts +59 -7
- package/core/odata.d.ts.map +1 -1
- package/core/odata.js +431 -99
- package/core/ogc-features.d.ts.map +1 -1
- package/core/ogc-features.js +3 -0
- package/core/ogc-maps.d.ts +7 -0
- package/core/ogc-maps.d.ts.map +1 -1
- package/core/ogc-maps.js +46 -7
- package/core/ogc-processes.d.ts +2 -1
- package/core/ogc-processes.d.ts.map +1 -1
- package/core/ogc-processes.js +33 -5
- package/core/ogc-records.d.ts +9 -0
- package/core/ogc-records.d.ts.map +1 -1
- package/core/ogc-records.js +78 -29
- package/core/ogc-tiles.d.ts +10 -1
- package/core/ogc-tiles.d.ts.map +1 -1
- package/core/ogc-tiles.js +56 -17
- package/core/path-utils.d.ts +9 -0
- package/core/path-utils.d.ts.map +1 -1
- package/core/path-utils.js +19 -0
- package/core/protocol-transport.d.ts +1 -0
- package/core/protocol-transport.d.ts.map +1 -1
- package/core/request-pipeline.d.ts.map +1 -1
- package/core/request-pipeline.js +1 -1
- package/core/spatial-filter.d.ts +8 -4
- package/core/spatial-filter.d.ts.map +1 -1
- package/core/spatial-filter.js +206 -16
- package/core/stac-static.d.ts +6 -2
- package/core/stac-static.d.ts.map +1 -1
- package/core/stac-static.js +260 -69
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +69 -5
- package/core/types.d.ts +125 -7
- package/core/types.d.ts.map +1 -1
- package/core/wfs-capabilities.d.ts +2 -0
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +8 -1
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +10 -0
- package/core/wms-capabilities.d.ts +56 -84
- package/core/wms-capabilities.d.ts.map +1 -1
- package/core/wms-capabilities.js +212 -509
- package/core/wmts-capabilities.d.ts +62 -62
- package/core/wmts-capabilities.d.ts.map +1 -1
- package/core/wmts-capabilities.js +224 -371
- package/esri-compat/editor.d.ts +8 -0
- package/esri-compat/editor.d.ts.map +1 -1
- package/esri-compat/editor.js +13 -0
- package/esri-compat/feature-layer.d.ts +2 -0
- package/esri-compat/feature-layer.d.ts.map +1 -1
- package/esri-compat/feature-layer.js +1 -0
- package/esri-compat/layer-list.d.ts +11 -0
- package/esri-compat/layer-list.d.ts.map +1 -1
- package/esri-compat/layer-list.js +49 -0
- package/esri-compat/legend.d.ts +10 -0
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +27 -0
- package/esri-compat/portal.d.ts +197 -0
- package/esri-compat/portal.d.ts.map +1 -0
- package/esri-compat/portal.js +251 -0
- package/esri-compat/renderer-objects.d.ts +40 -0
- package/esri-compat/renderer-objects.d.ts.map +1 -0
- package/esri-compat/renderer-objects.js +62 -0
- package/esri-compat/sketch.d.ts +43 -0
- package/esri-compat/sketch.d.ts.map +1 -1
- package/esri-compat/sketch.js +46 -0
- package/esri-compat/snapping.d.ts +43 -0
- package/esri-compat/snapping.d.ts.map +1 -0
- package/esri-compat/snapping.js +45 -0
- package/esri-compat/url.d.ts.map +1 -1
- package/esri-compat/url.js +1 -1
- package/esri-compat/widget-host.d.ts +84 -0
- package/esri-compat/widget-host.d.ts.map +1 -0
- package/esri-compat/widget-host.js +159 -0
- package/generated-app/errors.d.ts +18 -2
- package/generated-app/errors.d.ts.map +1 -1
- package/generated-app/errors.js +44 -11
- package/geocoding/index.d.ts +7 -0
- package/geocoding/index.d.ts.map +1 -1
- package/geocoding/index.js +5 -0
- package/geocoding/provider-http.d.ts +37 -0
- package/geocoding/provider-http.d.ts.map +1 -0
- package/geocoding/provider-http.js +91 -0
- package/geocoding/provider.d.ts +145 -0
- package/geocoding/provider.d.ts.map +1 -0
- package/geocoding/provider.js +41 -0
- package/geocoding/providers/honua.d.ts +28 -0
- package/geocoding/providers/honua.d.ts.map +1 -0
- package/geocoding/providers/honua.js +68 -0
- package/geocoding/providers/nominatim.d.ts +47 -0
- package/geocoding/providers/nominatim.d.ts.map +1 -0
- package/geocoding/providers/nominatim.js +105 -0
- package/geocoding/providers/pelias.d.ts +40 -0
- package/geocoding/providers/pelias.d.ts.map +1 -0
- package/geocoding/providers/pelias.js +115 -0
- package/geocoding/providers/photon.d.ts +39 -0
- package/geocoding/providers/photon.d.ts.map +1 -0
- package/geocoding/providers/photon.js +107 -0
- package/geometry/convert.d.ts +13 -0
- package/geometry/convert.d.ts.map +1 -0
- package/geometry/convert.js +12 -0
- package/geometry/index.d.ts +17 -0
- package/geometry/index.d.ts.map +1 -0
- package/geometry/index.js +15 -0
- package/geometry/internal.d.ts +25 -0
- package/geometry/internal.d.ts.map +1 -0
- package/geometry/internal.js +40 -0
- package/geometry/ops.d.ts +71 -0
- package/geometry/ops.d.ts.map +1 -0
- package/geometry/ops.js +147 -0
- package/geometry/project.d.ts +40 -0
- package/geometry/project.d.ts.map +1 -0
- package/geometry/project.js +88 -0
- package/geometry/types.d.ts +36 -0
- package/geometry/types.d.ts.map +1 -0
- package/geometry/types.js +12 -0
- package/map/automatic-mount-integration.d.ts +134 -0
- package/map/automatic-mount-integration.d.ts.map +1 -0
- package/map/automatic-mount-integration.js +305 -0
- package/map/automatic-source-strategy.d.ts +125 -0
- package/map/automatic-source-strategy.d.ts.map +1 -0
- package/map/automatic-source-strategy.js +494 -0
- package/map/data-to-map-bridge.d.ts +293 -0
- package/map/data-to-map-bridge.d.ts.map +1 -0
- package/map/data-to-map-bridge.js +817 -0
- package/map/geojson-projection.d.ts +33 -0
- package/map/geojson-projection.d.ts.map +1 -0
- package/map/geojson-projection.js +118 -0
- package/map/index.d.ts +14 -0
- package/map/index.d.ts.map +1 -1
- package/map/index.js +8 -0
- package/map/raster-source-spec.d.ts +30 -0
- package/map/raster-source-spec.d.ts.map +1 -0
- package/map/raster-source-spec.js +190 -0
- package/map/raster-source-strategy.d.ts +65 -0
- package/map/raster-source-strategy.d.ts.map +1 -0
- package/map/raster-source-strategy.js +232 -0
- package/map/source-to-maplibre.d.ts +91 -0
- package/map/source-to-maplibre.d.ts.map +1 -0
- package/map/source-to-maplibre.js +454 -0
- package/map/temporal-playback.d.ts +139 -0
- package/map/temporal-playback.d.ts.map +1 -0
- package/map/temporal-playback.js +247 -0
- package/package.json +28 -2
- package/query-planner/canonical.d.ts +7 -0
- package/query-planner/canonical.d.ts.map +1 -0
- package/query-planner/canonical.js +145 -0
- package/query-planner/cql2-json.d.ts +17 -0
- package/query-planner/cql2-json.d.ts.map +1 -0
- package/query-planner/cql2-json.js +646 -0
- package/query-planner/diagnostics.d.ts +35 -0
- package/query-planner/diagnostics.d.ts.map +1 -0
- package/query-planner/diagnostics.js +373 -0
- package/query-planner/duckdb.d.ts +79 -0
- package/query-planner/duckdb.d.ts.map +1 -0
- package/query-planner/duckdb.js +758 -0
- package/query-planner/execution-context.d.ts +5 -0
- package/query-planner/execution-context.d.ts.map +1 -0
- package/query-planner/execution-context.js +50 -0
- package/query-planner/executor.d.ts +5 -0
- package/query-planner/executor.d.ts.map +1 -0
- package/query-planner/executor.js +223 -0
- package/query-planner/geoservices.d.ts +91 -0
- package/query-planner/geoservices.d.ts.map +1 -0
- package/query-planner/geoservices.js +667 -0
- package/query-planner/grpc.d.ts +100 -0
- package/query-planner/grpc.d.ts.map +1 -0
- package/query-planner/grpc.js +736 -0
- package/query-planner/index.d.ts +44 -0
- package/query-planner/index.d.ts.map +1 -0
- package/query-planner/index.js +30 -0
- package/query-planner/ir.d.ts +20 -0
- package/query-planner/ir.d.ts.map +1 -0
- package/query-planner/ir.js +417 -0
- package/query-planner/local-aggregate.d.ts +5 -0
- package/query-planner/local-aggregate.d.ts.map +1 -0
- package/query-planner/local-aggregate.js +126 -0
- package/query-planner/odata.d.ts +48 -0
- package/query-planner/odata.d.ts.map +1 -0
- package/query-planner/odata.js +662 -0
- package/query-planner/ogc-compiler.d.ts +55 -0
- package/query-planner/ogc-compiler.d.ts.map +1 -0
- package/query-planner/ogc-compiler.js +480 -0
- package/query-planner/ogc-features.d.ts +53 -0
- package/query-planner/ogc-features.d.ts.map +1 -0
- package/query-planner/ogc-features.js +617 -0
- package/query-planner/planner.d.ts +17 -0
- package/query-planner/planner.d.ts.map +1 -0
- package/query-planner/planner.js +818 -0
- package/query-planner/resource.d.ts +94 -0
- package/query-planner/resource.d.ts.map +1 -0
- package/query-planner/resource.js +526 -0
- package/query-planner/semantic-canonical.d.ts +15 -0
- package/query-planner/semantic-canonical.d.ts.map +1 -0
- package/query-planner/semantic-canonical.js +62 -0
- package/query-planner/semantic-compat.d.ts +10 -0
- package/query-planner/semantic-compat.d.ts.map +1 -0
- package/query-planner/semantic-compat.js +35 -0
- package/query-planner/semantic-compiler.d.ts +64 -0
- package/query-planner/semantic-compiler.d.ts.map +1 -0
- package/query-planner/semantic-compiler.js +81 -0
- package/query-planner/semantic-literals.d.ts +30 -0
- package/query-planner/semantic-literals.d.ts.map +1 -0
- package/query-planner/semantic-literals.js +133 -0
- package/query-planner/semantic-types.d.ts +265 -0
- package/query-planner/semantic-types.d.ts.map +1 -0
- package/query-planner/semantic-types.js +1 -0
- package/query-planner/semantic.d.ts +54 -0
- package/query-planner/semantic.d.ts.map +1 -0
- package/query-planner/semantic.js +1421 -0
- package/query-planner/types.d.ts +560 -0
- package/query-planner/types.d.ts.map +1 -0
- package/query-planner/types.js +49 -0
- package/query-planner/wfs-semantic.d.ts +58 -0
- package/query-planner/wfs-semantic.d.ts.map +1 -0
- package/query-planner/wfs-semantic.js +547 -0
- package/query-planner/wfs.d.ts +6 -0
- package/query-planner/wfs.d.ts.map +1 -0
- package/query-planner/wfs.js +71 -0
- package/realtime/contract.d.ts +142 -0
- package/realtime/contract.d.ts.map +1 -0
- package/realtime/contract.js +154 -0
- package/realtime/honua-server.d.ts.map +1 -1
- package/realtime/honua-server.js +13 -8
- package/realtime/index.d.ts +19 -4
- package/realtime/index.d.ts.map +1 -1
- package/realtime/index.js +14 -4
- package/realtime/odata-delta.d.ts +114 -0
- package/realtime/odata-delta.d.ts.map +1 -0
- package/realtime/odata-delta.js +483 -0
- package/realtime/resumable-transport.d.ts +111 -0
- package/realtime/resumable-transport.d.ts.map +1 -0
- package/realtime/resumable-transport.js +406 -0
- package/realtime/resumable.d.ts +104 -0
- package/realtime/resumable.d.ts.map +1 -0
- package/realtime/resumable.js +632 -0
- package/realtime/sse.d.ts.map +1 -1
- package/realtime/sse.js +27 -23
- package/realtime/websocket.d.ts +60 -0
- package/realtime/websocket.d.ts.map +1 -0
- package/realtime/websocket.js +157 -0
- package/realtime/wire.d.ts +27 -0
- package/realtime/wire.d.ts.map +1 -0
- package/realtime/wire.js +57 -0
- package/replica-sync/errors.d.ts +2 -1
- package/replica-sync/errors.d.ts.map +1 -1
- package/replica-sync/errors.js +33 -2
- package/runtime/edit-snapping.d.ts +107 -0
- package/runtime/edit-snapping.d.ts.map +1 -0
- package/runtime/edit-snapping.js +190 -0
- package/runtime/errors.d.ts +3 -2
- package/runtime/errors.d.ts.map +1 -1
- package/runtime/errors.js +19 -2
- package/runtime/index.d.ts +6 -0
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +3 -0
- package/runtime/maplibre-renderer.d.ts +41 -0
- package/runtime/maplibre-renderer.d.ts.map +1 -0
- package/runtime/maplibre-renderer.js +322 -0
- package/runtime/query-tiles.d.ts +2 -1
- package/runtime/query-tiles.d.ts.map +1 -1
- package/runtime/query-tiles.js +6 -2
- package/runtime/source-bridge.d.ts +4 -4
- package/runtime/source-bridge.d.ts.map +1 -1
- package/runtime/source-bridge.js +9 -56
- package/runtime/style-interactions.d.ts +3 -2
- package/runtime/style-interactions.d.ts.map +1 -1
- package/runtime/style-interactions.js +11 -3
- package/runtime/terra-draw-sketch.d.ts +275 -0
- package/runtime/terra-draw-sketch.d.ts.map +1 -0
- package/runtime/terra-draw-sketch.js +404 -0
- package/scene-workspace/index.d.ts +4 -0
- package/scene-workspace/index.d.ts.map +1 -1
- package/scene-workspace/index.js +2 -0
- package/scene-workspace/source-to-cesium.d.ts +116 -0
- package/scene-workspace/source-to-cesium.d.ts.map +1 -0
- package/scene-workspace/source-to-cesium.js +791 -0
- package/scene-workspace/state-sync.d.ts +147 -0
- package/scene-workspace/state-sync.d.ts.map +1 -0
- package/scene-workspace/state-sync.js +1123 -0
- package/source-capability-registry.d.ts +1 -0
- package/source-capability-registry.js +1 -0
- package/source-capability-types.d.ts +186 -0
- package/source-capability-types.js +7 -0
- package/style/index.d.ts +2 -0
- package/style/index.d.ts.map +1 -1
- package/style/index.js +2 -0
- package/style/renderers.d.ts +326 -0
- package/style/renderers.d.ts.map +1 -0
- package/style/renderers.js +517 -0
- package/web-components/controller.d.ts +2 -0
- package/web-components/controller.d.ts.map +1 -1
- package/web-components/controller.js +49 -8
- package/web-components/elements.d.ts +95 -1
- package/web-components/elements.d.ts.map +1 -1
- package/web-components/elements.js +458 -19
- package/web-components/index.d.ts +8 -1
- package/web-components/index.d.ts.map +1 -1
- package/web-components/index.js +7 -0
- package/web-components/maplibre-renderer.d.ts.map +1 -1
- package/web-components/maplibre-renderer.js +87 -0
- package/web-components/measurement.d.ts +69 -0
- package/web-components/measurement.d.ts.map +1 -0
- package/web-components/measurement.js +523 -0
- package/web-components/types.d.ts +109 -0
- package/web-components/types.d.ts.map +1 -1
- package/webmap/convert-renderer.d.ts +24 -3
- package/webmap/convert-renderer.d.ts.map +1 -1
- package/webmap/convert-renderer.js +93 -112
- package/webmap/index.d.ts +1 -1
- package/webmap/index.d.ts.map +1 -1
- package/webmap/index.js +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHonuaWebComponentController } from "./controller.js";
|
|
2
2
|
import { HonuaMapLibreRenderer } from "./maplibre-renderer.js";
|
|
3
|
+
import { HonuaMeasurementElement } from "./measurement.js";
|
|
3
4
|
const globalDom = globalThis;
|
|
4
5
|
const HTMLElementBase = globalDom.HTMLElement ?? class {
|
|
5
6
|
};
|
|
@@ -348,36 +349,110 @@ export class HonuaMapElement extends HonuaElementBase {
|
|
|
348
349
|
return "No map package";
|
|
349
350
|
}
|
|
350
351
|
}
|
|
352
|
+
/**
|
|
353
|
+
* `<honua-layer-list>` — the survival-tier layer list (issue #493). Renders a
|
|
354
|
+
* row per runtime layer (in style order: the last row draws on top) with:
|
|
355
|
+
*
|
|
356
|
+
* - a visibility checkbox bound to `controller.setLayerVisibility`;
|
|
357
|
+
* - an opacity slider (rendered when the controller implements
|
|
358
|
+
* `setLayerOpacity`), committed on `change` so keyboard arrows and pointer
|
|
359
|
+
* drags both work;
|
|
360
|
+
* - reorder affordances (rendered when the controller implements
|
|
361
|
+
* `moveLayer`): keyboard-operable "Move up"/"Move down" buttons plus HTML5
|
|
362
|
+
* drag-and-drop between rows.
|
|
363
|
+
*
|
|
364
|
+
* Rows re-render from controller state events, so external visibility /
|
|
365
|
+
* opacity / order changes stay in sync. Theme via the `--honua-ui-*` CSS
|
|
366
|
+
* custom properties; rows are exposed as a `role="list"` of `listitem`s.
|
|
367
|
+
*/
|
|
351
368
|
export class HonuaLayerListElement extends HonuaElementBase {
|
|
352
369
|
static get observedAttributes() {
|
|
353
370
|
return ["for", "label"];
|
|
354
371
|
}
|
|
372
|
+
#dragLayerId;
|
|
373
|
+
#layersOverride;
|
|
374
|
+
/**
|
|
375
|
+
* The layer rows currently rendered. Headless hosts (for example the
|
|
376
|
+
* esri-compat LayerList shim delegating through `HonuaWidgetHost`) can
|
|
377
|
+
* assign this directly to bypass the controller; user toggles then surface
|
|
378
|
+
* only through the `honua-layer-visibility-change` event. Assign
|
|
379
|
+
* `undefined` to return to controller-driven rows.
|
|
380
|
+
*/
|
|
381
|
+
get layers() {
|
|
382
|
+
return this.#layersOverride ?? this.state?.layers ?? [];
|
|
383
|
+
}
|
|
384
|
+
set layers(layers) {
|
|
385
|
+
this.#layersOverride = layers;
|
|
386
|
+
this.render();
|
|
387
|
+
}
|
|
355
388
|
attributeChangedCallback() {
|
|
356
389
|
this.resolveControllerFromContext();
|
|
357
390
|
this.render();
|
|
358
391
|
}
|
|
392
|
+
controllerChanged() {
|
|
393
|
+
this.render();
|
|
394
|
+
}
|
|
359
395
|
render() {
|
|
360
|
-
const layers = this.
|
|
396
|
+
const layers = this.layers;
|
|
361
397
|
const label = this.getAttribute("label") ?? "Layers";
|
|
398
|
+
const supportsOpacity = typeof this.controller?.setLayerOpacity === "function";
|
|
399
|
+
const supportsReorder = typeof this.controller?.moveLayer === "function";
|
|
362
400
|
this.setShadowHtml(`
|
|
363
|
-
<style>${baseStyles()}${listStyles()}</style>
|
|
401
|
+
<style>${baseStyles()}${listStyles()}${layerListStyles()}</style>
|
|
364
402
|
<fieldset class="panel" part="panel">
|
|
365
403
|
<legend>${escapeHtml(label)}</legend>
|
|
366
404
|
<div class="stack" role="list">
|
|
367
405
|
${layers.length === 0
|
|
368
406
|
? `<p class="empty">No layers</p>`
|
|
369
407
|
: 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
|
-
`)
|
|
408
|
+
.map((layer, index) => this.renderRow(layer, index, layers.length, supportsOpacity, supportsReorder))
|
|
376
409
|
.join("")}
|
|
377
410
|
</div>
|
|
378
411
|
</fieldset>
|
|
379
412
|
`);
|
|
380
|
-
this.
|
|
413
|
+
this.bindRows(supportsReorder);
|
|
414
|
+
}
|
|
415
|
+
renderRow(layer, index, count, supportsOpacity, supportsReorder) {
|
|
416
|
+
const id = escapeAttribute(layer.id);
|
|
417
|
+
const opacityPercent = Math.round((layer.opacity ?? 1) * 100);
|
|
418
|
+
// Generic control names ("Opacity", "Move up") keep each row's checkbox as
|
|
419
|
+
// the only control whose accessible name is the layer title; the
|
|
420
|
+
// surrounding listitem carries the title for context.
|
|
421
|
+
const opacity = supportsOpacity
|
|
422
|
+
? `
|
|
423
|
+
<input
|
|
424
|
+
type="range"
|
|
425
|
+
class="opacity"
|
|
426
|
+
part="opacity"
|
|
427
|
+
min="0"
|
|
428
|
+
max="100"
|
|
429
|
+
step="1"
|
|
430
|
+
value="${opacityPercent}"
|
|
431
|
+
aria-label="Opacity"
|
|
432
|
+
aria-valuetext="${opacityPercent}%"
|
|
433
|
+
data-layer-opacity="${id}"
|
|
434
|
+
/>`
|
|
435
|
+
: "";
|
|
436
|
+
const reorder = supportsReorder
|
|
437
|
+
? `
|
|
438
|
+
<button type="button" class="move" part="move-up" aria-label="Move up" data-move="up:${id}" ${index === 0 ? "disabled" : ""}>▲</button>
|
|
439
|
+
<button type="button" class="move" part="move-down" aria-label="Move down" data-move="down:${id}" ${index === count - 1 ? "disabled" : ""}>▼</button>`
|
|
440
|
+
: "";
|
|
441
|
+
return `
|
|
442
|
+
<div class="layer-row" role="listitem" part="row" data-layer-row="${id}"${supportsReorder ? ` draggable="true"` : ""}>
|
|
443
|
+
<label class="check-row">
|
|
444
|
+
<input type="checkbox" data-layer-id="${id}" ${layer.visible ? "checked" : ""} />
|
|
445
|
+
<span>${escapeHtml(layer.title)}</span>
|
|
446
|
+
</label>
|
|
447
|
+
${supportsOpacity || supportsReorder ? `<div class="layer-row__tools">${opacity}${reorder}</div>` : ""}
|
|
448
|
+
</div>
|
|
449
|
+
`;
|
|
450
|
+
}
|
|
451
|
+
bindRows(supportsReorder) {
|
|
452
|
+
const root = this.shadowRoot;
|
|
453
|
+
if (!root)
|
|
454
|
+
return;
|
|
455
|
+
root.querySelectorAll("input[data-layer-id]").forEach((input) => {
|
|
381
456
|
input.addEventListener("change", () => {
|
|
382
457
|
const layerId = input.dataset.layerId;
|
|
383
458
|
if (!layerId)
|
|
@@ -389,32 +464,154 @@ export class HonuaLayerListElement extends HonuaElementBase {
|
|
|
389
464
|
});
|
|
390
465
|
});
|
|
391
466
|
});
|
|
467
|
+
root.querySelectorAll("input[data-layer-opacity]").forEach((input) => {
|
|
468
|
+
input.addEventListener("change", () => {
|
|
469
|
+
const layerId = input.dataset.layerOpacity;
|
|
470
|
+
if (!layerId)
|
|
471
|
+
return;
|
|
472
|
+
const opacity = Math.min(1, Math.max(0, Number(input.value) / 100));
|
|
473
|
+
this.controller?.setLayerOpacity?.(layerId, opacity);
|
|
474
|
+
this.dispatchTypedEvent("honua-layer-opacity-change", { layerId, opacity });
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
root.querySelectorAll("button[data-move]").forEach((button) => {
|
|
478
|
+
button.addEventListener("click", () => {
|
|
479
|
+
const encoded = button.dataset.move ?? "";
|
|
480
|
+
const separator = encoded.indexOf(":");
|
|
481
|
+
if (separator === -1)
|
|
482
|
+
return;
|
|
483
|
+
const direction = encoded.slice(0, separator);
|
|
484
|
+
const layerId = encoded.slice(separator + 1);
|
|
485
|
+
this.moveByOffset(layerId, direction === "up" ? -1 : 1);
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
if (!supportsReorder)
|
|
489
|
+
return;
|
|
490
|
+
root.querySelectorAll("[data-layer-row]").forEach((row) => {
|
|
491
|
+
row.addEventListener("dragstart", (event) => {
|
|
492
|
+
const layerId = row.dataset.layerRow;
|
|
493
|
+
if (!layerId)
|
|
494
|
+
return;
|
|
495
|
+
this.#dragLayerId = layerId;
|
|
496
|
+
const transfer = event.dataTransfer;
|
|
497
|
+
transfer?.setData("text/plain", layerId);
|
|
498
|
+
if (transfer)
|
|
499
|
+
transfer.effectAllowed = "move";
|
|
500
|
+
});
|
|
501
|
+
row.addEventListener("dragover", (event) => {
|
|
502
|
+
if (this.#dragLayerId)
|
|
503
|
+
event.preventDefault();
|
|
504
|
+
});
|
|
505
|
+
row.addEventListener("drop", (event) => {
|
|
506
|
+
event.preventDefault();
|
|
507
|
+
const source = this.#dragLayerId ?? event.dataTransfer?.getData("text/plain");
|
|
508
|
+
const target = row.dataset.layerRow;
|
|
509
|
+
this.#dragLayerId = undefined;
|
|
510
|
+
if (!source || !target || source === target)
|
|
511
|
+
return;
|
|
512
|
+
this.moveBefore(source, target);
|
|
513
|
+
});
|
|
514
|
+
row.addEventListener("dragend", () => {
|
|
515
|
+
this.#dragLayerId = undefined;
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
/** Moves a layer one list position up (`-1`) or down (`+1`). */
|
|
520
|
+
moveByOffset(layerId, offset) {
|
|
521
|
+
const layers = this.layers;
|
|
522
|
+
const index = layers.findIndex((layer) => layer.id === layerId);
|
|
523
|
+
if (index === -1)
|
|
524
|
+
return;
|
|
525
|
+
const targetIndex = index + offset;
|
|
526
|
+
if (targetIndex < 0 || targetIndex >= layers.length)
|
|
527
|
+
return;
|
|
528
|
+
const beforeId = offset === -1 ? layers[index - 1]?.id : layers[index + 2]?.id;
|
|
529
|
+
this.applyMove(layerId, beforeId);
|
|
530
|
+
}
|
|
531
|
+
moveBefore(layerId, targetId) {
|
|
532
|
+
this.applyMove(layerId, targetId);
|
|
533
|
+
}
|
|
534
|
+
applyMove(layerId, beforeId) {
|
|
535
|
+
const controller = this.controller;
|
|
536
|
+
if (!controller?.moveLayer)
|
|
537
|
+
return;
|
|
538
|
+
controller.moveLayer(layerId, beforeId);
|
|
539
|
+
this.dispatchTypedEvent("honua-layer-order-change", {
|
|
540
|
+
layerId,
|
|
541
|
+
...(beforeId !== undefined ? { beforeId } : {}),
|
|
542
|
+
order: controller.getState().layers.map((layer) => layer.id),
|
|
543
|
+
});
|
|
392
544
|
}
|
|
393
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* `<honua-legend>` — the survival-tier legend (issue #493). Renders
|
|
548
|
+
* swatch+label rows from the controller's runtime legend model
|
|
549
|
+
* (`HonuaLegendItem[]` derived from the map package / renderer metadata) and
|
|
550
|
+
* reacts to layer visibility changes: entries carrying a `layerId` are hidden
|
|
551
|
+
* while that layer is toggled off, unless the `include-hidden` attribute is
|
|
552
|
+
* present.
|
|
553
|
+
*
|
|
554
|
+
* Headless hosts (for example the esri-compat Legend shim delegating through
|
|
555
|
+
* `HonuaWidgetHost`) can bypass the controller and assign the `items`
|
|
556
|
+
* property directly.
|
|
557
|
+
*
|
|
558
|
+
* Swatches are `aria-hidden` presentation; the text labels carry the meaning.
|
|
559
|
+
* Theme via the `--honua-ui-*` CSS custom properties.
|
|
560
|
+
*/
|
|
394
561
|
export class HonuaLegendElement extends HonuaElementBase {
|
|
395
562
|
static get observedAttributes() {
|
|
396
|
-
return ["for", "label"];
|
|
563
|
+
return ["for", "label", "include-hidden"];
|
|
564
|
+
}
|
|
565
|
+
#itemsOverride;
|
|
566
|
+
/**
|
|
567
|
+
* Explicit legend items. When set, these render instead of the controller
|
|
568
|
+
* state's legend (visibility coupling still applies when the controller is
|
|
569
|
+
* also present). Assign `undefined` to return to controller-driven items.
|
|
570
|
+
*/
|
|
571
|
+
get items() {
|
|
572
|
+
return this.#itemsOverride;
|
|
573
|
+
}
|
|
574
|
+
set items(items) {
|
|
575
|
+
this.#itemsOverride = items;
|
|
576
|
+
this.render();
|
|
577
|
+
}
|
|
578
|
+
/** Render entries for hidden layers too. Reflects the `include-hidden` attribute. */
|
|
579
|
+
get includeHidden() {
|
|
580
|
+
return typeof this.hasAttribute === "function" && this.hasAttribute("include-hidden");
|
|
397
581
|
}
|
|
398
582
|
attributeChangedCallback() {
|
|
399
583
|
this.resolveControllerFromContext();
|
|
400
584
|
this.render();
|
|
401
585
|
}
|
|
586
|
+
/** The items currently rendered (after layer-visibility filtering). */
|
|
587
|
+
get visibleItems() {
|
|
588
|
+
const items = this.#itemsOverride ?? this.state?.legend ?? [];
|
|
589
|
+
if (this.includeHidden)
|
|
590
|
+
return items;
|
|
591
|
+
const layers = this.state?.layers ?? [];
|
|
592
|
+
return items.filter((item) => {
|
|
593
|
+
if (!item.layerId)
|
|
594
|
+
return true;
|
|
595
|
+
const layer = layers.find((candidate) => candidate.id === item.layerId);
|
|
596
|
+
return layer ? layer.visible : true;
|
|
597
|
+
});
|
|
598
|
+
}
|
|
402
599
|
render() {
|
|
403
|
-
const legend = this.
|
|
600
|
+
const legend = this.visibleItems;
|
|
404
601
|
const label = this.getAttribute("label") ?? "Legend";
|
|
405
602
|
this.setShadowHtml(`
|
|
406
603
|
<style>${baseStyles()}${listStyles()}</style>
|
|
407
604
|
<section class="panel" part="panel" aria-label="${escapeHtml(label)}">
|
|
408
605
|
<h2>${escapeHtml(label)}</h2>
|
|
409
|
-
<ul class="legend">
|
|
606
|
+
<ul class="legend" role="list">
|
|
410
607
|
${legend.length === 0
|
|
411
608
|
? `<li class="empty">No legend</li>`
|
|
412
609
|
: legend
|
|
413
610
|
.map((item) => `
|
|
414
|
-
<li>
|
|
611
|
+
<li role="listitem" data-legend-item="${escapeAttribute(item.id)}">
|
|
415
612
|
${item.iconUrl
|
|
416
|
-
? `<img class="swatch" alt="" src="${escapeAttribute(item.iconUrl)}" />`
|
|
417
|
-
: `<span class="swatch" style="--swatch:${escapeAttribute(item.color ?? "#64748b")}"></span>`}
|
|
613
|
+
? `<img class="swatch" alt="" aria-hidden="true" src="${escapeAttribute(item.iconUrl)}" />`
|
|
614
|
+
: `<span class="swatch" aria-hidden="true" style="--swatch:${escapeAttribute(item.color ?? "#64748b")}"></span>`}
|
|
418
615
|
<span>${escapeHtml(item.label)}</span>
|
|
419
616
|
</li>
|
|
420
617
|
`)
|
|
@@ -535,37 +732,109 @@ export class HonuaFeatureTableElement extends HonuaElementBase {
|
|
|
535
732
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
536
733
|
}
|
|
537
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* `<honua-search>` — the survival-tier search box (issue #493).
|
|
737
|
+
*
|
|
738
|
+
* Two lanes:
|
|
739
|
+
*
|
|
740
|
+
* - **Feature search** (default) — submitting the form runs
|
|
741
|
+
* `controller.search` over the shared dataset state and renders selectable
|
|
742
|
+
* feature results (the pre-existing behavior).
|
|
743
|
+
* - **Geocoding search** — assign the `geocoder` property a provider
|
|
744
|
+
* satisfying {@link HonuaSearchGeocoderLike} (a `HonuaGeocodingClient` from
|
|
745
|
+
* the stable `@honua/sdk-js/geocoding` entrypoint fits structurally). The
|
|
746
|
+
* input becomes an ARIA combobox with debounced typeahead suggestions
|
|
747
|
+
* (`debounce` attribute, default 250 ms) navigated with ArrowUp / ArrowDown,
|
|
748
|
+
* accepted with Enter, dismissed with Escape. Selecting a suggestion (or
|
|
749
|
+
* submitting) forward-geocodes and pans/zooms the map by writing the
|
|
750
|
+
* controller viewport (`zoom` attribute, default 15), then dispatches
|
|
751
|
+
* `honua-geocode-select`.
|
|
752
|
+
*/
|
|
538
753
|
export class HonuaSearchElement extends HonuaElementBase {
|
|
539
754
|
static get observedAttributes() {
|
|
540
|
-
return ["for", "source", "placeholder", "label"];
|
|
755
|
+
return ["for", "source", "placeholder", "label", "debounce", "zoom"];
|
|
541
756
|
}
|
|
542
757
|
#query = "";
|
|
543
758
|
#results = [];
|
|
759
|
+
#geocoder;
|
|
760
|
+
#suggestions = [];
|
|
761
|
+
#activeIndex = -1;
|
|
762
|
+
#status = "";
|
|
763
|
+
#suggestTimer;
|
|
764
|
+
#suggestToken = 0;
|
|
765
|
+
#geocodeToken = 0;
|
|
766
|
+
/** The geocoding provider powering typeahead + geocode-on-submit. */
|
|
767
|
+
get geocoder() {
|
|
768
|
+
return this.#geocoder;
|
|
769
|
+
}
|
|
770
|
+
set geocoder(geocoder) {
|
|
771
|
+
this.#geocoder = geocoder;
|
|
772
|
+
this.#clearSuggestTimer();
|
|
773
|
+
this.#suggestions = [];
|
|
774
|
+
this.#activeIndex = -1;
|
|
775
|
+
this.#status = "";
|
|
776
|
+
this.render();
|
|
777
|
+
}
|
|
544
778
|
attributeChangedCallback() {
|
|
545
779
|
this.resolveControllerFromContext();
|
|
546
780
|
this.render();
|
|
547
781
|
}
|
|
782
|
+
disconnectedCallback() {
|
|
783
|
+
this.#clearSuggestTimer();
|
|
784
|
+
super.disconnectedCallback();
|
|
785
|
+
}
|
|
548
786
|
render() {
|
|
549
787
|
const label = this.getAttribute("label") ?? "Search";
|
|
550
788
|
const placeholder = this.getAttribute("placeholder") ?? "Search";
|
|
789
|
+
const geocoding = this.#geocoder !== undefined;
|
|
790
|
+
const expanded = geocoding && this.#suggestions.length > 0;
|
|
791
|
+
const comboboxAttributes = geocoding
|
|
792
|
+
? ` role="combobox" aria-autocomplete="list" aria-expanded="${String(expanded)}" aria-controls="honua-search-listbox"${this.#activeIndex >= 0 ? ` aria-activedescendant="honua-search-option-${this.#activeIndex}"` : ""}`
|
|
793
|
+
: "";
|
|
551
794
|
this.setShadowHtml(`
|
|
552
795
|
<style>${baseStyles()}${searchStyles()}</style>
|
|
553
796
|
<section class="search" part="panel" aria-label="${escapeHtml(label)}">
|
|
554
797
|
<form>
|
|
555
798
|
<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" />
|
|
799
|
+
<input id="honua-search-input" name="q" value="${escapeAttribute(this.#query)}" placeholder="${escapeAttribute(placeholder)}" autocomplete="off"${comboboxAttributes} />
|
|
557
800
|
<button type="submit">Search</button>
|
|
558
801
|
</form>
|
|
802
|
+
${geocoding
|
|
803
|
+
? `<ul class="suggestions" id="honua-search-listbox" role="listbox" aria-label="${escapeAttribute(`${label} suggestions`)}"${expanded ? "" : " hidden"}>
|
|
804
|
+
${this.#suggestions
|
|
805
|
+
.map((suggestion, index) => `<li id="honua-search-option-${index}" role="option" aria-selected="${String(index === this.#activeIndex)}" data-suggestion-index="${index}">${escapeHtml(suggestion.text)}</li>`)
|
|
806
|
+
.join("")}
|
|
807
|
+
</ul>
|
|
808
|
+
<p class="status" role="status" aria-live="polite">${escapeHtml(this.#status)}</p>`
|
|
809
|
+
: ""}
|
|
559
810
|
<ul class="results" aria-live="polite">
|
|
560
811
|
${this.#results.map((result) => `<li><button type="button" data-result-id="${escapeHtml(result.id)}">${escapeHtml(result.label)}</button></li>`).join("")}
|
|
561
812
|
</ul>
|
|
562
813
|
</section>
|
|
563
814
|
`);
|
|
815
|
+
const input = this.shadowRoot?.querySelector("input[name='q']");
|
|
564
816
|
this.shadowRoot?.querySelector("form")?.addEventListener("submit", (event) => {
|
|
565
817
|
event.preventDefault();
|
|
566
|
-
const
|
|
567
|
-
|
|
818
|
+
const query = input?.value ?? "";
|
|
819
|
+
if (this.#geocoder)
|
|
820
|
+
void this.runGeocode(query);
|
|
821
|
+
else
|
|
822
|
+
void this.runSearch(query);
|
|
568
823
|
});
|
|
824
|
+
if (this.#geocoder) {
|
|
825
|
+
input?.addEventListener("input", () => {
|
|
826
|
+
this.#query = input.value;
|
|
827
|
+
this.scheduleSuggest();
|
|
828
|
+
});
|
|
829
|
+
input?.addEventListener("keydown", (event) => this.onComboboxKeydown(event));
|
|
830
|
+
this.shadowRoot?.querySelectorAll("li[data-suggestion-index]").forEach((option) => {
|
|
831
|
+
option.addEventListener("click", () => {
|
|
832
|
+
const index = Number(option.dataset.suggestionIndex);
|
|
833
|
+
if (Number.isInteger(index))
|
|
834
|
+
void this.selectSuggestion(index);
|
|
835
|
+
});
|
|
836
|
+
});
|
|
837
|
+
}
|
|
569
838
|
this.shadowRoot?.querySelectorAll("button[data-result-id]").forEach((button) => {
|
|
570
839
|
button.addEventListener("click", () => {
|
|
571
840
|
const result = this.#results.find((candidate) => candidate.id === button.dataset.resultId);
|
|
@@ -584,6 +853,126 @@ export class HonuaSearchElement extends HonuaElementBase {
|
|
|
584
853
|
});
|
|
585
854
|
});
|
|
586
855
|
}
|
|
856
|
+
onComboboxKeydown(event) {
|
|
857
|
+
if (this.#suggestions.length === 0)
|
|
858
|
+
return;
|
|
859
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
860
|
+
event.preventDefault();
|
|
861
|
+
const count = this.#suggestions.length;
|
|
862
|
+
const offset = event.key === "ArrowDown" ? 1 : -1;
|
|
863
|
+
this.#activeIndex = (this.#activeIndex + offset + count) % count;
|
|
864
|
+
this.render();
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
if (event.key === "Enter" && this.#activeIndex >= 0) {
|
|
868
|
+
event.preventDefault();
|
|
869
|
+
void this.selectSuggestion(this.#activeIndex);
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if (event.key === "Escape") {
|
|
873
|
+
event.preventDefault();
|
|
874
|
+
this.#clearSuggestTimer();
|
|
875
|
+
this.#suggestions = [];
|
|
876
|
+
this.#activeIndex = -1;
|
|
877
|
+
this.render();
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
scheduleSuggest() {
|
|
881
|
+
this.#clearSuggestTimer();
|
|
882
|
+
const geocoder = this.#geocoder;
|
|
883
|
+
if (!geocoder?.suggest)
|
|
884
|
+
return;
|
|
885
|
+
const text = this.#query.trim();
|
|
886
|
+
if (!text) {
|
|
887
|
+
this.#suggestions = [];
|
|
888
|
+
this.#activeIndex = -1;
|
|
889
|
+
this.render();
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
this.#suggestTimer = setTimeout(() => {
|
|
893
|
+
this.#suggestTimer = undefined;
|
|
894
|
+
void this.runSuggest(text);
|
|
895
|
+
}, this.debounceMs());
|
|
896
|
+
}
|
|
897
|
+
async runSuggest(text) {
|
|
898
|
+
const geocoder = this.#geocoder;
|
|
899
|
+
if (!geocoder?.suggest)
|
|
900
|
+
return;
|
|
901
|
+
const token = ++this.#suggestToken;
|
|
902
|
+
try {
|
|
903
|
+
const suggestions = await geocoder.suggest(text, { maxSuggestions: 8 });
|
|
904
|
+
if (token !== this.#suggestToken)
|
|
905
|
+
return;
|
|
906
|
+
this.#suggestions = suggestions;
|
|
907
|
+
this.#activeIndex = -1;
|
|
908
|
+
this.render();
|
|
909
|
+
}
|
|
910
|
+
catch (error) {
|
|
911
|
+
if (token !== this.#suggestToken)
|
|
912
|
+
return;
|
|
913
|
+
this.#suggestions = [];
|
|
914
|
+
this.#activeIndex = -1;
|
|
915
|
+
this.#status = error instanceof Error ? error.message : "Suggestions unavailable.";
|
|
916
|
+
this.render();
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
async selectSuggestion(index) {
|
|
920
|
+
const suggestion = this.#suggestions[index];
|
|
921
|
+
if (!suggestion)
|
|
922
|
+
return;
|
|
923
|
+
this.#query = suggestion.text;
|
|
924
|
+
this.#suggestions = [];
|
|
925
|
+
this.#activeIndex = -1;
|
|
926
|
+
await this.runGeocode(suggestion.text);
|
|
927
|
+
}
|
|
928
|
+
async runGeocode(query) {
|
|
929
|
+
const geocoder = this.#geocoder;
|
|
930
|
+
if (!geocoder)
|
|
931
|
+
return;
|
|
932
|
+
this.#clearSuggestTimer();
|
|
933
|
+
this.#suggestToken += 1;
|
|
934
|
+
// Overlapping geocodes resolve out of order on slow networks; only the
|
|
935
|
+
// most recent request may write the viewport/status or emit the event.
|
|
936
|
+
const token = ++this.#geocodeToken;
|
|
937
|
+
this.#query = query;
|
|
938
|
+
this.#suggestions = [];
|
|
939
|
+
this.#activeIndex = -1;
|
|
940
|
+
const trimmed = query.trim();
|
|
941
|
+
if (!trimmed) {
|
|
942
|
+
this.#status = "";
|
|
943
|
+
this.render();
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
try {
|
|
947
|
+
const candidates = await geocoder.forwardGeocode(trimmed, { maxResults: 1 });
|
|
948
|
+
if (token !== this.#geocodeToken)
|
|
949
|
+
return;
|
|
950
|
+
const candidate = candidates[0];
|
|
951
|
+
if (!candidate) {
|
|
952
|
+
this.#status = `No results for "${trimmed}".`;
|
|
953
|
+
this.render();
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const viewport = {
|
|
957
|
+
center: [candidate.longitude, candidate.latitude],
|
|
958
|
+
zoom: this.resultZoom(),
|
|
959
|
+
};
|
|
960
|
+
this.controller?.setViewport(viewport);
|
|
961
|
+
this.#status = candidate.address;
|
|
962
|
+
this.dispatchTypedEvent("honua-geocode-select", {
|
|
963
|
+
query: trimmed,
|
|
964
|
+
candidate,
|
|
965
|
+
viewport,
|
|
966
|
+
});
|
|
967
|
+
this.render();
|
|
968
|
+
}
|
|
969
|
+
catch (error) {
|
|
970
|
+
if (token !== this.#geocodeToken)
|
|
971
|
+
return;
|
|
972
|
+
this.#status = error instanceof Error ? error.message : "Geocoding failed.";
|
|
973
|
+
this.render();
|
|
974
|
+
}
|
|
975
|
+
}
|
|
587
976
|
async runSearch(query) {
|
|
588
977
|
this.#query = query;
|
|
589
978
|
const sourceId = this.getAttribute("source") ?? undefined;
|
|
@@ -591,6 +980,20 @@ export class HonuaSearchElement extends HonuaElementBase {
|
|
|
591
980
|
this.dispatchTypedEvent("honua-search", { query, results: this.#results });
|
|
592
981
|
this.render();
|
|
593
982
|
}
|
|
983
|
+
debounceMs() {
|
|
984
|
+
const parsed = Number(this.getAttribute("debounce"));
|
|
985
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 250;
|
|
986
|
+
}
|
|
987
|
+
resultZoom() {
|
|
988
|
+
const parsed = Number(this.getAttribute("zoom"));
|
|
989
|
+
return Number.isFinite(parsed) ? parsed : 15;
|
|
990
|
+
}
|
|
991
|
+
#clearSuggestTimer() {
|
|
992
|
+
if (this.#suggestTimer === undefined)
|
|
993
|
+
return;
|
|
994
|
+
clearTimeout(this.#suggestTimer);
|
|
995
|
+
this.#suggestTimer = undefined;
|
|
996
|
+
}
|
|
594
997
|
}
|
|
595
998
|
export class HonuaEditorElement extends HonuaElementBase {
|
|
596
999
|
static get observedAttributes() {
|
|
@@ -1160,6 +1563,7 @@ export function defineHonuaWebComponents(registry = globalDom.customElements) {
|
|
|
1160
1563
|
defineIfMissing(registry, "honua-bookmarks", HonuaBookmarksElement);
|
|
1161
1564
|
defineIfMissing(registry, "honua-locate-control", HonuaLocateControlElement);
|
|
1162
1565
|
defineIfMissing(registry, "honua-measure-control", HonuaMeasureControlElement);
|
|
1566
|
+
defineIfMissing(registry, "honua-measurement", HonuaMeasurementElement);
|
|
1163
1567
|
defineIfMissing(registry, "honua-sketch-control", HonuaSketchControlElement);
|
|
1164
1568
|
defineIfMissing(registry, "honua-print-export", HonuaPrintExportElement);
|
|
1165
1569
|
defineIfMissing(registry, "honua-map-status", HonuaMapStatusElement);
|
|
@@ -1499,6 +1903,24 @@ function listStyles() {
|
|
|
1499
1903
|
img.swatch { object-fit: cover; }
|
|
1500
1904
|
`;
|
|
1501
1905
|
}
|
|
1906
|
+
function layerListStyles() {
|
|
1907
|
+
return `
|
|
1908
|
+
.layer-row {
|
|
1909
|
+
border-top: 1px solid transparent;
|
|
1910
|
+
display: grid;
|
|
1911
|
+
gap: 4px;
|
|
1912
|
+
}
|
|
1913
|
+
.layer-row[draggable="true"] { cursor: grab; }
|
|
1914
|
+
.layer-row__tools {
|
|
1915
|
+
align-items: center;
|
|
1916
|
+
display: flex;
|
|
1917
|
+
gap: 6px;
|
|
1918
|
+
padding-left: 24px;
|
|
1919
|
+
}
|
|
1920
|
+
.opacity { flex: 1; min-width: 60px; }
|
|
1921
|
+
.move { min-width: 32px; padding: 0; }
|
|
1922
|
+
`;
|
|
1923
|
+
}
|
|
1502
1924
|
function tableStyles() {
|
|
1503
1925
|
return `
|
|
1504
1926
|
.table-panel {
|
|
@@ -1546,6 +1968,23 @@ function searchStyles() {
|
|
|
1546
1968
|
}
|
|
1547
1969
|
.results { display: grid; gap: 6px; list-style: none; margin: 10px 0 0; padding: 0; }
|
|
1548
1970
|
.results button { text-align: left; width: 100%; }
|
|
1971
|
+
.suggestions {
|
|
1972
|
+
border: 1px solid var(--honua-ui-border);
|
|
1973
|
+
border-radius: 6px;
|
|
1974
|
+
display: grid;
|
|
1975
|
+
list-style: none;
|
|
1976
|
+
margin: 6px 0 0;
|
|
1977
|
+
overflow: hidden;
|
|
1978
|
+
padding: 0;
|
|
1979
|
+
}
|
|
1980
|
+
.suggestions[hidden] { display: none; }
|
|
1981
|
+
.suggestions [role="option"] { cursor: pointer; padding: 6px 9px; }
|
|
1982
|
+
.suggestions [role="option"][aria-selected="true"] {
|
|
1983
|
+
background: var(--honua-ui-accent);
|
|
1984
|
+
color: var(--honua-ui-accent-fg);
|
|
1985
|
+
}
|
|
1986
|
+
.status { color: var(--honua-ui-muted); margin: 6px 0 0; }
|
|
1987
|
+
.status:empty { display: none; }
|
|
1549
1988
|
`;
|
|
1550
1989
|
}
|
|
1551
1990
|
function editorStyles() {
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
* `createHonuaWebComponentController`. Without a provider both controls render
|
|
14
14
|
* disabled by design with a "configure a provider" affordance.
|
|
15
15
|
*
|
|
16
|
+
* The survival-tier widget set (issue #493) — `<honua-legend>`,
|
|
17
|
+
* `<honua-layer-list>` (visibility / opacity / reorder), `<honua-search>`
|
|
18
|
+
* (geocoding-provider-aware), and `<honua-measurement>` (self-contained
|
|
19
|
+
* distance/area drawing on the map's pointer events, computed with
|
|
20
|
+
* `@honua/geometry` ops) — needs no external drawing provider.
|
|
21
|
+
*
|
|
16
22
|
* @experimental This entrypoint is not yet covered by the SDK's semver contract
|
|
17
23
|
* — the surface may change in any minor release prior to `1.0.0`.
|
|
18
24
|
* @module
|
|
@@ -20,5 +26,6 @@
|
|
|
20
26
|
import "./elements.js";
|
|
21
27
|
export { HonuaInMemoryWebComponentController, createHonuaWebComponentController, createHonuaWebComponentControllerFromRuntime, layersFromMapPackage, legendFromMapPackage, } from "./controller.js";
|
|
22
28
|
export { HonuaActionPanelElement, HonuaBasemapControlElement, HonuaBookmarksElement, HonuaChartElement, HonuaEditorElement, HonuaFeatureTableElement, HonuaLayerListElement, HonuaLegendElement, HonuaLocateControlElement, HonuaMapElement, HonuaMapStatusElement, HonuaMeasureControlElement, HonuaPrintExportElement, HonuaSearchElement, HonuaSketchControlElement, defineHonuaWebComponents, } from "./elements.js";
|
|
23
|
-
export
|
|
29
|
+
export { HonuaMeasurementElement, defineHonuaMeasurement } from "./measurement.js";
|
|
30
|
+
export type { HonuaActionDetail, HonuaActionPanelAction, HonuaBasemapChangeDetail, HonuaBookmark, HonuaBookmarkChangeDetail, CreateHonuaWebComponentControllerOptions, HonuaChartDatum, HonuaChartModel, HonuaComponentStatus, HonuaControllerReadyDetail, HonuaControllerStateListener, HonuaControllerSubscription, HonuaEditCapabilities, HonuaEditChangeDetail, HonuaEditRequest, HonuaEditorModel, HonuaExportDetail, HonuaFeatureRecord, HonuaFeatureStateEntry, HonuaFeatureStateTarget, HonuaFeatureTableModel, HonuaFilterChangeDetail, HonuaFilterState, HonuaFullscreenChangeDetail, HonuaGeocodeSelectDetail, HonuaLayerModel, HonuaLayerOpacityChangeDetail, HonuaLayerOrderChangeDetail, HonuaLayerVisibilityChangeDetail, HonuaLegendItem, HonuaLocateChangeDetail, HonuaMapClickDetail, HonuaMapErrorDetail, HonuaMapHoverDetail, HonuaMapInteractionDetail, HonuaMapInteractionPoint, HonuaMapReadyDetail, HonuaMeasureChangeDetail, HonuaMeasureMode, HonuaMeasureProvider, HonuaMeasureResult, HonuaMeasurementMap, HonuaQueryFeaturesOptions, HonuaSearchDetail, HonuaSearchGeocodeCandidate, HonuaSearchGeocodeSuggestion, HonuaSearchGeocoderLike, HonuaSearchOptions, HonuaSearchResult, HonuaSelectionChangeDetail, HonuaSelectionState, HonuaSketchChangeDetail, HonuaSketchMode, HonuaSketchProvider, HonuaSketchResult, HonuaViewportChangeDetail, HonuaViewportState, HonuaWebComponentController, HonuaWebComponentRuntimeLike, HonuaWebComponentState, } from "./types.js";
|
|
24
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/web-components/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/web-components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,eAAe,CAAC;AAEvB,OAAO,EACL,mCAAmC,EACnC,iCAAiC,EACjC,4CAA4C,EAC5C,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,EACvB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAEnF,YAAY,EACV,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,yBAAyB,EACzB,wCAAwC,EACxC,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,2BAA2B,EAC3B,wBAAwB,EACxB,eAAe,EACf,6BAA6B,EAC7B,2BAA2B,EAC3B,gCAAgC,EAChC,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EACjB,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,mBAAmB,EACnB,uBAAuB,EACvB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
|
package/web-components/index.js
CHANGED
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
* `createHonuaWebComponentController`. Without a provider both controls render
|
|
14
14
|
* disabled by design with a "configure a provider" affordance.
|
|
15
15
|
*
|
|
16
|
+
* The survival-tier widget set (issue #493) — `<honua-legend>`,
|
|
17
|
+
* `<honua-layer-list>` (visibility / opacity / reorder), `<honua-search>`
|
|
18
|
+
* (geocoding-provider-aware), and `<honua-measurement>` (self-contained
|
|
19
|
+
* distance/area drawing on the map's pointer events, computed with
|
|
20
|
+
* `@honua/geometry` ops) — needs no external drawing provider.
|
|
21
|
+
*
|
|
16
22
|
* @experimental This entrypoint is not yet covered by the SDK's semver contract
|
|
17
23
|
* — the surface may change in any minor release prior to `1.0.0`.
|
|
18
24
|
* @module
|
|
@@ -20,3 +26,4 @@
|
|
|
20
26
|
import "./elements.js";
|
|
21
27
|
export { HonuaInMemoryWebComponentController, createHonuaWebComponentController, createHonuaWebComponentControllerFromRuntime, layersFromMapPackage, legendFromMapPackage, } from "./controller.js";
|
|
22
28
|
export { HonuaActionPanelElement, HonuaBasemapControlElement, HonuaBookmarksElement, HonuaChartElement, HonuaEditorElement, HonuaFeatureTableElement, HonuaLayerListElement, HonuaLegendElement, HonuaLocateControlElement, HonuaMapElement, HonuaMapStatusElement, HonuaMeasureControlElement, HonuaPrintExportElement, HonuaSearchElement, HonuaSketchControlElement, defineHonuaWebComponents, } from "./elements.js";
|
|
29
|
+
export { HonuaMeasurementElement, defineHonuaMeasurement } from "./measurement.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maplibre-renderer.d.ts","sourceRoot":"","sources":["../../../src/web-components/maplibre-renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAGV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAqCpB,MAAM,WAAW,4BAA4B,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvE,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,IAAI,WAAW,GAAG,SAAS,CAAC;IACrC,aAAa,IAAI,2BAA2B,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC5D,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,UAAU,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACpD,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CAC1D;AAED,qBAAa,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;
|
|
1
|
+
{"version":3,"file":"maplibre-renderer.d.ts","sourceRoot":"","sources":["../../../src/web-components/maplibre-renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAGV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,4BAA4B,EAC5B,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAqCpB,MAAM,WAAW,4BAA4B,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvE,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,IAAI,WAAW,GAAG,SAAS,CAAC;IACrC,aAAa,IAAI,2BAA2B,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC5D,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3C,UAAU,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACpD,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC9C,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CAC1D;AAED,qBAAa,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;gBAgBzC,OAAO,EAAE,4BAA4B,CAAC,CAAC,CAAC;IAI3D,IAAW,GAAG,IAAI,OAAO,GAAG,SAAS,CAEpC;IAED,IAAW,OAAO,IAAI,4BAA4B,CAAC,CAAC,CAAC,GAAG,SAAS,CAEhE;IAEY,UAAU,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBjE,UAAU,IAAI,IAAI;CAwW1B"}
|