@sqlrooms/deck 0.29.0-rc.10 → 0.29.0-rc.12
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/README.md +88 -16
- package/dist/BlockMapSettings.d.ts.map +1 -1
- package/dist/BlockMapSettings.js +4 -16
- package/dist/BlockMapSettings.js.map +1 -1
- package/dist/DashboardMapSettings.d.ts.map +1 -1
- package/dist/DashboardMapSettings.js +7 -10
- package/dist/DashboardMapSettings.js.map +1 -1
- package/dist/DeckJsonMap.d.ts.map +1 -1
- package/dist/DeckJsonMap.js +20 -18
- package/dist/DeckJsonMap.js.map +1 -1
- package/dist/DeckJsonMapSpec.d.ts +916 -53
- package/dist/DeckJsonMapSpec.d.ts.map +1 -1
- package/dist/DeckJsonMapSpec.js +9 -0
- package/dist/DeckJsonMapSpec.js.map +1 -1
- package/dist/DeckMapDefaultStylesProvider.d.ts +3 -4
- package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
- package/dist/DeckMapDefaultStylesProvider.js +13 -7
- package/dist/DeckMapDefaultStylesProvider.js.map +1 -1
- package/dist/DeckMapSurface.d.ts +1 -1
- package/dist/DeckMapSurface.js +1 -1
- package/dist/DeckMapSurface.js.map +1 -1
- package/dist/MapSettings.d.ts +14 -0
- package/dist/MapSettings.d.ts.map +1 -1
- package/dist/MapSettings.js +555 -186
- package/dist/MapSettings.js.map +1 -1
- package/dist/MapSettingsControls.d.ts +8 -1
- package/dist/MapSettingsControls.d.ts.map +1 -1
- package/dist/MapSettingsControls.js +24 -2
- package/dist/MapSettingsControls.js.map +1 -1
- package/dist/ai.d.ts +19 -5
- package/dist/ai.d.ts.map +1 -1
- package/dist/ai.js +63 -112
- package/dist/ai.js.map +1 -1
- package/dist/aiNormalize.d.ts +31 -0
- package/dist/aiNormalize.d.ts.map +1 -0
- package/dist/aiNormalize.js +630 -0
- package/dist/aiNormalize.js.map +1 -0
- package/dist/block.d.ts +1 -1
- package/dist/block.d.ts.map +1 -1
- package/dist/block.js +1 -1
- package/dist/block.js.map +1 -1
- package/dist/createOrUpdateDeckMapResource.d.ts +6 -2
- package/dist/createOrUpdateDeckMapResource.d.ts.map +1 -1
- package/dist/createOrUpdateDeckMapResource.js +57 -4
- package/dist/createOrUpdateDeckMapResource.js.map +1 -1
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +72 -8
- package/dist/dashboard.js.map +1 -1
- package/dist/dashboardConfig.d.ts +10 -1
- package/dist/dashboardConfig.d.ts.map +1 -1
- package/dist/dashboardConfig.js +55 -22
- package/dist/dashboardConfig.js.map +1 -1
- package/dist/datasets/PreparedDatasetStore.d.ts +3 -4
- package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -1
- package/dist/datasets/PreparedDatasetStore.js +35 -10
- package/dist/datasets/PreparedDatasetStore.js.map +1 -1
- package/dist/datasets/helpers.d.ts +39 -2
- package/dist/datasets/helpers.d.ts.map +1 -1
- package/dist/datasets/helpers.js +86 -3
- package/dist/datasets/helpers.js.map +1 -1
- package/dist/datasets/usePreparedDatasetStates.d.ts.map +1 -1
- package/dist/datasets/usePreparedDatasetStates.js +12 -8
- package/dist/datasets/usePreparedDatasetStates.js.map +1 -1
- package/dist/datasets/wrapGeometryAsWkb.d.ts +20 -0
- package/dist/datasets/wrapGeometryAsWkb.d.ts.map +1 -0
- package/dist/datasets/wrapGeometryAsWkb.js +65 -0
- package/dist/datasets/wrapGeometryAsWkb.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/json/colorScaleFunction.d.ts +12 -4
- package/dist/json/colorScaleFunction.d.ts.map +1 -1
- package/dist/json/colorScaleFunction.js.map +1 -1
- package/dist/json/compileColorScale.d.ts +3 -2
- package/dist/json/compileColorScale.d.ts.map +1 -1
- package/dist/json/compileColorScale.js +16 -1
- package/dist/json/compileColorScale.js.map +1 -1
- package/dist/json/compileGeoArrowAccessor.d.ts +5 -0
- package/dist/json/compileGeoArrowAccessor.d.ts.map +1 -1
- package/dist/json/compileGeoArrowAccessor.js +17 -3
- package/dist/json/compileGeoArrowAccessor.js.map +1 -1
- package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -1
- package/dist/json/createDeckJsonConfiguration.js +278 -151
- package/dist/json/createDeckJsonConfiguration.js.map +1 -1
- package/dist/json/defaultClasses.d.ts.map +1 -1
- package/dist/json/defaultClasses.js +3 -3
- package/dist/json/defaultClasses.js.map +1 -1
- package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
- package/dist/json/extractColorScaleLegends.js +43 -14
- package/dist/json/extractColorScaleLegends.js.map +1 -1
- package/dist/json/heatmapDefaults.d.ts +17 -7
- package/dist/json/heatmapDefaults.d.ts.map +1 -1
- package/dist/json/heatmapDefaults.js +54 -12
- package/dist/json/heatmapDefaults.js.map +1 -1
- package/dist/json/layers/DeckH3HexagonLayer.d.ts.map +1 -1
- package/dist/json/layers/DeckH3HexagonLayer.js +9 -14
- package/dist/json/layers/DeckH3HexagonLayer.js.map +1 -1
- package/dist/json/layers/DeckHeatmapLayer.d.ts +32 -0
- package/dist/json/layers/DeckHeatmapLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckHeatmapLayer.js +69 -0
- package/dist/json/layers/DeckHeatmapLayer.js.map +1 -0
- package/dist/json/layers/h3IndexFormat.d.ts +6 -0
- package/dist/json/layers/h3IndexFormat.d.ts.map +1 -0
- package/dist/json/layers/h3IndexFormat.js +17 -0
- package/dist/json/layers/h3IndexFormat.js.map +1 -0
- package/dist/json/layers/index.d.ts +2 -0
- package/dist/json/layers/index.d.ts.map +1 -1
- package/dist/json/layers/index.js +2 -0
- package/dist/json/layers/index.js.map +1 -1
- package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
- package/dist/json/rewriteGeoArrowAccessors.js +22 -5
- package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
- package/dist/json/scaleFunction.d.ts +27 -0
- package/dist/json/scaleFunction.d.ts.map +1 -0
- package/dist/json/scaleFunction.js +151 -0
- package/dist/json/scaleFunction.js.map +1 -0
- package/dist/mapAiConfig.d.ts +8 -0
- package/dist/mapAiConfig.d.ts.map +1 -1
- package/dist/mapAiConfig.js +9 -1
- package/dist/mapAiConfig.js.map +1 -1
- package/dist/mapAiSharedInstructions.d.ts +3 -0
- package/dist/mapAiSharedInstructions.d.ts.map +1 -0
- package/dist/mapAiSharedInstructions.js +16 -0
- package/dist/mapAiSharedInstructions.js.map +1 -0
- package/dist/mapConfig.d.ts +7 -1
- package/dist/mapConfig.d.ts.map +1 -1
- package/dist/mapConfig.js.map +1 -1
- package/dist/mapConfigUtils.d.ts +22 -0
- package/dist/mapConfigUtils.d.ts.map +1 -1
- package/dist/mapConfigUtils.js +147 -3
- package/dist/mapConfigUtils.js.map +1 -1
- package/dist/mapFit.d.ts +16 -0
- package/dist/mapFit.d.ts.map +1 -1
- package/dist/mapFit.js +208 -30
- package/dist/mapFit.js.map +1 -1
- package/dist/mapLayerConfigUtils.d.ts +64 -1
- package/dist/mapLayerConfigUtils.d.ts.map +1 -1
- package/dist/mapLayerConfigUtils.js +277 -16
- package/dist/mapLayerConfigUtils.js.map +1 -1
- package/dist/mapResourceAuthoring.d.ts +3 -1
- package/dist/mapResourceAuthoring.d.ts.map +1 -1
- package/dist/mapResourceAuthoring.js +413 -20
- package/dist/mapResourceAuthoring.js.map +1 -1
- package/dist/mosaic.d.ts +1 -1
- package/dist/mosaic.d.ts.map +1 -1
- package/dist/mosaic.js.map +1 -1
- package/dist/prepare/geoarrow.js.map +1 -1
- package/dist/prepare/prepareDeckDataset.d.ts.map +1 -1
- package/dist/prepare/prepareDeckDataset.js +1 -0
- package/dist/prepare/prepareDeckDataset.js.map +1 -1
- package/dist/prepare/types.d.ts +3 -0
- package/dist/prepare/types.d.ts.map +1 -1
- package/dist/prepare/types.js.map +1 -1
- package/dist/prepare/wkbDecoder.d.ts +10 -0
- package/dist/prepare/wkbDecoder.d.ts.map +1 -1
- package/dist/prepare/wkbDecoder.js +141 -20
- package/dist/prepare/wkbDecoder.js.map +1 -1
- package/dist/prepare/wkbParser.d.ts +9 -0
- package/dist/prepare/wkbParser.d.ts.map +1 -1
- package/dist/prepare/wkbParser.js +22 -0
- package/dist/prepare/wkbParser.js.map +1 -1
- package/dist/selectStarAsWkbCollision.d.ts +3 -0
- package/dist/selectStarAsWkbCollision.d.ts.map +1 -0
- package/dist/selectStarAsWkbCollision.js +78 -0
- package/dist/selectStarAsWkbCollision.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/useDeckMapFitToBounds.d.ts.map +1 -1
- package/dist/useDeckMapFitToBounds.js +1 -1
- package/dist/useDeckMapFitToBounds.js.map +1 -1
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ preparation.
|
|
|
4
4
|
|
|
5
5
|
## Map resources and dashboard adapters
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Document maps are first-class `deckMaps` resources. The root package export
|
|
8
8
|
contains the resource slice, renderer, settings, direct DuckDB data adapter,
|
|
9
9
|
and resource orchestration APIs. It does not require Mosaic.
|
|
10
10
|
|
|
@@ -14,14 +14,14 @@ selection, and issue translation inside that adapter boundary.
|
|
|
14
14
|
|
|
15
15
|
`DeckMapSettingsPanel` is the shared host-neutral editor for both surfaces. It
|
|
16
16
|
receives a map config, selected table, available tables, and edit callbacks;
|
|
17
|
-
|
|
17
|
+
document resources and Mosaic panels only adapt their respective stores to
|
|
18
18
|
that contract. Layer, binding, style, extrusion, and code-view controls therefore
|
|
19
|
-
stay consistent without putting Mosaic APIs in the
|
|
19
|
+
stay consistent without putting Mosaic APIs in the document settings path.
|
|
20
20
|
|
|
21
21
|
Use `getDeckMapDataPolicy(...)` to resolve a map config into the exported
|
|
22
22
|
`DeckMapDataPolicy` runtime row-limit policy.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Document map runtime issues distinguish dataset SQL failures (`sql-error`)
|
|
25
25
|
from fit-to-data bounds failures (`fit-error`), so each issue is cleared only
|
|
26
26
|
after its corresponding operation recovers.
|
|
27
27
|
|
|
@@ -29,7 +29,7 @@ after its corresponding operation recovers.
|
|
|
29
29
|
fit-to-data bounds queries. The direct adapter uses the authored source for
|
|
30
30
|
bounds while applying the configured row-limit policy only to rendered rows.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Document maps deliberately use independent selection semantics. Their direct
|
|
33
33
|
data adapter executes each configured SQL/table dataset through the room's
|
|
34
34
|
DuckDB connector and neither reads nor publishes Mosaic selections. This drops
|
|
35
35
|
the old incidental intra-map cross-filtering between datasets; a future
|
|
@@ -134,7 +134,8 @@ By default, the helper is conservative:
|
|
|
134
134
|
|
|
135
135
|
- point / multipoint -> `GeoArrowScatterplotLayer`
|
|
136
136
|
- linestring / multilinestring -> `GeoArrowPathLayer`
|
|
137
|
-
- polygon / multipolygon -> `GeoArrowPolygonLayer`
|
|
137
|
+
- native GeoArrow polygon / multipolygon -> `GeoArrowPolygonLayer`
|
|
138
|
+
- WKB/WKT multipolygon -> `GeoJsonLayer`
|
|
138
139
|
- mixed, unknown, or unsupported -> `GeoJsonLayer`
|
|
139
140
|
|
|
140
141
|
You can provide semantic hints for special layers:
|
|
@@ -267,11 +268,11 @@ Runtime issue recovery can call `deckMaps.clearMapIssue(mapId, kind)` to clear
|
|
|
267
268
|
only a matching issue kind; omit `kind` when the map state should clear any
|
|
268
269
|
stale issue. Replacing a map config clears its prior render issue, while data
|
|
269
270
|
issues remain until the corresponding dataset recovery is reported.
|
|
270
|
-
Direct
|
|
271
|
+
Direct document maps automatically fit the configured dataset when the map or
|
|
271
272
|
its source first becomes ready; the header action remains available for manual
|
|
272
273
|
refitting.
|
|
273
274
|
|
|
274
|
-
Hosts that expose direct
|
|
275
|
+
Hosts that expose direct document-map AI capability should include
|
|
275
276
|
`getDeckMapResourceAiInstructions()` in the responsible agent and tool
|
|
276
277
|
instructions. `createOrUpdateDeckMapResource(...)` validates the fully merged
|
|
277
278
|
resource before any durable block or map write: each dataset needs a
|
|
@@ -333,6 +334,11 @@ const result = await createOrUpdateDeckMapResource(
|
|
|
333
334
|
blockDocumentId,
|
|
334
335
|
mapId,
|
|
335
336
|
config,
|
|
337
|
+
pointBinding: {
|
|
338
|
+
dataset: 'places',
|
|
339
|
+
longitudeColumn: 'longitude',
|
|
340
|
+
latitudeColumn: 'latitude',
|
|
341
|
+
},
|
|
336
342
|
tableName,
|
|
337
343
|
title,
|
|
338
344
|
intent,
|
|
@@ -354,10 +360,22 @@ title and uses it as the default block caption. Block metadata is written only
|
|
|
354
360
|
after the map write succeeds.
|
|
355
361
|
|
|
356
362
|
Map authoring helpers such as `normalizeDeckMapPointConfig(...)`,
|
|
357
|
-
`
|
|
363
|
+
`applyDeckMapPointBinding(...)`, `normalizeDeckMapFillColor(...)`,
|
|
364
|
+
`regenerateMapConfigForTable(...)`, and
|
|
358
365
|
dataset-source helpers such as `getFirstDatasetSourceTableName(...)` are
|
|
359
366
|
exported so hosts can normalize AI-authored configs before calling
|
|
360
|
-
`createOrUpdateDeckMapResource(...)`. `
|
|
367
|
+
`createOrUpdateDeckMapResource(...)`. Passing structured `pointBinding` to the
|
|
368
|
+
resource helper applies `applyDeckMapPointBinding(...)`: it generates canonical
|
|
369
|
+
WKB point SQL through `createDeckMapPointTransformSql(...)` and aligns the target
|
|
370
|
+
dataset, point layers, brush interaction, and fit binding. The host table lookup
|
|
371
|
+
also supplies source columns so missing coordinate columns and a generated
|
|
372
|
+
geometry alias that would duplicate an existing column are rejected before
|
|
373
|
+
durable state is written. For a single table-backed dataset, its canonical table
|
|
374
|
+
identity must also match the selected table because that selection overrides the
|
|
375
|
+
authored dataset source at render time. This is the preferred path for standard
|
|
376
|
+
table-backed longitude/latitude maps; raw `transformSql` remains available for
|
|
377
|
+
custom spatial transforms.
|
|
378
|
+
`normalizeDeckMapPointConfig(...)` only adds
|
|
361
379
|
the standard lon/lat point transform to table-backed datasets that do not
|
|
362
380
|
already declare `geometryColumn`, `source.sqlQuery`, or `source.transformSql`
|
|
363
381
|
and whose resolved table does not expose a native geometry column; native
|
|
@@ -539,6 +557,21 @@ getFillColor: {
|
|
|
539
557
|
}
|
|
540
558
|
```
|
|
541
559
|
|
|
560
|
+
Optional `opacity` (0–1) is a SQLRooms `colorScale` extension. The compiler
|
|
561
|
+
multiplies it into the color's alpha so fill, stroke, and arc endpoints can be
|
|
562
|
+
dimmed independently of deck.gl `layer.opacity`:
|
|
563
|
+
|
|
564
|
+
```tsx
|
|
565
|
+
getFillColor: {
|
|
566
|
+
'@@function': 'colorScale',
|
|
567
|
+
field: 'Magnitude',
|
|
568
|
+
type: 'sequential',
|
|
569
|
+
scheme: 'YlOrRd',
|
|
570
|
+
domain: 'auto',
|
|
571
|
+
opacity: 0.6,
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
542
575
|
Discrete numeric palettes are supported too:
|
|
543
576
|
|
|
544
577
|
```tsx
|
|
@@ -596,6 +629,10 @@ scenes. It accepts resolved Arrow tables with geometry stored as:
|
|
|
596
629
|
- WKB / GeoArrow WKB
|
|
597
630
|
- WKT / GeoArrow WKT
|
|
598
631
|
|
|
632
|
+
The returned `PreparedDeckDataset` records the dataset-level
|
|
633
|
+
`datasetGeometryColumn` and `datasetGeometryEncodingHint` used to prepare
|
|
634
|
+
and identify that payload.
|
|
635
|
+
|
|
599
636
|
It then produces canonical deck-facing geometry outputs for:
|
|
600
637
|
|
|
601
638
|
- GeoArrow-native layers such as `GeoArrowScatterplotLayer`
|
|
@@ -623,7 +660,6 @@ The current curated layer set is:
|
|
|
623
660
|
- `GeoArrowColumnLayer`
|
|
624
661
|
- `GeoArrowPathLayer`
|
|
625
662
|
- `GeoArrowPolygonLayer`
|
|
626
|
-
- `GeoArrowSolidPolygonLayer`
|
|
627
663
|
- `GeoArrowArcLayer`
|
|
628
664
|
- `GeoArrowTripsLayer`
|
|
629
665
|
- `GeoArrowH3HexagonLayer`
|
|
@@ -632,15 +668,51 @@ The current curated layer set is:
|
|
|
632
668
|
GeoArrow-native geometry columns are the efficient path. WKB/WKT geometry falls
|
|
633
669
|
back to decoding and GeoJSON-binary preparation, with promotion available
|
|
634
670
|
for point-focused GeoArrow layers such as `GeoArrowScatterplotLayer`,
|
|
635
|
-
`GeoArrowHeatmapLayer`, and `GeoArrowColumnLayer`, plus
|
|
636
|
-
`GeoArrowPolygonLayer
|
|
671
|
+
`GeoArrowHeatmapLayer`, and `GeoArrowColumnLayer`, plus Polygon promotion for
|
|
672
|
+
`GeoArrowPolygonLayer`. WKB/WKT MultiPolygon
|
|
673
|
+
uses the GeoJSON-binary path so separate polygon parts retain their nesting.
|
|
637
674
|
|
|
638
675
|
The GeoArrow layer implementations themselves come from
|
|
639
676
|
[`@geoarrow/deck.gl-geoarrow`](https://github.com/geoarrow/deck.gl-geoarrow).
|
|
640
677
|
|
|
641
|
-
When querying DuckDB spatial `GEOMETRY` columns
|
|
642
|
-
with `
|
|
643
|
-
|
|
678
|
+
When querying DuckDB spatial `GEOMETRY` columns, the dataset pipeline probes
|
|
679
|
+
output types with `DESCRIBE` and projects native `GEOMETRY` columns through
|
|
680
|
+
`SELECT * REPLACE (ST_AsWKB(col) AS col)` before prepare/decode. Matching is
|
|
681
|
+
exact for `GEOMETRY` and CRS-parameterized forms such as
|
|
682
|
+
`GEOMETRY('EPSG:4326')` — not containers like `GEOMETRY[]`. Authored SQL is
|
|
683
|
+
not rewritten — the wrap is an outer pipeline query. Prefer writing
|
|
684
|
+
`ST_AsWKB(...)` in transforms when you control the SQL; the pipeline covers
|
|
685
|
+
bare `ST_Point(...)` / table `GEOMETRY` columns for every authoring surface.
|
|
686
|
+
|
|
687
|
+
## AI map config prepare
|
|
688
|
+
|
|
689
|
+
AI and host tooling should prepare authored Deck map configs through the shared
|
|
690
|
+
helpers exported from `@sqlrooms/deck`:
|
|
691
|
+
|
|
692
|
+
- `prepareAiDeckMapConfig(config, {resolveTable?, stripCatalogNames?})` — preferred entrypoint:
|
|
693
|
+
validates `colorScale.field` names against known tables when a resolver is
|
|
694
|
+
provided, then runs normalization. Hosts that attach a workspace DB under a
|
|
695
|
+
catalog that is **not** in scope for dataset SQL should pass that catalog via
|
|
696
|
+
`stripCatalogNames` (CLI passes `['sqlrooms-cli']`). Default is **no
|
|
697
|
+
stripping** so other apps keep their own catalogs / attached remotes intact.
|
|
698
|
+
Dashboard AI helpers (`createDashboardAgentToolWithDeckMaps`,
|
|
699
|
+
`createDashboardWithDeckMapAiTools`, `createDeckMapDashboardTool`) accept the
|
|
700
|
+
same option.
|
|
701
|
+
- `normalizeAiDeckMapConfig(config, {stripCatalogNames?})` — safe structural defaults only (scheme
|
|
702
|
+
casing, solo-dataset binding inject, size clamps, heatmap `colorRange` strip,
|
|
703
|
+
lon/lat → WKB transform inject). `SELECT *` / `ST_AsWKB` alias collisions are
|
|
704
|
+
rejected by validation for agent retry — SQL is not rewritten.
|
|
705
|
+
Does not invent schemes or silently mutate polygon geometry into centroids.
|
|
706
|
+
- `validateAndFixColorScaleFields(config, resolveTable)` — casing fix for
|
|
707
|
+
base-table columns; hard-rejects unknown fields on bare `{tableName}` sources.
|
|
708
|
+
Skips unknown-field rejection when `transformSql` / `sqlQuery` is present
|
|
709
|
+
(aliases may be transform-only).
|
|
710
|
+
|
|
711
|
+
Durable resource writes also run `getDeckMapResourceConfigIssues` /
|
|
712
|
+
`assertDeckMapResourceConfig` for syntax, supported layer types, and type/scheme
|
|
713
|
+
compatibility (e.g. `quantile` + `Viridis` is rejected; layer `@@type` must be
|
|
714
|
+
one of the settings picker classes). Native `GEOMETRY` columns are
|
|
715
|
+
normalized to WKB by the dataset pipeline (not by SQL-string validation).
|
|
644
716
|
|
|
645
717
|
## Runtime Props and Children
|
|
646
718
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockMapSettings.d.ts","sourceRoot":"","sources":["../src/BlockMapSettings.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,2BAA2B,EAEjC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"BlockMapSettings.d.ts","sourceRoot":"","sources":["../src/BlockMapSettings.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,2BAA2B,EAEjC,MAAM,qBAAqB,CAAC;AAM7B,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,WAAW,EACX,eAAe,EACf,OAAO,EACP,QAAQ,GACT,EAAE,2BAA2B,2CA2E7B"}
|
package/dist/BlockMapSettings.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { getTableIdentity } from '@sqlrooms/duckdb';
|
|
3
3
|
import { blockDocumentContentToBlocks, useStoreWithBlockDocuments, } from '@sqlrooms/documents';
|
|
4
|
-
import { Button } from '@sqlrooms/ui';
|
|
5
|
-
import { XIcon } from 'lucide-react';
|
|
6
4
|
import { useCallback, useMemo } from 'react';
|
|
7
5
|
import { useStoreWithDeckMaps } from './DeckMapsSlice';
|
|
8
6
|
import { DeckMapSettingsPanel } from './MapSettings';
|
|
9
|
-
import {
|
|
10
|
-
import { getDeckMapResourceConfigIssues } from './mapResourceAuthoring';
|
|
7
|
+
import { applyDeckMapTableSelection } from './mapConfigUtils';
|
|
11
8
|
export function DeckMapBlockSettings({ blockId, dashboardId, blockInstanceId, onClose, readOnly, }) {
|
|
12
9
|
const mapId = blockInstanceId ?? blockId;
|
|
13
10
|
const map = useStoreWithDeckMaps((state) => state.deckMaps.config.mapsById[mapId]);
|
|
@@ -22,7 +19,6 @@ export function DeckMapBlockSettings({ blockId, dashboardId, blockInstanceId, on
|
|
|
22
19
|
candidate.type === 'statefulBlock' &&
|
|
23
20
|
candidate.blockType === 'map')
|
|
24
21
|
: undefined, [artifact, blockId]);
|
|
25
|
-
const configIssues = useMemo(() => map ? getDeckMapResourceConfigIssues(map.config, { allowEmpty: true }) : [], [map]);
|
|
26
22
|
const handleTitleChange = useCallback((title) => {
|
|
27
23
|
if (readOnly)
|
|
28
24
|
return;
|
|
@@ -37,21 +33,13 @@ export function DeckMapBlockSettings({ blockId, dashboardId, blockInstanceId, on
|
|
|
37
33
|
const handleTableChange = useCallback((table) => {
|
|
38
34
|
if (readOnly || !map)
|
|
39
35
|
return;
|
|
40
|
-
const config = regenerateMapConfigForTable({ config: map.config }, table);
|
|
41
|
-
if (config === map.config)
|
|
42
|
-
return;
|
|
43
36
|
updateMap(mapId, {
|
|
44
37
|
selectedTable: getTableIdentity(table.table),
|
|
45
|
-
config: config,
|
|
38
|
+
config: applyDeckMapTableSelection(map.config, table),
|
|
46
39
|
});
|
|
47
40
|
}, [map, mapId, readOnly, updateMap]);
|
|
48
41
|
if (!map)
|
|
49
42
|
return (_jsx("div", { className: "text-muted-foreground p-4 text-sm", children: "Map settings not available" }));
|
|
50
|
-
|
|
51
|
-
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-3 py-1.5 text-xs font-medium", children: [_jsx("span", { children: "Map settings" }), onClose ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-5 w-5", onClick: onClose, "aria-label": "Close", children: _jsx(XIcon, { className: "h-3.5 w-3.5" }) })) : null] }), _jsx("div", { className: "text-muted-foreground flex flex-1 items-center justify-center p-4 text-center text-sm", children: configIssues.length > 0
|
|
52
|
-
? `Invalid map configuration: ${configIssues[0].path}: ${configIssues[0].message}`
|
|
53
|
-
: 'This custom map configuration cannot be safely edited with the basic settings controls.' })] }));
|
|
54
|
-
}
|
|
55
|
-
return (_jsx(DeckMapSettingsPanel, { title: block?.caption ?? map.title, selectedTable: map.selectedTable, config: map.config, tables: tables.filter((table) => table.columns.length > 0), onClose: onClose, onTitleChange: handleTitleChange, onTableChange: handleTableChange, onConfigChange: (config) => updateMap(mapId, { config }), readOnly: readOnly }));
|
|
43
|
+
return (_jsx(DeckMapSettingsPanel, { title: block?.caption ?? map.title, selectedTable: map.selectedTable, config: map.config, tables: tables.filter((table) => table.columns.length > 0), onClose: onClose, onTitleChange: handleTitleChange, onTableChange: handleTableChange, onConfigChange: (config) => updateMap(mapId, { config }), readOnly: readOnly, customConfig: map.config.configMode === 'custom', preferDatasetSource: true }));
|
|
56
44
|
}
|
|
57
45
|
//# sourceMappingURL=BlockMapSettings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockMapSettings.js","sourceRoot":"","sources":["../src/BlockMapSettings.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,gBAAgB,EAAiB,MAAM,kBAAkB,CAAC;AAClE,OAAO,EACL,4BAA4B,EAG5B,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAC,
|
|
1
|
+
{"version":3,"file":"BlockMapSettings.js","sourceRoot":"","sources":["../src/BlockMapSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {getTableIdentity, type DataTable} from '@sqlrooms/duckdb';\nimport {\n blockDocumentContentToBlocks,\n type BlockDocumentStatefulBlockBlock,\n type BlockSettingsComponentProps,\n useStoreWithBlockDocuments,\n} from '@sqlrooms/documents';\nimport {useCallback, useMemo} from 'react';\nimport {useStoreWithDeckMaps} from './DeckMapsSlice';\nimport {DeckMapSettingsPanel} from './MapSettings';\nimport {applyDeckMapTableSelection} from './mapConfigUtils';\n\nexport function DeckMapBlockSettings({\n blockId,\n dashboardId,\n blockInstanceId,\n onClose,\n readOnly,\n}: BlockSettingsComponentProps) {\n const mapId = blockInstanceId ?? blockId;\n const map = useStoreWithDeckMaps(\n (state) => state.deckMaps.config.mapsById[mapId],\n );\n const tables = useStoreWithDeckMaps((state) => state.db.tables);\n const updateMap = useStoreWithDeckMaps((state) => state.deckMaps.updateMap);\n const artifact = useStoreWithBlockDocuments((state) =>\n dashboardId\n ? state.blockDocuments.config.artifacts[dashboardId]\n : undefined,\n );\n const updateBlock = useStoreWithBlockDocuments(\n (state) => state.blockDocuments.updateBlock,\n );\n const block = useMemo(\n () =>\n artifact\n ? blockDocumentContentToBlocks(artifact.content).find(\n (candidate): candidate is BlockDocumentStatefulBlockBlock =>\n candidate.id === blockId &&\n candidate.type === 'statefulBlock' &&\n candidate.blockType === 'map',\n )\n : undefined,\n [artifact, blockId],\n );\n\n const handleTitleChange = useCallback(\n (title: string) => {\n if (readOnly) return;\n updateMap(mapId, {title});\n if (dashboardId && block) {\n updateBlock(dashboardId, blockId, {\n ...block,\n caption: title || undefined,\n });\n }\n },\n [block, blockId, dashboardId, mapId, readOnly, updateBlock, updateMap],\n );\n\n const handleTableChange = useCallback(\n (table: DataTable) => {\n if (readOnly || !map) return;\n updateMap(mapId, {\n selectedTable: getTableIdentity(table.table),\n config: applyDeckMapTableSelection(map.config, table),\n });\n },\n [map, mapId, readOnly, updateMap],\n );\n\n if (!map)\n return (\n <div className=\"text-muted-foreground p-4 text-sm\">\n Map settings not available\n </div>\n );\n\n return (\n <DeckMapSettingsPanel\n title={block?.caption ?? map.title}\n selectedTable={map.selectedTable}\n config={map.config}\n tables={tables.filter((table) => table.columns.length > 0)}\n onClose={onClose}\n onTitleChange={handleTitleChange}\n onTableChange={handleTableChange}\n onConfigChange={(config) => updateMap(mapId, {config})}\n readOnly={readOnly}\n customConfig={map.config.configMode === 'custom'}\n preferDatasetSource\n />\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardMapSettings.d.ts","sourceRoot":"","sources":["../src/DashboardMapSettings.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"DashboardMapSettings.d.ts","sourceRoot":"","sources":["../src/DashboardMapSettings.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,qBAAqB,CAAC;AAOrE,OAAO,EAAC,KAAK,EAAE,EAAc,MAAM,OAAO,CAAC;AAQ3C;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,EAAE,CAAC,2BAA2B,CA+FpE,CAAC"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { getTableIdentity } from '@sqlrooms/duckdb';
|
|
3
3
|
import { ConfirmDatasetChangeDialog, useConfirmDatasetChange, useStoreWithMosaicDashboard, useTablesWithColumns, } from '@sqlrooms/mosaic';
|
|
4
|
-
import { Button } from '@sqlrooms/ui';
|
|
5
|
-
import { XIcon } from 'lucide-react';
|
|
6
4
|
import { useCallback } from 'react';
|
|
7
5
|
import { DeckMapSettingsPanel } from './MapSettings';
|
|
8
6
|
import { DECK_MAP_DASHBOARD_PANEL_TYPE, } from './dashboardConfig';
|
|
@@ -36,17 +34,16 @@ export const DeckMapDashboardSettings = ({ blockId, dashboardId, onClose, readOn
|
|
|
36
34
|
});
|
|
37
35
|
}, [blockId, dashboardId, readOnly, updatePanel]);
|
|
38
36
|
const { handleChangeRequest, handleConfirm, handleCancel, isDialogOpen } = useConfirmDatasetChange(handleTableChange);
|
|
37
|
+
const panel = dashboard?.panels.find((candidate) => candidate.id === blockId);
|
|
38
|
+
const mapConfig = panel?.type === DECK_MAP_DASHBOARD_PANEL_TYPE
|
|
39
|
+
? panel.config
|
|
40
|
+
: undefined;
|
|
39
41
|
if (!dashboard) {
|
|
40
42
|
return (_jsx("div", { className: "flex h-full items-center justify-center p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Dashboard not found" }) }));
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
if (!panel || panel.type !== DECK_MAP_DASHBOARD_PANEL_TYPE) {
|
|
44
|
+
if (!panel || !mapConfig) {
|
|
44
45
|
return (_jsx("div", { className: "flex h-full items-center justify-center p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Map panel not found" }) }));
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
if (mapConfig.configMode === 'custom') {
|
|
48
|
-
return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-3 py-1.5 text-xs font-medium", children: [_jsx("span", { children: "Map settings" }), onClose ? (_jsx(Button, { variant: "ghost", size: "icon", className: "h-5 w-5", onClick: onClose, "aria-label": "Close", children: _jsx(XIcon, { className: "h-3.5 w-3.5" }) })) : null] }), _jsx("div", { className: "text-muted-foreground flex flex-1 items-center justify-center p-4 text-center text-sm", children: "This custom map configuration cannot be safely edited with the basic settings controls." })] }));
|
|
49
|
-
}
|
|
50
|
-
return (_jsxs(_Fragment, { children: [_jsx(DeckMapSettingsPanel, { title: panel.title, selectedTable: dashboard.selectedTable, config: mapConfig, tables: tables, onClose: onClose, onTableChange: handleChangeRequest, onTitleChange: handleTitleChange, onConfigChange: handleConfigChange, readOnly: readOnly }), _jsx(ConfirmDatasetChangeDialog, { open: isDialogOpen, onConfirm: handleConfirm, onCancel: handleCancel })] }));
|
|
47
|
+
return (_jsxs(_Fragment, { children: [_jsx(DeckMapSettingsPanel, { title: panel.title, selectedTable: dashboard.selectedTable, config: mapConfig, tables: tables, onClose: onClose, onTableChange: handleChangeRequest, onTitleChange: handleTitleChange, onConfigChange: handleConfigChange, readOnly: readOnly, customConfig: mapConfig.configMode === 'custom' }), _jsx(ConfirmDatasetChangeDialog, { open: isDialogOpen, onConfirm: handleConfirm, onCancel: handleCancel })] }));
|
|
51
48
|
};
|
|
52
49
|
//# sourceMappingURL=DashboardMapSettings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardMapSettings.js","sourceRoot":"","sources":["../src/DashboardMapSettings.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,gBAAgB,EAAiB,MAAM,kBAAkB,CAAC;AAElE,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"DashboardMapSettings.js","sourceRoot":"","sources":["../src/DashboardMapSettings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {getTableIdentity, type DataTable} from '@sqlrooms/duckdb';\nimport type {BlockSettingsComponentProps} from '@sqlrooms/documents';\nimport {\n ConfirmDatasetChangeDialog,\n useConfirmDatasetChange,\n useStoreWithMosaicDashboard,\n useTablesWithColumns,\n} from '@sqlrooms/mosaic';\nimport {type FC, useCallback} from 'react';\nimport {DeckMapSettingsPanel} from './MapSettings';\nimport {\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n type DeckMapDashboardPanelConfig,\n} from './dashboardConfig';\nimport type {DeckMapConfig} from './mapConfig';\n\n/**\n * Settings adapter for a Deck map panel inside a Mosaic dashboard.\n */\nexport const DeckMapDashboardSettings: FC<BlockSettingsComponentProps> = ({\n blockId,\n dashboardId,\n onClose,\n readOnly,\n}) => {\n const dashboard = useStoreWithMosaicDashboard((state) =>\n dashboardId ? state.mosaicDashboard.getDashboard(dashboardId) : undefined,\n );\n const updatePanel = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.updatePanel,\n );\n const setSelectedTable = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.setSelectedTable,\n );\n const tables = useTablesWithColumns();\n\n const handleTableChange = useCallback(\n (table: DataTable) => {\n if (readOnly) return;\n\n if (dashboardId) {\n setSelectedTable(dashboardId, getTableIdentity(table.table));\n }\n },\n [dashboardId, readOnly, setSelectedTable],\n );\n\n const handleTitleChange = useCallback(\n (title: string) => {\n if (readOnly) return;\n\n if (dashboardId) {\n updatePanel(dashboardId, blockId, {title: title || undefined});\n }\n },\n [dashboardId, blockId, readOnly, updatePanel],\n );\n\n const handleConfigChange = useCallback(\n (config: DeckMapConfig) => {\n if (readOnly || !dashboardId) return;\n updatePanel(dashboardId, blockId, {\n config: config as unknown as Record<string, unknown>,\n });\n },\n [blockId, dashboardId, readOnly, updatePanel],\n );\n\n const {handleChangeRequest, handleConfirm, handleCancel, isDialogOpen} =\n useConfirmDatasetChange(handleTableChange);\n\n const panel = dashboard?.panels.find((candidate) => candidate.id === blockId);\n const mapConfig =\n panel?.type === DECK_MAP_DASHBOARD_PANEL_TYPE\n ? (panel.config as DeckMapDashboardPanelConfig)\n : undefined;\n\n if (!dashboard) {\n return (\n <div className=\"flex h-full items-center justify-center p-4\">\n <p className=\"text-muted-foreground text-sm\">Dashboard not found</p>\n </div>\n );\n }\n\n if (!panel || !mapConfig) {\n return (\n <div className=\"flex h-full items-center justify-center p-4\">\n <p className=\"text-muted-foreground text-sm\">Map panel not found</p>\n </div>\n );\n }\n\n return (\n <>\n <DeckMapSettingsPanel\n title={panel.title}\n selectedTable={dashboard.selectedTable}\n config={mapConfig}\n tables={tables}\n onClose={onClose}\n onTableChange={handleChangeRequest}\n onTitleChange={handleTitleChange}\n onConfigChange={handleConfigChange}\n readOnly={readOnly}\n customConfig={mapConfig.configMode === 'custom'}\n />\n <ConfirmDatasetChangeDialog\n open={isDialogOpen}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n </>\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeckJsonMap.d.ts","sourceRoot":"","sources":["../src/DeckJsonMap.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DeckJsonMap.d.ts","sourceRoot":"","sources":["../src/DeckJsonMap.tsx"],"names":[],"mappings":"AAYA,OAAO,kCAAkC,CAAC;AAyB1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAEjB,MAAM,SAAS,CAAC;AA+QjB,eAAO,MAAM,WAAW,gHAuVvB,CAAC"}
|
package/dist/DeckJsonMap.js
CHANGED
|
@@ -2,7 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { JSONConverter } from '@deck.gl/json';
|
|
3
3
|
import { MapboxOverlay } from '@deck.gl/mapbox';
|
|
4
4
|
import { ColorScaleLegend } from '@sqlrooms/color-scales';
|
|
5
|
-
import { cn, useTheme } from '@sqlrooms/ui';
|
|
5
|
+
import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger, useTheme, } from '@sqlrooms/ui';
|
|
6
|
+
import { ChevronRightIcon } from 'lucide-react';
|
|
6
7
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
7
8
|
import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
|
|
8
9
|
import { forwardRef } from 'react';
|
|
@@ -15,6 +16,7 @@ import { createDeckJsonConfiguration } from './json/createDeckJsonConfiguration'
|
|
|
15
16
|
import { extractColorScaleLegends } from './json/extractColorScaleLegends';
|
|
16
17
|
import { getLayerCompatibility } from './json/layerCompatibility';
|
|
17
18
|
import { resolveDatasetId } from './json/layerConfig';
|
|
19
|
+
import { buildDeckMapJumpToOptions } from './mapFit';
|
|
18
20
|
const DEFAULT_MAP_STYLES = {
|
|
19
21
|
light: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
|
|
20
22
|
dark: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
|
|
@@ -102,6 +104,14 @@ const TripsTimeControl = ({ currentTime, maxTime, playing, onPlayPause, onSeek }
|
|
|
102
104
|
}
|
|
103
105
|
return (_jsxs("div", { className: "bg-background/90 border-border/70 pointer-events-auto relative flex items-center gap-1.5 rounded-md border px-2 py-1.5 pr-7 shadow-sm backdrop-blur-sm", children: [_jsx("button", { type: "button", onClick: onPlayPause, className: "text-foreground hover:bg-accent flex h-5 w-5 shrink-0 items-center justify-center rounded", title: playing ? 'Pause' : 'Play', children: playing ? (_jsxs("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", children: [_jsx("rect", { x: "1", y: "1", width: "3", height: "8" }), _jsx("rect", { x: "6", y: "1", width: "3", height: "8" })] })) : (_jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", children: _jsx("polygon", { points: "2,1 9,5 2,9" }) })) }), _jsx("input", { type: "range", min: 0, max: 1000, value: Math.round(progress * 1000), onChange: (e) => onSeek((Number(e.target.value) / 1000) * maxTime), className: "h-1 w-24 flex-1 cursor-pointer" }), _jsx("button", { type: "button", onClick: () => setCollapsed(true), className: "text-muted-foreground hover:text-foreground absolute top-1.5 right-1.5 flex h-4 w-4 items-center justify-center rounded-sm transition-colors", title: "Collapse", children: _jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", children: _jsx("path", { d: "M1 1L7 7M7 1L1 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })] }));
|
|
104
106
|
};
|
|
107
|
+
function getDeckLayerTypeName(layer) {
|
|
108
|
+
if (!layer || typeof layer !== 'object')
|
|
109
|
+
return '?';
|
|
110
|
+
const ctor = layer.constructor;
|
|
111
|
+
// Prefer static layerName: table-to-RecordBatch adapters all share
|
|
112
|
+
// constructor.name "Adapter", which would miss heatmap ↔ scatterplot swaps.
|
|
113
|
+
return ctor?.layerName ?? ctor?.name ?? '?';
|
|
114
|
+
}
|
|
105
115
|
// Workaround for deck.gl HeatmapLayer not releasing its WebGL framebuffer
|
|
106
116
|
// when replaced by another layer type (e.g. switching heatmap → scatterplot).
|
|
107
117
|
// We detect layer class changes and clear layers for one animation frame,
|
|
@@ -113,14 +123,7 @@ function DeckOverlayControl({ interleaved, ...deckProps }) {
|
|
|
113
123
|
const [clearing, setClearing] = useState(false);
|
|
114
124
|
const layers = deckProps.layers;
|
|
115
125
|
const layerKey = Array.isArray(layers)
|
|
116
|
-
? layers
|
|
117
|
-
.map((l) => {
|
|
118
|
-
if (!l || typeof l !== 'object')
|
|
119
|
-
return '?';
|
|
120
|
-
const ctor = l.constructor;
|
|
121
|
-
return ctor?.name ?? '?';
|
|
122
|
-
})
|
|
123
|
-
.join(',')
|
|
126
|
+
? layers.map(getDeckLayerTypeName).join(',')
|
|
124
127
|
: '';
|
|
125
128
|
useEffect(() => {
|
|
126
129
|
if (prevLayerKeyRef.current &&
|
|
@@ -141,9 +144,13 @@ function DeckOverlayControl({ interleaved, ...deckProps }) {
|
|
|
141
144
|
}
|
|
142
145
|
return null;
|
|
143
146
|
}
|
|
147
|
+
function DeckMapRenderingErrorOverlay({ error }) {
|
|
148
|
+
return (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center p-4", children: _jsx("div", { className: "max-w-sm rounded-md border border-red-200 bg-red-50/95 p-4 text-sm text-red-700 shadow-sm", children: _jsxs(Collapsible, { children: [_jsxs("div", { className: "flex items-start gap-1", children: [_jsx("span", { children: "Map couldn't be rendered" }), _jsx(CollapsibleTrigger, { className: "group mt-0.5 shrink-0 rounded p-0.5 hover:bg-red-100", "aria-label": "Show error details", children: _jsx(ChevronRightIcon, { className: "h-3.5 w-3.5 transition-transform group-data-[state=open]:rotate-90" }) })] }), _jsx(CollapsibleContent, { children: _jsx("pre", { className: "mt-2 max-h-40 overflow-auto font-mono text-xs whitespace-pre-wrap", children: error.message }) })] }) }) }));
|
|
149
|
+
}
|
|
144
150
|
export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, mapStyle, interleaved = true, deckProps, mapProps, showLegends = true, className, children, onDatasetStatesChange, onRenderingError, }, ref) {
|
|
145
151
|
const normalizedDatasets = useMemo(() => normalizeDatasets(datasets), [datasets]);
|
|
146
|
-
const
|
|
152
|
+
const datasetIdKey = JSON.stringify(Object.keys(normalizedDatasets).sort());
|
|
153
|
+
const datasetIds = useMemo(() => JSON.parse(datasetIdKey), [datasetIdKey]);
|
|
147
154
|
const datasetStates = usePreparedDatasetStates(normalizedDatasets);
|
|
148
155
|
const onDatasetStatesChangeRef = useRef(onDatasetStatesChange);
|
|
149
156
|
const { spec: parsedSpec, error: specError } = useMemo(() => parseSpec(spec), [spec]);
|
|
@@ -322,12 +329,7 @@ export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, map
|
|
|
322
329
|
const pendingJumpRef = useRef(null);
|
|
323
330
|
useImperativeHandle(ref, () => ({
|
|
324
331
|
jumpTo(opts) {
|
|
325
|
-
const jumpOpts =
|
|
326
|
-
center: [opts.longitude, opts.latitude],
|
|
327
|
-
zoom: opts.zoom,
|
|
328
|
-
bearing: opts.bearing ?? 0,
|
|
329
|
-
pitch: opts.pitch ?? 0,
|
|
330
|
-
};
|
|
332
|
+
const jumpOpts = buildDeckMapJumpToOptions(opts);
|
|
331
333
|
if (mapRef.current) {
|
|
332
334
|
mapRef.current.jumpTo(jumpOpts);
|
|
333
335
|
}
|
|
@@ -362,8 +364,8 @@ export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, map
|
|
|
362
364
|
datasetIds,
|
|
363
365
|
datasetStates,
|
|
364
366
|
})
|
|
365
|
-
: [], [availableSpec, datasetIds,
|
|
366
|
-
return (_jsxs("div", { className: cn('relative h-full w-full', className), children: [
|
|
367
|
+
: [], [availableSpec, datasetIds, showLegends, datasetStates]);
|
|
368
|
+
return (_jsxs("div", { className: cn('relative h-full w-full', className), children: [finalDeckPropsResult.error ? (_jsx(DeckMapRenderingErrorOverlay, { error: finalDeckPropsResult.error })) : null, _jsxs(Map, { ref: mapRef, ...mergedMapProps, ...(initialViewState
|
|
367
369
|
? { initialViewState: initialViewState }
|
|
368
370
|
: {}), onLoad: handleMapLoad, style: { width: '100%', height: '100%', ...mapProps?.style }, children: [_jsx(DeckOverlayControl, { interleaved: interleaved, ...overlayDeckProps }), children] }), renderDatasetErrorOverlay(datasetStates), !hasRenderingError && showLegends ? (_jsxs("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10 max-w-56", children: [hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "mb-1", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null, _jsx(ColorScaleLegend, { legends: legends })] })) : hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null] }));
|
|
369
371
|
});
|