@honua/react 0.0.20-alpha.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 +12 -1
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +4 -0
- package/contract/pmtiles.d.ts +193 -0
- package/contract/pmtiles.d.ts.map +1 -0
- package/contract/pmtiles.js +195 -0
- 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 +57 -15
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +368 -65
- package/contract/types.d.ts +171 -6
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +14 -14
- package/core/auth/client-credentials-provider.d.ts +51 -0
- package/core/auth/client-credentials-provider.d.ts.map +1 -0
- package/core/auth/client-credentials-provider.js +115 -0
- package/core/auth/credential-store.d.ts +52 -0
- package/core/auth/credential-store.d.ts.map +1 -0
- package/core/auth/credential-store.js +82 -0
- package/core/auth/index.d.ts +23 -0
- package/core/auth/index.d.ts.map +1 -0
- package/core/auth/index.js +20 -0
- package/core/auth/oauth2-provider.d.ts +114 -0
- package/core/auth/oauth2-provider.d.ts.map +1 -0
- package/core/auth/oauth2-provider.js +408 -0
- package/core/auth/pkce.d.ts +25 -0
- package/core/auth/pkce.d.ts.map +1 -0
- package/core/auth/pkce.js +46 -0
- package/core/auth/static-providers.d.ts +20 -0
- package/core/auth/static-providers.d.ts.map +1 -0
- package/core/auth/static-providers.js +26 -0
- package/core/auth/token-endpoint.d.ts +40 -0
- package/core/auth/token-endpoint.d.ts.map +1 -0
- package/core/auth/token-endpoint.js +133 -0
- package/core/auth/types.d.ts +144 -0
- package/core/auth/types.d.ts.map +1 -0
- package/core/auth/types.js +8 -0
- 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 +35 -2
- package/core/client.d.ts.map +1 -1
- package/core/client.js +167 -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 +73 -25
- package/core/errors.d.ts.map +1 -1
- package/core/errors.js +113 -46
- package/core/geoparquet-sql.d.ts +190 -0
- package/core/geoparquet-sql.d.ts.map +1 -0
- package/core/geoparquet-sql.js +368 -0
- 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-endpoint-layout.d.ts +70 -0
- package/core/ogc-endpoint-layout.d.ts.map +1 -0
- package/core/ogc-endpoint-layout.js +173 -0
- package/core/ogc-features.d.ts.map +1 -1
- package/core/ogc-features.js +35 -17
- 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 +55 -0
- package/core/stac-static.d.ts.map +1 -0
- package/core/stac-static.js +386 -0
- package/core/stac.d.ts +12 -0
- package/core/stac.d.ts.map +1 -1
- package/core/stac.js +45 -15
- package/core/surfaces.d.ts +13 -0
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +127 -16
- package/core/types.d.ts +174 -7
- package/core/types.d.ts.map +1 -1
- package/core/wfs-capabilities.d.ts +12 -0
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +22 -3
- package/core/wfs.d.ts +13 -0
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +35 -5
- 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/identity-manager.d.ts +43 -0
- package/esri-compat/identity-manager.d.ts.map +1 -1
- package/esri-compat/identity-manager.js +131 -1
- 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/oauth-info.d.ts +15 -0
- package/esri-compat/oauth-info.d.ts.map +1 -1
- package/esri-compat/oauth-info.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/filter-registry/index.d.ts +145 -0
- package/filter-registry/index.d.ts.map +1 -0
- package/filter-registry/index.js +531 -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/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 +19 -1
- 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/react/external-map.d.ts +67 -0
- package/react/external-map.d.ts.map +1 -0
- package/react/external-map.js +63 -0
- package/react/honua-map.d.ts.map +1 -1
- package/react/honua-map.js +3 -2
- package/react/honua-source-layer.d.ts +110 -0
- package/react/honua-source-layer.d.ts.map +1 -0
- package/react/honua-source-layer.js +101 -0
- package/react/hooks.d.ts +28 -0
- package/react/hooks.d.ts.map +1 -1
- package/react/hooks.js +26 -4
- package/react/index.d.ts +8 -0
- package/react/index.d.ts.map +1 -1
- package/react/index.js +5 -0
- package/react/query-cache.d.ts +26 -4
- package/react/query-cache.d.ts.map +1 -1
- package/react/query-cache.js +51 -8
- package/react/selection.d.ts +177 -0
- package/react/selection.d.ts.map +1 -0
- package/react/selection.js +0 -0
- package/react/use-mounted-source.d.ts +69 -0
- package/react/use-mounted-source.d.ts.map +1 -0
- package/react/use-mounted-source.js +346 -0
- 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 +8 -2
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +4 -4
- package/runtime/load-package.d.ts.map +1 -1
- package/runtime/load-package.js +8 -0
- package/runtime/map-package-validation.d.ts +0 -13
- package/runtime/map-package-validation.d.ts.map +1 -1
- package/runtime/map-package-validation.js +0 -12
- package/runtime/map-package.d.ts +1 -1
- package/runtime/map-package.d.ts.map +1 -1
- 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/pmtiles-protocol.d.ts +77 -0
- package/runtime/pmtiles-protocol.d.ts.map +1 -0
- package/runtime/pmtiles-protocol.js +120 -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 +36 -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/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/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
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { UNSUPPORTED_FES, compileSpatialFilter, compileWhere, serializeFes } from "../core/wfs-filter.js";
|
|
2
|
+
import { HonuaQueryPlanningError } from "./types.js";
|
|
3
|
+
export { compileSemanticWfsQuery } from "./wfs-semantic.js";
|
|
4
|
+
/** Compile canonical query IR to a deterministic WFS 2.0 GetFeature request. */
|
|
5
|
+
export function compileWfsQuery(source, query) {
|
|
6
|
+
if (source.protocol !== "wfs") {
|
|
7
|
+
throw new HonuaQueryPlanningError("unsupported-compiler", `wfs-2.0-get-feature-v1 does not compile protocol "${source.protocol}"`);
|
|
8
|
+
}
|
|
9
|
+
if (!source.typeName) {
|
|
10
|
+
throw new HonuaQueryPlanningError("invalid-query", `Source "${source.id}" requires locator.typeName for WFS planning`);
|
|
11
|
+
}
|
|
12
|
+
if (query.aggregation) {
|
|
13
|
+
throw new HonuaQueryPlanningError("unsupported-query", "WFS 2.0 has no portable remote aggregation; use degraded policy with an explicit bounded-local fallback");
|
|
14
|
+
}
|
|
15
|
+
if (query.spatialFilter && query.outSr !== undefined) {
|
|
16
|
+
throw new HonuaQueryPlanningError("unsupported-query", "WFS planning cannot use outSr to label input filter coordinates; stamp the input geometry through the typed WFS escape hatch");
|
|
17
|
+
}
|
|
18
|
+
// Keep this aligned with the current WFS adapter's reviewed default. A
|
|
19
|
+
// vendor-specific geometry property requires the typed WFS escape hatch
|
|
20
|
+
// until discovery carries that binding into both planner and executor.
|
|
21
|
+
const geometryProperty = "the_geom";
|
|
22
|
+
const filters = [];
|
|
23
|
+
if (query.where) {
|
|
24
|
+
const where = compileWhere(query.where.expression);
|
|
25
|
+
if (where === UNSUPPORTED_FES) {
|
|
26
|
+
throw new HonuaQueryPlanningError("unsupported-query", "The where clause is not expressible as FES 2.0");
|
|
27
|
+
}
|
|
28
|
+
if (where.kind !== "and" || where.operands.length > 0)
|
|
29
|
+
filters.push(where);
|
|
30
|
+
}
|
|
31
|
+
if (query.spatialFilter) {
|
|
32
|
+
const spatial = compileSpatialFilter({
|
|
33
|
+
geometry: query.spatialFilter.geometry,
|
|
34
|
+
geometryType: query.spatialFilter.geometryType,
|
|
35
|
+
...(query.spatialFilter.spatialRel ? { spatialRel: query.spatialFilter.spatialRel } : {}),
|
|
36
|
+
}, {
|
|
37
|
+
geometryProperty,
|
|
38
|
+
});
|
|
39
|
+
if (spatial === UNSUPPORTED_FES) {
|
|
40
|
+
throw new HonuaQueryPlanningError("unsupported-query", "The spatial predicate is not expressible as FES 2.0");
|
|
41
|
+
}
|
|
42
|
+
filters.push(spatial);
|
|
43
|
+
}
|
|
44
|
+
let propertyName;
|
|
45
|
+
if (query.outFields && query.outFields.length > 0) {
|
|
46
|
+
const fields = [...query.outFields];
|
|
47
|
+
if (query.returnGeometry === false && fields.includes(geometryProperty)) {
|
|
48
|
+
throw new HonuaQueryPlanningError("unsupported-query", `WFS returnGeometry=false conflicts with outFields containing the geometry property "${geometryProperty}"`);
|
|
49
|
+
}
|
|
50
|
+
if (query.returnGeometry !== false && !fields.includes(geometryProperty))
|
|
51
|
+
fields.push(geometryProperty);
|
|
52
|
+
propertyName = fields;
|
|
53
|
+
}
|
|
54
|
+
else if (query.returnGeometry === false) {
|
|
55
|
+
throw new HonuaQueryPlanningError("unsupported-query", "WFS returnGeometry=false requires explicit outFields because propertyName cannot otherwise suppress geometry exactly");
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
compiler: "wfs-2.0-get-feature-v1",
|
|
59
|
+
typeName: source.typeName,
|
|
60
|
+
...(filters.length > 0 ? { filter: serializeFes(filters, { typeName: source.typeName }) } : {}),
|
|
61
|
+
...(propertyName ? { propertyName } : {}),
|
|
62
|
+
...(query.orderBy && query.orderBy.length > 0
|
|
63
|
+
? {
|
|
64
|
+
sortBy: query.orderBy.map((sort) => `${sort.field} ${sort.direction === "desc" ? "DESC" : "ASC"}`).join(","),
|
|
65
|
+
}
|
|
66
|
+
: {}),
|
|
67
|
+
...(query.pagination?.offset !== undefined ? { startIndex: query.pagination.offset } : {}),
|
|
68
|
+
...(query.pagination?.limit !== undefined ? { count: query.pagination.limit } : {}),
|
|
69
|
+
...(query.outSr !== undefined ? { srsName: String(query.outSr) } : {}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External-map interop for `@honua/react` (REQ-001 of the react depth pass).
|
|
3
|
+
*
|
|
4
|
+
* Every map-attached hook/component in this package resolves its MapLibre map
|
|
5
|
+
* through {@link useHonuaMap}: an explicit prop/argument wins, then the nearest
|
|
6
|
+
* {@link HonuaMapProvider} (or enclosing `HonuaMap`, which publishes the same
|
|
7
|
+
* context). The map is duck-typed as the data-to-map bridge's
|
|
8
|
+
* {@link DataToMapLibreMap} — any real `maplibre-gl` `Map` instance satisfies
|
|
9
|
+
* it, including the instance exposed by `@vis.gl/react-maplibre`'s `useMap()`
|
|
10
|
+
* (`mapRef.getMap()`). `@vis.gl/react-maplibre` is **not** a dependency; the
|
|
11
|
+
* interop is purely structural.
|
|
12
|
+
*
|
|
13
|
+
* SSR-safe: no `window` / `document` access at module scope.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { type ReactNode } from "react";
|
|
18
|
+
import type { DataToMapLibreMap } from "../map/data-to-map-bridge.js";
|
|
19
|
+
/**
|
|
20
|
+
* Context carrying the active, externally-visible MapLibre map instance.
|
|
21
|
+
* Populated by {@link HonuaMapProvider} and by `HonuaMap` (for its own map),
|
|
22
|
+
* so `useHonuaMap` always resolves the nearest enclosing map.
|
|
23
|
+
*
|
|
24
|
+
* @experimental
|
|
25
|
+
*/
|
|
26
|
+
export declare const HonuaExternalMapContext: import("react").Context<DataToMapLibreMap | null>;
|
|
27
|
+
/** Props for {@link HonuaMapProvider}. @experimental */
|
|
28
|
+
export interface HonuaMapProviderProps {
|
|
29
|
+
/**
|
|
30
|
+
* The externally-owned MapLibre map (duck-typed). Pass `null`/`undefined`
|
|
31
|
+
* while the map is still being created — descendants simply wait.
|
|
32
|
+
*/
|
|
33
|
+
map: DataToMapLibreMap | null | undefined;
|
|
34
|
+
children?: ReactNode;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Publish an externally-owned MapLibre map to the Honua map-attached hooks and
|
|
38
|
+
* components below it ({@link HonuaSourceLayer}, {@link useMountedSource},
|
|
39
|
+
* selection bindings). Use this when another library owns the map — e.g.
|
|
40
|
+
* `@vis.gl/react-maplibre`'s `<Map>` — and Honua should only mount data onto
|
|
41
|
+
* it. The provider never mutates or removes the map.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function Overlay() {
|
|
46
|
+
* const { current } = useMap(); // @vis.gl/react-maplibre
|
|
47
|
+
* return (
|
|
48
|
+
* <HonuaMapProvider map={current?.getMap() ?? null}>
|
|
49
|
+
* <HonuaSourceLayer source={source} hover />
|
|
50
|
+
* </HonuaMapProvider>
|
|
51
|
+
* );
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @experimental
|
|
56
|
+
*/
|
|
57
|
+
export declare function HonuaMapProvider({ map, children }: HonuaMapProviderProps): ReactNode;
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the MapLibre map a map-attached hook/component should target: the
|
|
60
|
+
* explicit `map` argument when given, otherwise the nearest enclosing
|
|
61
|
+
* {@link HonuaMapProvider} or `HonuaMap`. Returns `null` while no map is
|
|
62
|
+
* available (SSR, or before the map finished creating).
|
|
63
|
+
*
|
|
64
|
+
* @experimental
|
|
65
|
+
*/
|
|
66
|
+
export declare function useHonuaMap(map?: DataToMapLibreMap | null): DataToMapLibreMap | null;
|
|
67
|
+
//# sourceMappingURL=external-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-map.d.ts","sourceRoot":"","sources":["../../../src/react/external-map.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,OAAO,CAAC;AAElE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,mDAAgD,CAAC;AAGrF,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,GAAG,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,iBAAiB,GAAG,IAAI,GAAG,iBAAiB,GAAG,IAAI,CAGpF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* External-map interop for `@honua/react` (REQ-001 of the react depth pass).
|
|
4
|
+
*
|
|
5
|
+
* Every map-attached hook/component in this package resolves its MapLibre map
|
|
6
|
+
* through {@link useHonuaMap}: an explicit prop/argument wins, then the nearest
|
|
7
|
+
* {@link HonuaMapProvider} (or enclosing `HonuaMap`, which publishes the same
|
|
8
|
+
* context). The map is duck-typed as the data-to-map bridge's
|
|
9
|
+
* {@link DataToMapLibreMap} — any real `maplibre-gl` `Map` instance satisfies
|
|
10
|
+
* it, including the instance exposed by `@vis.gl/react-maplibre`'s `useMap()`
|
|
11
|
+
* (`mapRef.getMap()`). `@vis.gl/react-maplibre` is **not** a dependency; the
|
|
12
|
+
* interop is purely structural.
|
|
13
|
+
*
|
|
14
|
+
* SSR-safe: no `window` / `document` access at module scope.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import { createContext, useContext } from "react";
|
|
19
|
+
/**
|
|
20
|
+
* Context carrying the active, externally-visible MapLibre map instance.
|
|
21
|
+
* Populated by {@link HonuaMapProvider} and by `HonuaMap` (for its own map),
|
|
22
|
+
* so `useHonuaMap` always resolves the nearest enclosing map.
|
|
23
|
+
*
|
|
24
|
+
* @experimental
|
|
25
|
+
*/
|
|
26
|
+
export const HonuaExternalMapContext = createContext(null);
|
|
27
|
+
HonuaExternalMapContext.displayName = "HonuaExternalMapContext";
|
|
28
|
+
/**
|
|
29
|
+
* Publish an externally-owned MapLibre map to the Honua map-attached hooks and
|
|
30
|
+
* components below it ({@link HonuaSourceLayer}, {@link useMountedSource},
|
|
31
|
+
* selection bindings). Use this when another library owns the map — e.g.
|
|
32
|
+
* `@vis.gl/react-maplibre`'s `<Map>` — and Honua should only mount data onto
|
|
33
|
+
* it. The provider never mutates or removes the map.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* function Overlay() {
|
|
38
|
+
* const { current } = useMap(); // @vis.gl/react-maplibre
|
|
39
|
+
* return (
|
|
40
|
+
* <HonuaMapProvider map={current?.getMap() ?? null}>
|
|
41
|
+
* <HonuaSourceLayer source={source} hover />
|
|
42
|
+
* </HonuaMapProvider>
|
|
43
|
+
* );
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @experimental
|
|
48
|
+
*/
|
|
49
|
+
export function HonuaMapProvider({ map, children }) {
|
|
50
|
+
return _jsx(HonuaExternalMapContext.Provider, { value: map ?? null, children: children });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the MapLibre map a map-attached hook/component should target: the
|
|
54
|
+
* explicit `map` argument when given, otherwise the nearest enclosing
|
|
55
|
+
* {@link HonuaMapProvider} or `HonuaMap`. Returns `null` while no map is
|
|
56
|
+
* available (SSR, or before the map finished creating).
|
|
57
|
+
*
|
|
58
|
+
* @experimental
|
|
59
|
+
*/
|
|
60
|
+
export function useHonuaMap(map) {
|
|
61
|
+
const contextMap = useContext(HonuaExternalMapContext);
|
|
62
|
+
return map ?? contextMap;
|
|
63
|
+
}
|
package/react/honua-map.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"honua-map.d.ts","sourceRoot":"","sources":["../../../src/react/honua-map.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"honua-map.d.ts","sourceRoot":"","sources":["../../../src/react/honua-map.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOhH,oFAAoF;AACpF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,KAAK,OAAO,EAAE,kBAAkB,KAAK,WAAW,GAAG;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE,CAAC;IAC3E,KAAK,EAAE,KAAK,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;CAC3D;AAID,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,OAAO,EAAE,eAAe,CAAC;IACzB;;;;OAIG;IACH,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5D;;;;OAIG;IACH,WAAW,CAAC,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;IACpD,wCAAwC;IACxC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/C,uDAAuD;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAwGxD"}
|
package/react/honua-map.js
CHANGED
|
@@ -15,8 +15,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
*/
|
|
16
16
|
import { useEffect, useRef, useState } from "react";
|
|
17
17
|
import { loadMapPackage } from "../runtime/index.js";
|
|
18
|
-
import { useHonuaClient } from "./hooks.js";
|
|
19
18
|
import { HonuaMapContext } from "./context.js";
|
|
19
|
+
import { HonuaExternalMapContext } from "./external-map.js";
|
|
20
|
+
import { useHonuaClient } from "./hooks.js";
|
|
20
21
|
const EMPTY_STYLE = { version: 8, sources: {}, layers: [] };
|
|
21
22
|
/**
|
|
22
23
|
* Render a Honua-composed MapLibre map.
|
|
@@ -105,5 +106,5 @@ export function HonuaMap(props) {
|
|
|
105
106
|
runtime.updatePackage(mapPackage).catch((error) => onError?.(error));
|
|
106
107
|
// biome-ignore lint/correctness/useExhaustiveDependencies: onError is a callback prop; re-running on its identity is undesirable.
|
|
107
108
|
}, [contextValue.runtime, mapPackage]);
|
|
108
|
-
return (
|
|
109
|
+
return (_jsx(HonuaMapContext.Provider, { value: contextValue, children: _jsxs(HonuaExternalMapContext.Provider, { value: contextValue.map ?? null, children: [externalMap ? null : _jsx("div", { ref: containerRef, className: className, style: style, "data-honua-map": "" }), children] }) }));
|
|
109
110
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link HonuaSourceLayer} — the declarative face of the data-to-map bridge
|
|
3
|
+
* (REQ-002 of the react depth pass): mount a contract `Source` as a styled,
|
|
4
|
+
* interactive MapLibre layer set inside any enclosing map (`HonuaMap`, a
|
|
5
|
+
* {@link HonuaMapProvider}-published external map, or an explicit `map` prop).
|
|
6
|
+
*
|
|
7
|
+
* Prop changes diff in place (`query` → `setFilter`, `renderer.paint/layout` →
|
|
8
|
+
* property setters); unmounting disposes every bridge-owned MapLibre resource;
|
|
9
|
+
* React 18/19 StrictMode double-mounts neither leak nor double-add (see
|
|
10
|
+
* {@link useMountedSource}).
|
|
11
|
+
*
|
|
12
|
+
* SSR-safe: no `window` / `document` access at module scope.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import type { ReactNode } from "react";
|
|
17
|
+
import type { Query, Source } from "../contract/types.js";
|
|
18
|
+
import type { DataToMapLibreMap, MountSourceOptions, MountedSourceDiagnostics, MountSourcePopupOptions } from "../map/data-to-map-bridge.js";
|
|
19
|
+
import type { Renderer } from "../style/renderers.js";
|
|
20
|
+
/**
|
|
21
|
+
* Declarative styling for a {@link HonuaSourceLayer}: the bridge's styling
|
|
22
|
+
* surface (geometry restriction, per-geometry paint/layout overrides, or a
|
|
23
|
+
* verbatim custom layer set). `paint` / `layout` changes are applied in place;
|
|
24
|
+
* `geometry` / `layers` changes remount the layer set.
|
|
25
|
+
*
|
|
26
|
+
* The `renderer` prop also accepts a first-class renderer object from
|
|
27
|
+
* `@honua/sdk-js/style` (`classBreaksRenderer`, `uniqueValueRenderer`,
|
|
28
|
+
* `heatmapRenderer`, `clusterRenderer`); changes diff through the handle's
|
|
29
|
+
* `setRenderer` without teardown.
|
|
30
|
+
*
|
|
31
|
+
* @experimental
|
|
32
|
+
*/
|
|
33
|
+
export type HonuaSourceRenderer<T = Record<string, unknown>> = Pick<MountSourceOptions<T>, "geometry" | "layers" | "paint" | "layout">;
|
|
34
|
+
/** Props for {@link HonuaSourceLayer}. @experimental */
|
|
35
|
+
export interface HonuaSourceLayerProps<T = Record<string, unknown>> {
|
|
36
|
+
/** The contract `Source` to mount. `null` while it is still resolving. */
|
|
37
|
+
source: Source<T> | null | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Target map. Omit to resolve the nearest enclosing `HonuaMap` /
|
|
40
|
+
* {@link HonuaMapProvider} (external-map interop).
|
|
41
|
+
*/
|
|
42
|
+
map?: DataToMapLibreMap | null;
|
|
43
|
+
/** Filter applied to the mounted data; changes diff via `setFilter`. */
|
|
44
|
+
query?: Readonly<Omit<Query<T>, "signal">>;
|
|
45
|
+
/**
|
|
46
|
+
* Styling: either a first-class renderer object from `@honua/sdk-js/style`
|
|
47
|
+
* (diffed via `setRenderer`) or a {@link HonuaSourceRenderer} bag of
|
|
48
|
+
* geometry restriction + paint/layout overrides or custom layers.
|
|
49
|
+
*/
|
|
50
|
+
renderer?: HonuaSourceRenderer<T> | Renderer;
|
|
51
|
+
/** Open a popup on feature click (`factory` usually `() => new maplibregl.Popup()`). */
|
|
52
|
+
popup?: MountSourcePopupOptions;
|
|
53
|
+
/** Toggle hover feature-state on the mounted layers (bridge `hover` option). */
|
|
54
|
+
hover?: boolean | {
|
|
55
|
+
readonly stateKey?: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Share feature selection with the enclosing `HonuaSelectionProvider`:
|
|
59
|
+
* clicks toggle the shared selection and the shared selection is mirrored
|
|
60
|
+
* onto feature-state (default key `"selected"`). Also publishes hover to the
|
|
61
|
+
* provider when {@link hover} is enabled. No-op without a provider.
|
|
62
|
+
*/
|
|
63
|
+
selection?: boolean | {
|
|
64
|
+
readonly stateKey?: string;
|
|
65
|
+
readonly multiSelect?: boolean;
|
|
66
|
+
};
|
|
67
|
+
/** When `false`, nothing is mounted. @default true */
|
|
68
|
+
enabled?: boolean;
|
|
69
|
+
/** Called with fresh diagnostics after the mount and each applied update. */
|
|
70
|
+
onDiagnostics?: (diagnostics: MountedSourceDiagnostics) => void;
|
|
71
|
+
/** Called when mounting or an update fails. */
|
|
72
|
+
onError?: (error: unknown) => void;
|
|
73
|
+
/** Force a bridge strategy (`"geojson"` / `"query-tiles"`). */
|
|
74
|
+
strategy?: MountSourceOptions<T>["strategy"];
|
|
75
|
+
/** MapLibre source id override. @default `honua-<descriptor id>` */
|
|
76
|
+
sourceId?: string;
|
|
77
|
+
/** Base layer id override; geometry suffixes are appended. */
|
|
78
|
+
layerId?: string;
|
|
79
|
+
/** Existing layer id to insert the bridge layers before. */
|
|
80
|
+
beforeId?: string;
|
|
81
|
+
/** GeoJSON materialization bound. @default 10000 */
|
|
82
|
+
maxGeoJsonFeatures?: number;
|
|
83
|
+
/** Dynamic query-tile descriptor enabling the tile strategy. */
|
|
84
|
+
queryTiles?: MountSourceOptions<T>["queryTiles"];
|
|
85
|
+
/** Vector `source-layer` for the tile strategy. */
|
|
86
|
+
sourceLayer?: string;
|
|
87
|
+
/** Attribution override. */
|
|
88
|
+
attribution?: string;
|
|
89
|
+
/** Fit the map to the mounted data. */
|
|
90
|
+
fitBounds?: MountSourceOptions<T>["fitBounds"];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Mount a contract `Source` through the data-to-map bridge, declaratively.
|
|
94
|
+
* Renders nothing itself.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```tsx
|
|
98
|
+
* <HonuaSourceLayer
|
|
99
|
+
* source={source}
|
|
100
|
+
* query={{ where: "STATUS = 'OPEN'" }}
|
|
101
|
+
* renderer={{ paint: { point: { "circle-color": "#38bdf8" } } }}
|
|
102
|
+
* hover
|
|
103
|
+
* selection
|
|
104
|
+
* />
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @experimental
|
|
108
|
+
*/
|
|
109
|
+
export declare function HonuaSourceLayer<T = Record<string, unknown>>(props: HonuaSourceLayerProps<T>): ReactNode;
|
|
110
|
+
//# sourceMappingURL=honua-source-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"honua-source-layer.d.ts","sourceRoot":"","sources":["../../../src/react/honua-source-layer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,CACjE,kBAAkB,CAAC,CAAC,CAAC,EACrB,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAC3C,CAAC;AAYF,wDAAwD;AACxD,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC;;;OAGG;IACH,GAAG,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,wEAAwE;IACxE,KAAK,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC7C,wFAAwF;IACxF,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrF,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAChE,+CAA+C;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC7C,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,UAAU,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACjD,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,SAAS,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,SAAS,CA+DxG"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link HonuaSourceLayer} — the declarative face of the data-to-map bridge
|
|
3
|
+
* (REQ-002 of the react depth pass): mount a contract `Source` as a styled,
|
|
4
|
+
* interactive MapLibre layer set inside any enclosing map (`HonuaMap`, a
|
|
5
|
+
* {@link HonuaMapProvider}-published external map, or an explicit `map` prop).
|
|
6
|
+
*
|
|
7
|
+
* Prop changes diff in place (`query` → `setFilter`, `renderer.paint/layout` →
|
|
8
|
+
* property setters); unmounting disposes every bridge-owned MapLibre resource;
|
|
9
|
+
* React 18/19 StrictMode double-mounts neither leak nor double-add (see
|
|
10
|
+
* {@link useMountedSource}).
|
|
11
|
+
*
|
|
12
|
+
* SSR-safe: no `window` / `document` access at module scope.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import { useMemo } from "react";
|
|
17
|
+
import { useHonuaMap } from "./external-map.js";
|
|
18
|
+
import { useMapHoverBinding, useMapSelectionBinding } from "./selection.js";
|
|
19
|
+
import { useMountedSource } from "./use-mounted-source.js";
|
|
20
|
+
/** Recognize a first-class renderer object from `@honua/sdk-js/style`. */
|
|
21
|
+
function isRendererObject(value) {
|
|
22
|
+
return (typeof value === "object" &&
|
|
23
|
+
value !== null &&
|
|
24
|
+
typeof value.kind === "string" &&
|
|
25
|
+
typeof value.toMapLibre === "function");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mount a contract `Source` through the data-to-map bridge, declaratively.
|
|
29
|
+
* Renders nothing itself.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* <HonuaSourceLayer
|
|
34
|
+
* source={source}
|
|
35
|
+
* query={{ where: "STATUS = 'OPEN'" }}
|
|
36
|
+
* renderer={{ paint: { point: { "circle-color": "#38bdf8" } } }}
|
|
37
|
+
* hover
|
|
38
|
+
* selection
|
|
39
|
+
* />
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @experimental
|
|
43
|
+
*/
|
|
44
|
+
export function HonuaSourceLayer(props) {
|
|
45
|
+
const map = useHonuaMap(props.map);
|
|
46
|
+
// The renderer prop carries either a first-class renderer object (routed to
|
|
47
|
+
// the bridge's `renderer` option, diffed via setRenderer) or the
|
|
48
|
+
// geometry-default styling bag (diffed via property setters).
|
|
49
|
+
const rendererObject = isRendererObject(props.renderer) ? props.renderer : undefined;
|
|
50
|
+
const styleRenderer = rendererObject === undefined ? props.renderer : undefined;
|
|
51
|
+
const { handle, diagnostics } = useMountedSource(map, props.source, {
|
|
52
|
+
enabled: props.enabled,
|
|
53
|
+
query: props.query,
|
|
54
|
+
renderer: rendererObject,
|
|
55
|
+
geometry: styleRenderer?.geometry,
|
|
56
|
+
layers: styleRenderer?.layers,
|
|
57
|
+
paint: styleRenderer?.paint,
|
|
58
|
+
layout: styleRenderer?.layout,
|
|
59
|
+
popup: props.popup,
|
|
60
|
+
hover: props.hover,
|
|
61
|
+
onDiagnostics: props.onDiagnostics,
|
|
62
|
+
onError: props.onError,
|
|
63
|
+
strategy: props.strategy,
|
|
64
|
+
sourceId: props.sourceId,
|
|
65
|
+
layerId: props.layerId,
|
|
66
|
+
beforeId: props.beforeId,
|
|
67
|
+
maxGeoJsonFeatures: props.maxGeoJsonFeatures,
|
|
68
|
+
queryTiles: props.queryTiles,
|
|
69
|
+
sourceLayer: props.sourceLayer,
|
|
70
|
+
attribution: props.attribution,
|
|
71
|
+
fitBounds: props.fitBounds,
|
|
72
|
+
});
|
|
73
|
+
// Interactive layers exclude the polygon outline companion, mirroring the
|
|
74
|
+
// bridge's own popup/hover wiring. Re-read after every applied update
|
|
75
|
+
// (`diagnostics` changes) — a structural setRenderer swap replaces the
|
|
76
|
+
// owned layer ids on the same handle.
|
|
77
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: `diagnostics` signals layer-set changes; ids are read from the handle getter.
|
|
78
|
+
const interactiveLayerIds = useMemo(() => (handle ? handle.layerIds.filter((id) => !id.endsWith("-polygon-outline")) : []), [handle, diagnostics]);
|
|
79
|
+
const selection = props.selection;
|
|
80
|
+
const selectionEnabled = Boolean(selection) && handle !== null;
|
|
81
|
+
// Bind against the handle's *resolved* source-layer — the explicit prop or
|
|
82
|
+
// the default the bridge derived from the query-tile descriptor. MapLibre
|
|
83
|
+
// scopes vector-tile feature-state by source-layer, so the binding must
|
|
84
|
+
// target the exact value the mounted layers render with.
|
|
85
|
+
const resolvedSourceLayer = handle?.sourceLayer ?? props.sourceLayer;
|
|
86
|
+
useMapSelectionBinding(map, {
|
|
87
|
+
sourceId: handle?.sourceId ?? "",
|
|
88
|
+
layerIds: interactiveLayerIds,
|
|
89
|
+
sourceLayer: resolvedSourceLayer,
|
|
90
|
+
stateKey: typeof selection === "object" ? selection.stateKey : undefined,
|
|
91
|
+
multiSelect: typeof selection === "object" ? selection.multiSelect : undefined,
|
|
92
|
+
enabled: selectionEnabled,
|
|
93
|
+
});
|
|
94
|
+
useMapHoverBinding(map, {
|
|
95
|
+
sourceId: handle?.sourceId ?? "",
|
|
96
|
+
layerIds: interactiveLayerIds,
|
|
97
|
+
sourceLayer: resolvedSourceLayer,
|
|
98
|
+
enabled: selectionEnabled && Boolean(props.hover),
|
|
99
|
+
});
|
|
100
|
+
return null;
|
|
101
|
+
}
|
package/react/hooks.d.ts
CHANGED
|
@@ -56,6 +56,34 @@ export interface UseQueryOptions {
|
|
|
56
56
|
enabled?: boolean;
|
|
57
57
|
/** Use `source.queryAll()` (drain every page) instead of a single page. */
|
|
58
58
|
drainAllPages?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Stale-while-revalidate window in milliseconds. When a consumer (re)mounts
|
|
61
|
+
* or the query key changes and the cached result is at least this old, the
|
|
62
|
+
* cached data keeps rendering while a background refetch runs
|
|
63
|
+
* (`isFetching: true`, `data` preserved). `0` revalidates on every mount.
|
|
64
|
+
* Omitted keeps the historical behavior: cached results are served without
|
|
65
|
+
* revalidation until `refetch()` or an explicit invalidation.
|
|
66
|
+
*
|
|
67
|
+
* @experimental
|
|
68
|
+
*/
|
|
69
|
+
staleTimeMs?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Throw query errors during render so the nearest React error boundary
|
|
72
|
+
* receives them (typed errors such as `HonuaCapabilityNotSupportedError`
|
|
73
|
+
* arrive intact). Default `false`: errors are returned on the snapshot.
|
|
74
|
+
*
|
|
75
|
+
* @experimental
|
|
76
|
+
*/
|
|
77
|
+
throwOnError?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Suspense mode: while the first fetch (no cached data yet) is in flight the
|
|
80
|
+
* hook suspends, and errors are thrown to the nearest error boundary. Wrap
|
|
81
|
+
* consumers in `<Suspense fallback={…}>`. Background refetches do not
|
|
82
|
+
* suspend — cached data keeps rendering stale-while-revalidate style.
|
|
83
|
+
*
|
|
84
|
+
* @experimental
|
|
85
|
+
*/
|
|
86
|
+
suspense?: boolean;
|
|
59
87
|
}
|
|
60
88
|
/** Result of {@link useQuery}: a stable snapshot plus a `refetch` trigger. */
|
|
61
89
|
export interface UseQueryResult<T> extends QuerySnapshot<Result<T>> {
|
package/react/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAiC,MAAM,kBAAkB,CAAC;AAU3G;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,SAAS,CAAC;IACd,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAqB9D;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,OAAO,EACP,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,aAAa,EAAiC,MAAM,kBAAkB,CAAC;AAU3G;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,SAAS,CAAC;IACd,OAAO,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAqB9D;AAED,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjE,8DAA8D;IAC9D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClD,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,EACpC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAChB,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAAC,CAAC,CAAC,CAmEnB;AAED,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;CACrD;AAED,yCAAyC;AACzC,MAAM,WAAW,qBAAsB,SAAQ,aAAa,CAAC,wBAAwB,CAAC;IACpF,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,qBAAqB,CAmC3F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,eAAe,GAAG,IAAI,CAEtD;AAED,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG;IAAE,KAAK,IAAI,IAAI,CAAA;CAAE,GAAG;IAAE,MAAM,IAAI,IAAI,CAAA;CAAE,GAAG;IAAE,WAAW,IAAI,IAAI,CAAA;CAAE,CAAC;AAE9G;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/D,IAAI,GAAE,SAAS,OAAO,EAAO,GAC5B,IAAI,CASN"}
|
package/react/hooks.js
CHANGED
|
@@ -112,19 +112,41 @@ export function useQuery(source, query, options = {}) {
|
|
|
112
112
|
const subscribe = useCallback((onStoreChange) => (key ? cache.subscribe(key, onStoreChange) : () => { }), [cache, key]);
|
|
113
113
|
const getSnapshot = useCallback(() => (key ? cache.getSnapshot(key) : idleSnapshot()), [cache, key]);
|
|
114
114
|
const snapshot = useSyncExternalStore(subscribe, getSnapshot, () => idleSnapshot());
|
|
115
|
+
const staleTimeMs = options.staleTimeMs;
|
|
116
|
+
// `key` already encodes source id + query + mode, so the fetcher (like the
|
|
117
|
+
// effects below) is intentionally keyed on it rather than on the identity of
|
|
118
|
+
// the `source` / `query` objects — an inline literal cannot thrash the cache.
|
|
119
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: `key` already encodes source id + query + mode.
|
|
120
|
+
const fetcher = useCallback((signal) => drainAllPages
|
|
121
|
+
? source.queryAll({ ...query, signal })
|
|
122
|
+
: source.query({ ...query, signal }), [key]);
|
|
115
123
|
// biome-ignore lint/correctness/useExhaustiveDependencies: `key` already encodes source id + query + mode.
|
|
116
124
|
useEffect(() => {
|
|
117
125
|
if (!key || !source)
|
|
118
126
|
return;
|
|
119
|
-
cache.ensure(key,
|
|
120
|
-
}, [cache, key]);
|
|
127
|
+
cache.ensure(key, fetcher, staleTimeMs !== undefined ? { staleTimeMs } : {});
|
|
128
|
+
}, [cache, key, fetcher, staleTimeMs]);
|
|
121
129
|
// biome-ignore lint/correctness/useExhaustiveDependencies: `key` already encodes source id + query + mode.
|
|
122
130
|
const refetch = useCallback(() => {
|
|
123
131
|
if (!key || !source)
|
|
124
132
|
return;
|
|
125
|
-
cache.run(key,
|
|
126
|
-
}, [cache, key]);
|
|
133
|
+
cache.run(key, fetcher);
|
|
134
|
+
}, [cache, key, fetcher]);
|
|
127
135
|
useDebugValue(snapshot.status);
|
|
136
|
+
if (key && source && (options.suspense || options.throwOnError) && snapshot.status === "error") {
|
|
137
|
+
// Surface the typed error (e.g. HonuaCapabilityNotSupportedError) to the
|
|
138
|
+
// nearest error boundary. `refetch()` from the boundary retries.
|
|
139
|
+
throw snapshot.error;
|
|
140
|
+
}
|
|
141
|
+
if (options.suspense && key && source && snapshot.data === undefined) {
|
|
142
|
+
// First load with no cached data: kick the fetch during render (idempotent
|
|
143
|
+
// — `ensure` is a no-op once the entry left `idle`, so StrictMode's double
|
|
144
|
+
// render cannot double-fetch) and suspend on its promise.
|
|
145
|
+
cache.ensure(key, fetcher, staleTimeMs !== undefined ? { staleTimeMs } : {});
|
|
146
|
+
const pending = cache.getPromise(key);
|
|
147
|
+
if (pending)
|
|
148
|
+
throw pending;
|
|
149
|
+
}
|
|
128
150
|
return useMemo(() => ({ ...snapshot, refetch }), [snapshot, refetch]);
|
|
129
151
|
}
|
|
130
152
|
/**
|
package/react/index.d.ts
CHANGED
|
@@ -39,4 +39,12 @@ export { HonuaContext, HonuaMapContext } from "./context.js";
|
|
|
39
39
|
export type { HonuaContextValue, HonuaMapContextValue } from "./context.js";
|
|
40
40
|
export { HonuaQueryCache, stableQueryHash, idleSnapshot } from "./query-cache.js";
|
|
41
41
|
export type { QueryStatus, QuerySnapshot, QueryFetcher } from "./query-cache.js";
|
|
42
|
+
export { HonuaExternalMapContext, HonuaMapProvider, useHonuaMap } from "./external-map.js";
|
|
43
|
+
export type { HonuaMapProviderProps } from "./external-map.js";
|
|
44
|
+
export { useMountedSource } from "./use-mounted-source.js";
|
|
45
|
+
export type { UseMountedSourceOptions, UseMountedSourceResult } from "./use-mounted-source.js";
|
|
46
|
+
export { HonuaSourceLayer } from "./honua-source-layer.js";
|
|
47
|
+
export type { HonuaSourceLayerProps, HonuaSourceRenderer } from "./honua-source-layer.js";
|
|
48
|
+
export { HonuaSelectionContext, HonuaSelectionProvider, HonuaSelectionStore, useHover, useMapHoverBinding, useMapSelectionBinding, useSelection, } from "./selection.js";
|
|
49
|
+
export type { HonuaSelectionProviderProps, HonuaSelectionSnapshot, MapHoverBindingOptions, MapSelectionBindingOptions, UseHoverResult, UseSelectionResult, } from "./selection.js";
|
|
42
50
|
//# sourceMappingURL=index.d.ts.map
|
package/react/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIjF,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE1F,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,EACtB,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
|
package/react/index.js
CHANGED
|
@@ -32,3 +32,8 @@ export { HonuaLayer } from "./honua-layer.js";
|
|
|
32
32
|
export { HonuaPopup } from "./honua-popup.js";
|
|
33
33
|
export { HonuaContext, HonuaMapContext } from "./context.js";
|
|
34
34
|
export { HonuaQueryCache, stableQueryHash, idleSnapshot } from "./query-cache.js";
|
|
35
|
+
// ── React depth pass (issue #498) — all @experimental ─────────────
|
|
36
|
+
export { HonuaExternalMapContext, HonuaMapProvider, useHonuaMap } from "./external-map.js";
|
|
37
|
+
export { useMountedSource } from "./use-mounted-source.js";
|
|
38
|
+
export { HonuaSourceLayer } from "./honua-source-layer.js";
|
|
39
|
+
export { HonuaSelectionContext, HonuaSelectionProvider, HonuaSelectionStore, useHover, useMapHoverBinding, useMapSelectionBinding, useSelection, } from "./selection.js";
|
package/react/query-cache.d.ts
CHANGED
|
@@ -27,6 +27,13 @@ export interface QuerySnapshot<T> {
|
|
|
27
27
|
readonly isLoading: boolean;
|
|
28
28
|
/** True whenever a fetch is in flight, including background refetches. */
|
|
29
29
|
readonly isFetching: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Epoch milliseconds of the last successful fetch, `undefined` until one
|
|
32
|
+
* resolves. Drives stale-while-revalidate decisions.
|
|
33
|
+
*
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
36
|
+
readonly dataUpdatedAt?: number;
|
|
30
37
|
}
|
|
31
38
|
/**
|
|
32
39
|
* Returns the shared idle snapshot. Exposed so the SSR / disabled-query paths
|
|
@@ -50,11 +57,26 @@ export declare class HonuaQueryCache {
|
|
|
50
57
|
*/
|
|
51
58
|
subscribe(key: string, listener: () => void): () => void;
|
|
52
59
|
/**
|
|
53
|
-
* Kick off a fetch for `key`
|
|
54
|
-
*
|
|
55
|
-
*
|
|
60
|
+
* Kick off a fetch for `key` when it has never resolved and is not already
|
|
61
|
+
* in flight. This is the idempotent entry point hooks call from an effect;
|
|
62
|
+
* StrictMode's double-invoke therefore does not double-fetch.
|
|
63
|
+
*
|
|
64
|
+
* With `options.staleTimeMs`, a resolved entry whose data is at least that
|
|
65
|
+
* old is additionally revalidated in the background (stale-while-revalidate:
|
|
66
|
+
* the cached data stays served while `isFetching` is true). `0` revalidates
|
|
67
|
+
* on every ensure; omitted keeps the historical never-revalidate behavior.
|
|
68
|
+
*/
|
|
69
|
+
ensure<T>(key: string, fetcher: QueryFetcher<T>, options?: {
|
|
70
|
+
staleTimeMs?: number;
|
|
71
|
+
}): void;
|
|
72
|
+
/**
|
|
73
|
+
* The promise of the in-flight run for `key`, or `undefined` when no fetch
|
|
74
|
+
* is running. Suspense-mode hooks throw this promise while the first load is
|
|
75
|
+
* pending; it never rejects (errors land on the snapshot instead).
|
|
76
|
+
*
|
|
77
|
+
* @experimental
|
|
56
78
|
*/
|
|
57
|
-
|
|
79
|
+
getPromise(key: string): Promise<unknown> | undefined;
|
|
58
80
|
/**
|
|
59
81
|
* Force a (re)fetch for `key`, superseding any in-flight request. The last
|
|
60
82
|
* resolved `data` is preserved while the refetch runs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../../src/react/query-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gDAAgD;AAChD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../../src/react/query-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gDAAgD;AAChD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAoBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CAElD;AAED,qFAAqF;AACrF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAElE;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IAEzD,6EAA6E;IAC7E,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IAI7C;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAgCxD;;;;;;;;;OASG;IACH,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;IAgB9F;;;;;;OAMG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,SAAS;IAKrD;;;OAGG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IA8CnD,sEAAsE;IACtE,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAS7B,gEAAgE;IAChE,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,KAAK;CAMd;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEtD"}
|