@sqlrooms/deck 0.29.0-rc.11 → 0.29.0-rc.13
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 +193 -35
- 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 +75 -23
- package/dist/DeckJsonMap.js.map +1 -1
- package/dist/DeckJsonMapSpec.d.ts +41 -0
- package/dist/DeckJsonMapSpec.d.ts.map +1 -1
- package/dist/DeckJsonMapSpec.js +2 -0
- package/dist/DeckJsonMapSpec.js.map +1 -1
- package/dist/DeckMapBasemapSelect.d.ts +9 -0
- package/dist/DeckMapBasemapSelect.d.ts.map +1 -0
- package/dist/DeckMapBasemapSelect.js +20 -0
- package/dist/DeckMapBasemapSelect.js.map +1 -0
- package/dist/DeckMapDefaultStylesProvider.d.ts +13 -19
- package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
- package/dist/DeckMapDefaultStylesProvider.js +11 -18
- 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/DeckMapsSlice.d.ts +5 -0
- package/dist/DeckMapsSlice.d.ts.map +1 -1
- package/dist/DeckMapsSlice.js +6 -3
- package/dist/DeckMapsSlice.js.map +1 -1
- package/dist/MapSettings.d.ts +14 -0
- package/dist/MapSettings.d.ts.map +1 -1
- package/dist/MapSettings.js +548 -192
- 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.map +1 -1
- package/dist/ai.js +20 -12
- package/dist/ai.js.map +1 -1
- package/dist/aiNormalize.d.ts.map +1 -1
- package/dist/aiNormalize.js +2 -1
- package/dist/aiNormalize.js.map +1 -1
- package/dist/basemap.d.ts +23 -0
- package/dist/basemap.d.ts.map +1 -0
- package/dist/basemap.js +23 -0
- package/dist/basemap.js.map +1 -0
- package/dist/block.d.ts +1 -1
- package/dist/block.d.ts.map +1 -1
- package/dist/block.js +13 -9
- 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/datasets/PreparedDatasetStore.d.ts +3 -4
- package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -1
- package/dist/datasets/PreparedDatasetStore.js +4 -8
- 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/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- 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/createDeckJsonConfiguration.d.ts.map +1 -1
- package/dist/json/createDeckJsonConfiguration.js +235 -175
- 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 +41 -26
- 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/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/index.d.ts +1 -0
- package/dist/json/layers/index.d.ts.map +1 -1
- package/dist/json/layers/index.js +1 -0
- package/dist/json/layers/index.js.map +1 -1
- package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
- package/dist/json/rewriteGeoArrowAccessors.js +13 -5
- package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
- package/dist/json/scaleFunction.d.ts +5 -8
- package/dist/json/scaleFunction.d.ts.map +1 -1
- package/dist/json/scaleFunction.js +30 -5
- package/dist/json/scaleFunction.js.map +1 -1
- package/dist/mapAiConfig.d.ts +6 -0
- package/dist/mapAiConfig.d.ts.map +1 -1
- package/dist/mapAiConfig.js +7 -0
- package/dist/mapAiConfig.js.map +1 -1
- package/dist/mapAiSharedInstructions.d.ts +1 -1
- package/dist/mapAiSharedInstructions.d.ts.map +1 -1
- package/dist/mapAiSharedInstructions.js +4 -3
- package/dist/mapAiSharedInstructions.js.map +1 -1
- package/dist/mapConfig.d.ts +6 -1
- package/dist/mapConfig.d.ts.map +1 -1
- package/dist/mapConfig.js +28 -3
- 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 +152 -5
- package/dist/mapConfigUtils.js.map +1 -1
- package/dist/mapLayerConfigUtils.d.ts +55 -0
- package/dist/mapLayerConfigUtils.d.ts.map +1 -1
- package/dist/mapLayerConfigUtils.js +222 -11
- package/dist/mapLayerConfigUtils.js.map +1 -1
- package/dist/mapResourceAuthoring.d.ts +1 -1
- package/dist/mapResourceAuthoring.d.ts.map +1 -1
- package/dist/mapResourceAuthoring.js +14 -7
- package/dist/mapResourceAuthoring.js.map +1 -1
- package/dist/mapStyles.d.ts +16 -0
- package/dist/mapStyles.d.ts.map +1 -0
- package/dist/mapStyles.js +32 -0
- package/dist/mapStyles.js.map +1 -0
- 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.map +1 -1
- package/dist/prepare/wkbDecoder.js +62 -16
- package/dist/prepare/wkbDecoder.js.map +1 -1
- package/dist/prepare/wkbParser.d.ts +2 -0
- package/dist/prepare/wkbParser.d.ts.map +1 -1
- package/dist/prepare/wkbParser.js +1 -0
- package/dist/prepare/wkbParser.js.map +1 -1
- package/dist/protomapsStyles.d.ts +18 -0
- package/dist/protomapsStyles.d.ts.map +1 -0
- package/dist/protomapsStyles.js +38 -0
- package/dist/protomapsStyles.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +11 -9
package/README.md
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
# @sqlrooms/deck
|
|
2
|
+
|
|
1
3
|
Deck.gl integration for SQLRooms with JSON-driven map specs, dataset registry
|
|
2
4
|
binding, DuckDB-backed or in-memory Arrow datasets, and GeoArrow-first geometry
|
|
3
5
|
preparation.
|
|
4
6
|
|
|
7
|
+
## Package entry points
|
|
8
|
+
|
|
9
|
+
| Import | Use |
|
|
10
|
+
| ----------------------- | ----------------------------------------------------------------------------------------- |
|
|
11
|
+
| `@sqlrooms/deck` | Host-neutral maps, durable map resources, block-document integration, and authoring tools |
|
|
12
|
+
| `@sqlrooms/deck/mosaic` | Opt-in Mosaic dashboard renderers, configuration helpers, and AI tools |
|
|
13
|
+
|
|
14
|
+
The [Deck.gl example](https://github.com/sqlrooms/examples/tree/main/deckgl)
|
|
15
|
+
shows direct DuckDB-backed maps. The
|
|
16
|
+
[Deck.gl + Mosaic example](https://github.com/sqlrooms/examples/tree/main/deckgl-mosaic)
|
|
17
|
+
shows custom cross-filter integration.
|
|
18
|
+
|
|
5
19
|
## Map resources and dashboard adapters
|
|
6
20
|
|
|
7
|
-
|
|
21
|
+
Document maps are first-class `deckMaps` resources. The root package export
|
|
8
22
|
contains the resource slice, renderer, settings, direct DuckDB data adapter,
|
|
9
23
|
and resource orchestration APIs. It does not require Mosaic.
|
|
10
24
|
|
|
@@ -14,14 +28,14 @@ selection, and issue translation inside that adapter boundary.
|
|
|
14
28
|
|
|
15
29
|
`DeckMapSettingsPanel` is the shared host-neutral editor for both surfaces. It
|
|
16
30
|
receives a map config, selected table, available tables, and edit callbacks;
|
|
17
|
-
|
|
31
|
+
document resources and Mosaic panels only adapt their respective stores to
|
|
18
32
|
that contract. Layer, binding, style, extrusion, and code-view controls therefore
|
|
19
|
-
stay consistent without putting Mosaic APIs in the
|
|
33
|
+
stay consistent without putting Mosaic APIs in the document settings path.
|
|
20
34
|
|
|
21
35
|
Use `getDeckMapDataPolicy(...)` to resolve a map config into the exported
|
|
22
36
|
`DeckMapDataPolicy` runtime row-limit policy.
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
Document map runtime issues distinguish dataset SQL failures (`sql-error`)
|
|
25
39
|
from fit-to-data bounds failures (`fit-error`), so each issue is cleared only
|
|
26
40
|
after its corresponding operation recovers.
|
|
27
41
|
|
|
@@ -29,7 +43,7 @@ after its corresponding operation recovers.
|
|
|
29
43
|
fit-to-data bounds queries. The direct adapter uses the authored source for
|
|
30
44
|
bounds while applying the configured row-limit policy only to rendered rows.
|
|
31
45
|
|
|
32
|
-
|
|
46
|
+
Document maps deliberately use independent selection semantics. Their direct
|
|
33
47
|
data adapter executes each configured SQL/table dataset through the room's
|
|
34
48
|
DuckDB connector and neither reads nor publishes Mosaic selections. This drops
|
|
35
49
|
the old incidental intra-map cross-filtering between datasets; a future
|
|
@@ -39,9 +53,13 @@ resource ownership.
|
|
|
39
53
|
## Installation
|
|
40
54
|
|
|
41
55
|
```bash
|
|
42
|
-
npm install @sqlrooms/deck @sqlrooms/
|
|
56
|
+
npm install @sqlrooms/deck @sqlrooms/room-shell apache-arrow
|
|
43
57
|
```
|
|
44
58
|
|
|
59
|
+
For Mosaic dashboard integration, also install `@sqlrooms/mosaic`,
|
|
60
|
+
`@uwdata/mosaic-core`, and `@uwdata/mosaic-sql`, then import the adapter from
|
|
61
|
+
`@sqlrooms/deck/mosaic`.
|
|
62
|
+
|
|
45
63
|
## What This Package Does
|
|
46
64
|
|
|
47
65
|
`@sqlrooms/deck` is the JSON-spec bridge between SQLRooms data and deck.gl:
|
|
@@ -60,6 +78,10 @@ instead of hand-constructing deck layer instances in React code.
|
|
|
60
78
|
|
|
61
79
|
## Quick Start
|
|
62
80
|
|
|
81
|
+
`DeckJsonMap` resolves SQL and table datasets through the current SQLRooms
|
|
82
|
+
store. Render it inside `RoomShell` or `RoomStateProvider` with a store that
|
|
83
|
+
includes DuckDB state. The example below assumes that host is already mounted.
|
|
84
|
+
|
|
63
85
|
```tsx
|
|
64
86
|
import {DeckJsonMap} from '@sqlrooms/deck';
|
|
65
87
|
|
|
@@ -87,7 +109,8 @@ const spec = {
|
|
|
87
109
|
scheme: 'YlOrRd',
|
|
88
110
|
domain: 'auto',
|
|
89
111
|
},
|
|
90
|
-
getRadius:
|
|
112
|
+
getRadius: 6,
|
|
113
|
+
radiusUnits: 'pixels',
|
|
91
114
|
radiusMinPixels: 2,
|
|
92
115
|
},
|
|
93
116
|
],
|
|
@@ -105,12 +128,78 @@ export function AirportsMap() {
|
|
|
105
128
|
geometryEncodingHint: 'wkb',
|
|
106
129
|
},
|
|
107
130
|
}}
|
|
108
|
-
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
|
|
109
131
|
/>
|
|
110
132
|
);
|
|
111
133
|
}
|
|
112
134
|
```
|
|
113
135
|
|
|
136
|
+
## Basemaps
|
|
137
|
+
|
|
138
|
+
Deck maps use [OpenFreeMap](https://openfreemap.org/) vector tiles by default:
|
|
139
|
+
**Positron** for light mode and **Dark** for dark mode. No API key or registration
|
|
140
|
+
is required. The hosted styles include attribution, which MapLibre displays.
|
|
141
|
+
Maps work immediately with `createDeckMapsSlice()` or `DeckJsonMap`, without
|
|
142
|
+
additional configuration.
|
|
143
|
+
|
|
144
|
+
New map resources and dashboard panels save `mapStyle: 'light'` or
|
|
145
|
+
`'dark'` using the app theme at creation. Changing the app theme later
|
|
146
|
+
does not change existing maps. The **Basemap** dropdown in map settings selects
|
|
147
|
+
Light or Dark, including for maps with custom layer configurations. The selection
|
|
148
|
+
survives dataset changes, config updates, and saved-workspace reloads; keys and
|
|
149
|
+
generated style objects are not stored in map resources. Applications creating
|
|
150
|
+
configs outside the browser can use `getDefaultDeckMapStyle(theme)` explicitly.
|
|
151
|
+
|
|
152
|
+
Bare `DeckJsonMap` instances and older saved maps without a style continue to
|
|
153
|
+
follow the app theme. Choose a basemap in settings to persist it in an older map.
|
|
154
|
+
Explicit custom `mapStyle` URLs and `mapProps.mapStyle` objects remain supported;
|
|
155
|
+
the selector displays **Custom** until a built-in style is selected.
|
|
156
|
+
|
|
157
|
+
For custom basemaps, supply a `DeckMapBasemapProvider` callback:
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
createDeckMapsSlice({basemapProvider: (theme) => customStyles[theme]});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Return stable MapLibre style objects or URLs. Direct `DeckJsonMap` callers
|
|
164
|
+
can pass `basemapProvider` as a prop, overriding the room's provider without
|
|
165
|
+
requiring the Deck maps slice. The existing room store is still required for
|
|
166
|
+
dataset preparation. Explicit custom map styles take precedence over
|
|
167
|
+
the provider.
|
|
168
|
+
|
|
169
|
+
`DeckMapDefaultStylesProvider` and `useDeckMapDefaultStyles` are deprecated.
|
|
170
|
+
To migrate an existing `styles={{light, dark}}` wrapper, keep the style objects
|
|
171
|
+
and pass `basemapProvider: (theme) => styles[theme]` to `createDeckMapsSlice`,
|
|
172
|
+
then remove the wrapper. For individual map overrides, pass the same callback
|
|
173
|
+
to `DeckJsonMap`. Code that reads `useDeckMapDefaultStyles` should use the room's
|
|
174
|
+
`deckMaps.basemapProvider` or the supplied callback instead.
|
|
175
|
+
The context API remains functional for backward compatibility, as a fallback
|
|
176
|
+
when no callback style is available. Removal is reserved for a future breaking
|
|
177
|
+
release.
|
|
178
|
+
|
|
179
|
+
Protomaps remains an optional provider for applications supplying their own key:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import {
|
|
183
|
+
createDeckMapsSlice,
|
|
184
|
+
createProtomapsBasemapProvider,
|
|
185
|
+
} from '@sqlrooms/deck';
|
|
186
|
+
|
|
187
|
+
createDeckMapsSlice({
|
|
188
|
+
basemapProvider: createProtomapsBasemapProvider(protomapsApiKey),
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The helper creates and reuses the light/dark style objects. Its callback lives
|
|
193
|
+
outside `deckMaps.config`, so its key is not persisted with maps. Obtain a
|
|
194
|
+
browser-visible key from [Protomaps](https://protomaps.com/api) and configure
|
|
195
|
+
allowed origins. A missing or blank key falls back to OpenFreeMap.
|
|
196
|
+
Document maps, dashboard maps, and `DeckJsonMap` inherit the room's provider.
|
|
197
|
+
|
|
198
|
+
`createProtomapsStyle(flavor, apiKey)` creates a MapLibre style object, and
|
|
199
|
+
`createProtomapsDefaultStyles(apiKey)` creates the Protomaps light/dark pair.
|
|
200
|
+
`DECK_MAP_BASEMAP_STYLES` lists the provider-neutral IDs and labels. Existing
|
|
201
|
+
`protomaps-light`/`protomaps-dark` selections are recognized as light/dark aliases.
|
|
202
|
+
|
|
114
203
|
## Auto Spec Generation
|
|
115
204
|
|
|
116
205
|
If you want a starter JSON spec instead of writing every layer manually, use
|
|
@@ -164,10 +253,11 @@ const spec = createDeckJsonSpecFromDatasets({
|
|
|
164
253
|
|
|
165
254
|
## Mosaic Dashboard Renderer
|
|
166
255
|
|
|
167
|
-
`@sqlrooms/deck`
|
|
256
|
+
`@sqlrooms/deck/mosaic` contributes a `deck-json-map` panel renderer to
|
|
168
257
|
`@sqlrooms/mosaic` dashboards without making the Mosaic package depend on
|
|
169
|
-
deck.gl or MapLibre.
|
|
170
|
-
|
|
258
|
+
deck.gl or MapLibre. `createDeckMapDashboardSliceOptions()` installs the map
|
|
259
|
+
renderer and add-panel action alongside the default Mosaic renderers, actions,
|
|
260
|
+
and chart types.
|
|
171
261
|
|
|
172
262
|
The dashboard renderer exposes `DeckMapDashboardSettings` through its renderer
|
|
173
263
|
definition. `DeckMapBlockSettings` is also exported for block-document hosts
|
|
@@ -176,20 +266,13 @@ that embed maps as stateful blocks.
|
|
|
176
266
|
```tsx
|
|
177
267
|
import {
|
|
178
268
|
createDeckMapDashboardPanelConfig,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
} from '@sqlrooms/
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
} from '@sqlrooms/mosaic';
|
|
187
|
-
|
|
188
|
-
const dashboardSlice = createMosaicDashboardSlice({
|
|
189
|
-
panelRenderers: createDefaultMosaicDashboardPanelRenderers({
|
|
190
|
-
[DECK_MAP_DASHBOARD_PANEL_TYPE]: deckMapDashboardPanelRenderer,
|
|
191
|
-
}),
|
|
192
|
-
});
|
|
269
|
+
createDeckMapDashboardSliceOptions,
|
|
270
|
+
} from '@sqlrooms/deck/mosaic';
|
|
271
|
+
import {createMosaicDashboardSlice, MosaicDashboard} from '@sqlrooms/mosaic';
|
|
272
|
+
|
|
273
|
+
const dashboardSlice = createMosaicDashboardSlice(
|
|
274
|
+
createDeckMapDashboardSliceOptions(),
|
|
275
|
+
);
|
|
193
276
|
|
|
194
277
|
function Dashboard() {
|
|
195
278
|
return <MosaicDashboard dashboardId="geo" />;
|
|
@@ -264,15 +347,19 @@ as durable resources without creating a dashboard. Compose
|
|
|
264
347
|
`ensureDeckMapResourceState(...)` for a durable map id, and render it with
|
|
265
348
|
`DeckMapBlockRenderer`.
|
|
266
349
|
|
|
350
|
+
See [Blocks and Block Documents](https://sqlrooms.org/blocks-and-documents.html)
|
|
351
|
+
for the surrounding artifact, renderer-provider, persistence, and ownership
|
|
352
|
+
setup.
|
|
353
|
+
|
|
267
354
|
Runtime issue recovery can call `deckMaps.clearMapIssue(mapId, kind)` to clear
|
|
268
355
|
only a matching issue kind; omit `kind` when the map state should clear any
|
|
269
356
|
stale issue. Replacing a map config clears its prior render issue, while data
|
|
270
357
|
issues remain until the corresponding dataset recovery is reported.
|
|
271
|
-
Direct
|
|
358
|
+
Direct document maps automatically fit the configured dataset when the map or
|
|
272
359
|
its source first becomes ready; the header action remains available for manual
|
|
273
360
|
refitting.
|
|
274
361
|
|
|
275
|
-
Hosts that expose direct
|
|
362
|
+
Hosts that expose direct document-map AI capability should include
|
|
276
363
|
`getDeckMapResourceAiInstructions()` in the responsible agent and tool
|
|
277
364
|
instructions. `createOrUpdateDeckMapResource(...)` validates the fully merged
|
|
278
365
|
resource before any durable block or map write: each dataset needs a
|
|
@@ -334,6 +421,11 @@ const result = await createOrUpdateDeckMapResource(
|
|
|
334
421
|
blockDocumentId,
|
|
335
422
|
mapId,
|
|
336
423
|
config,
|
|
424
|
+
pointBinding: {
|
|
425
|
+
dataset: 'places',
|
|
426
|
+
longitudeColumn: 'longitude',
|
|
427
|
+
latitudeColumn: 'latitude',
|
|
428
|
+
},
|
|
337
429
|
tableName,
|
|
338
430
|
title,
|
|
339
431
|
intent,
|
|
@@ -355,10 +447,22 @@ title and uses it as the default block caption. Block metadata is written only
|
|
|
355
447
|
after the map write succeeds.
|
|
356
448
|
|
|
357
449
|
Map authoring helpers such as `normalizeDeckMapPointConfig(...)`,
|
|
358
|
-
`
|
|
450
|
+
`applyDeckMapPointBinding(...)`, `normalizeDeckMapFillColor(...)`,
|
|
451
|
+
`regenerateMapConfigForTable(...)`, and
|
|
359
452
|
dataset-source helpers such as `getFirstDatasetSourceTableName(...)` are
|
|
360
453
|
exported so hosts can normalize AI-authored configs before calling
|
|
361
|
-
`createOrUpdateDeckMapResource(...)`. `
|
|
454
|
+
`createOrUpdateDeckMapResource(...)`. Passing structured `pointBinding` to the
|
|
455
|
+
resource helper applies `applyDeckMapPointBinding(...)`: it generates canonical
|
|
456
|
+
WKB point SQL through `createDeckMapPointTransformSql(...)` and aligns the target
|
|
457
|
+
dataset, point layers, brush interaction, and fit binding. The host table lookup
|
|
458
|
+
also supplies source columns so missing coordinate columns and a generated
|
|
459
|
+
geometry alias that would duplicate an existing column are rejected before
|
|
460
|
+
durable state is written. For a single table-backed dataset, its canonical table
|
|
461
|
+
identity must also match the selected table because that selection overrides the
|
|
462
|
+
authored dataset source at render time. This is the preferred path for standard
|
|
463
|
+
table-backed longitude/latitude maps; raw `transformSql` remains available for
|
|
464
|
+
custom spatial transforms.
|
|
465
|
+
`normalizeDeckMapPointConfig(...)` only adds
|
|
362
466
|
the standard lon/lat point transform to table-backed datasets that do not
|
|
363
467
|
already declare `geometryColumn`, `source.sqlQuery`, or `source.transformSql`
|
|
364
468
|
and whose resolved table does not expose a native geometry column; native
|
|
@@ -392,6 +496,24 @@ layers (e.g. render points under map labels) and reduces WebGL context usage.
|
|
|
392
496
|
Set `interleaved` to `false` to render deck layers in a separate overlay canvas
|
|
393
497
|
on top of all basemap layers (uses an additional WebGL context per map).
|
|
394
498
|
|
|
499
|
+
MapLibre's drawing buffer is preserved by default so DOM image capture can
|
|
500
|
+
include the basemap and interleaved deck layers after a frame finishes.
|
|
501
|
+
In separate-overlay mode, deck.gl/luma.gl also preserves its drawing buffer by
|
|
502
|
+
default. Both map canvases are identified for capture validation, including
|
|
503
|
+
overlays with a custom deck ID. A lost context or disabled preservation on
|
|
504
|
+
either canvas causes the CLI rendering tools to return an actionable error.
|
|
505
|
+
Capture readiness also tracks dataset preparation, MapLibre tile rendering,
|
|
506
|
+
and deck layers' asynchronous resources. While any map in the requested surface
|
|
507
|
+
is still loading, the CLI rendering tools return an error asking the caller to
|
|
508
|
+
wait and retry, instead of returning an incomplete image.
|
|
509
|
+
Preserving the buffer can increase GPU memory use and reduce rendering
|
|
510
|
+
performance. Hosts that do not need image capture can opt out by setting
|
|
511
|
+
`mapProps.canvasContextAttributes.preserveDrawingBuffer` to `false`.
|
|
512
|
+
Changing this context option requires remounting the map.
|
|
513
|
+
To opt out for a separate deck overlay, set
|
|
514
|
+
`deckProps.deviceProps.webgl.preserveDrawingBuffer` to `false` and remount
|
|
515
|
+
the map; DOM image capture will then be unavailable.
|
|
516
|
+
|
|
395
517
|
```tsx
|
|
396
518
|
{
|
|
397
519
|
/* Default (interleaved): */
|
|
@@ -540,6 +662,21 @@ getFillColor: {
|
|
|
540
662
|
}
|
|
541
663
|
```
|
|
542
664
|
|
|
665
|
+
Optional `opacity` (0–1) is a SQLRooms `colorScale` extension. The compiler
|
|
666
|
+
multiplies it into the color's alpha so fill, stroke, and arc endpoints can be
|
|
667
|
+
dimmed independently of deck.gl `layer.opacity`:
|
|
668
|
+
|
|
669
|
+
```tsx
|
|
670
|
+
getFillColor: {
|
|
671
|
+
'@@function': 'colorScale',
|
|
672
|
+
field: 'Magnitude',
|
|
673
|
+
type: 'sequential',
|
|
674
|
+
scheme: 'YlOrRd',
|
|
675
|
+
domain: 'auto',
|
|
676
|
+
opacity: 0.6,
|
|
677
|
+
}
|
|
678
|
+
```
|
|
679
|
+
|
|
543
680
|
Discrete numeric palettes are supported too:
|
|
544
681
|
|
|
545
682
|
```tsx
|
|
@@ -597,6 +734,10 @@ scenes. It accepts resolved Arrow tables with geometry stored as:
|
|
|
597
734
|
- WKB / GeoArrow WKB
|
|
598
735
|
- WKT / GeoArrow WKT
|
|
599
736
|
|
|
737
|
+
The returned `PreparedDeckDataset` records the dataset-level
|
|
738
|
+
`datasetGeometryColumn` and `datasetGeometryEncodingHint` used to prepare
|
|
739
|
+
and identify that payload.
|
|
740
|
+
|
|
600
741
|
It then produces canonical deck-facing geometry outputs for:
|
|
601
742
|
|
|
602
743
|
- GeoArrow-native layers such as `GeoArrowScatterplotLayer`
|
|
@@ -617,24 +758,27 @@ Deck caches only the expensive geometry preparation layer on top.
|
|
|
617
758
|
|
|
618
759
|
## Supported Layers
|
|
619
760
|
|
|
620
|
-
The
|
|
761
|
+
The map-resource validator and settings UI support this curated layer set:
|
|
621
762
|
|
|
622
763
|
- `GeoArrowScatterplotLayer`
|
|
623
764
|
- `GeoArrowHeatmapLayer`
|
|
624
765
|
- `GeoArrowColumnLayer`
|
|
625
766
|
- `GeoArrowPathLayer`
|
|
626
767
|
- `GeoArrowPolygonLayer`
|
|
627
|
-
- `GeoArrowSolidPolygonLayer`
|
|
628
768
|
- `GeoArrowArcLayer`
|
|
629
769
|
- `GeoArrowTripsLayer`
|
|
630
770
|
- `GeoArrowH3HexagonLayer`
|
|
631
771
|
- `GeoJsonLayer`
|
|
632
772
|
|
|
773
|
+
The lower-level `DeckJsonMap` JSON converter also registers
|
|
774
|
+
`GeoArrowSolidPolygonLayer`. Durable resource and AI authoring intentionally do
|
|
775
|
+
not accept it; use `GeoArrowPolygonLayer` for authored map resources.
|
|
776
|
+
|
|
633
777
|
GeoArrow-native geometry columns are the efficient path. WKB/WKT geometry falls
|
|
634
778
|
back to decoding and GeoJSON-binary preparation, with promotion available
|
|
635
779
|
for point-focused GeoArrow layers such as `GeoArrowScatterplotLayer`,
|
|
636
780
|
`GeoArrowHeatmapLayer`, and `GeoArrowColumnLayer`, plus Polygon promotion for
|
|
637
|
-
`GeoArrowPolygonLayer
|
|
781
|
+
`GeoArrowPolygonLayer`. WKB/WKT MultiPolygon
|
|
638
782
|
uses the GeoJSON-binary path so separate polygon parts retain their nesting.
|
|
639
783
|
|
|
640
784
|
The GeoArrow layer implementations themselves come from
|
|
@@ -649,7 +793,7 @@ not rewritten — the wrap is an outer pipeline query. Prefer writing
|
|
|
649
793
|
`ST_AsWKB(...)` in transforms when you control the SQL; the pipeline covers
|
|
650
794
|
bare `ST_Point(...)` / table `GEOMETRY` columns for every authoring surface.
|
|
651
795
|
|
|
652
|
-
## AI map
|
|
796
|
+
## Prepare AI-authored map configs
|
|
653
797
|
|
|
654
798
|
AI and host tooling should prepare authored Deck map configs through the shared
|
|
655
799
|
helpers exported from `@sqlrooms/deck`:
|
|
@@ -673,9 +817,15 @@ helpers exported from `@sqlrooms/deck`:
|
|
|
673
817
|
Skips unknown-field rejection when `transformSql` / `sqlQuery` is present
|
|
674
818
|
(aliases may be transform-only).
|
|
675
819
|
|
|
820
|
+
Mosaic-specific AI helpers such as `createDeckMapDashboardTool()`,
|
|
821
|
+
`createDashboardWithDeckMapAiTools()`, and
|
|
822
|
+
`createDashboardAgentToolWithDeckMaps()` are exported from
|
|
823
|
+
`@sqlrooms/deck/mosaic`.
|
|
824
|
+
|
|
676
825
|
Durable resource writes also run `getDeckMapResourceConfigIssues` /
|
|
677
|
-
`assertDeckMapResourceConfig` for syntax and type/scheme
|
|
678
|
-
(e.g. `quantile` + `Viridis` is rejected
|
|
826
|
+
`assertDeckMapResourceConfig` for syntax, supported layer types, and type/scheme
|
|
827
|
+
compatibility (e.g. `quantile` + `Viridis` is rejected; layer `@@type` must be
|
|
828
|
+
one of the settings picker classes). Native `GEOMETRY` columns are
|
|
679
829
|
normalized to WKB by the dataset pipeline (not by SQL-string validation).
|
|
680
830
|
|
|
681
831
|
## Runtime Props and Children
|
|
@@ -688,3 +838,11 @@ Keep the spec serializable, then pass runtime behavior separately:
|
|
|
688
838
|
|
|
689
839
|
This lets the spec stay stable for storage, validation, and future AI-assisted
|
|
690
840
|
generation while still supporting interactive React behavior at runtime.
|
|
841
|
+
|
|
842
|
+
## More resources
|
|
843
|
+
|
|
844
|
+
- [`@sqlrooms/deck` API reference](https://sqlrooms.org/api/deck/)
|
|
845
|
+
- [Deck.gl example source](https://github.com/sqlrooms/examples/tree/main/deckgl)
|
|
846
|
+
- [Deck.gl + Mosaic example source](https://github.com/sqlrooms/examples/tree/main/deckgl-mosaic)
|
|
847
|
+
- [Blocks and Block Documents](https://sqlrooms.org/blocks-and-documents.html)
|
|
848
|
+
- [Commands](https://sqlrooms.org/commands.html)
|
|
@@ -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":"AAaA,OAAO,kCAAkC,CAAC;AAyB1C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAEjB,MAAM,SAAS,CAAC;AA8SjB,eAAO,MAAM,WAAW,gHAsXvB,CAAC"}
|