@sqlrooms/deck 0.29.0-rc.10
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/LICENSE.md +10 -0
- package/README.md +654 -0
- package/dist/BlockMapSettings.d.ts +3 -0
- package/dist/BlockMapSettings.d.ts.map +1 -0
- package/dist/BlockMapSettings.js +57 -0
- package/dist/BlockMapSettings.js.map +1 -0
- package/dist/DashboardMapSettings.d.ts +7 -0
- package/dist/DashboardMapSettings.d.ts.map +1 -0
- package/dist/DashboardMapSettings.js +52 -0
- package/dist/DashboardMapSettings.js.map +1 -0
- package/dist/DeckJsonMap.d.ts +4 -0
- package/dist/DeckJsonMap.d.ts.map +1 -0
- package/dist/DeckJsonMap.js +370 -0
- package/dist/DeckJsonMap.js.map +1 -0
- package/dist/DeckJsonMapSpec.d.ts +7617 -0
- package/dist/DeckJsonMapSpec.d.ts.map +1 -0
- package/dist/DeckJsonMapSpec.js +82 -0
- package/dist/DeckJsonMapSpec.js.map +1 -0
- package/dist/DeckMapDefaultStylesProvider.d.ts +28 -0
- package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -0
- package/dist/DeckMapDefaultStylesProvider.js +23 -0
- package/dist/DeckMapDefaultStylesProvider.js.map +1 -0
- package/dist/DeckMapSurface.d.ts +39 -0
- package/dist/DeckMapSurface.d.ts.map +1 -0
- package/dist/DeckMapSurface.js +137 -0
- package/dist/DeckMapSurface.js.map +1 -0
- package/dist/DeckMapsSlice.d.ts +99 -0
- package/dist/DeckMapsSlice.d.ts.map +1 -0
- package/dist/DeckMapsSlice.js +89 -0
- package/dist/DeckMapsSlice.js.map +1 -0
- package/dist/MapSettings.d.ts +16 -0
- package/dist/MapSettings.d.ts.map +1 -0
- package/dist/MapSettings.js +292 -0
- package/dist/MapSettings.js.map +1 -0
- package/dist/MapSettingsControls.d.ts +40 -0
- package/dist/MapSettingsControls.d.ts.map +1 -0
- package/dist/MapSettingsControls.js +54 -0
- package/dist/MapSettingsControls.js.map +1 -0
- package/dist/ai.d.ts +261 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +392 -0
- package/dist/ai.js.map +1 -0
- package/dist/block.d.ts +21 -0
- package/dist/block.d.ts.map +1 -0
- package/dist/block.js +105 -0
- package/dist/block.js.map +1 -0
- package/dist/blockDocumentRegistration.d.ts +45 -0
- package/dist/blockDocumentRegistration.d.ts.map +1 -0
- package/dist/blockDocumentRegistration.js +68 -0
- package/dist/blockDocumentRegistration.js.map +1 -0
- package/dist/createDeckJsonSpecFromDatasets.d.ts +11 -0
- package/dist/createDeckJsonSpecFromDatasets.d.ts.map +1 -0
- package/dist/createDeckJsonSpecFromDatasets.js +85 -0
- package/dist/createDeckJsonSpecFromDatasets.js.map +1 -0
- package/dist/createOrUpdateDeckMapResource.d.ts +81 -0
- package/dist/createOrUpdateDeckMapResource.d.ts.map +1 -0
- package/dist/createOrUpdateDeckMapResource.js +82 -0
- package/dist/createOrUpdateDeckMapResource.js.map +1 -0
- package/dist/dashboard.d.ts +6 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +337 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/dashboardConfig.d.ts +25 -0
- package/dist/dashboardConfig.d.ts.map +1 -0
- package/dist/dashboardConfig.js +82 -0
- package/dist/dashboardConfig.js.map +1 -0
- package/dist/dashboardIntegration.d.ts +3 -0
- package/dist/dashboardIntegration.d.ts.map +1 -0
- package/dist/dashboardIntegration.js +16 -0
- package/dist/dashboardIntegration.js.map +1 -0
- package/dist/datasetSourceUtils.d.ts +16 -0
- package/dist/datasetSourceUtils.d.ts.map +1 -0
- package/dist/datasetSourceUtils.js +25 -0
- package/dist/datasetSourceUtils.js.map +1 -0
- package/dist/datasets/PreparedDatasetStore.d.ts +120 -0
- package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -0
- package/dist/datasets/PreparedDatasetStore.js +268 -0
- package/dist/datasets/PreparedDatasetStore.js.map +1 -0
- package/dist/datasets/helpers.d.ts +57 -0
- package/dist/datasets/helpers.d.ts.map +1 -0
- package/dist/datasets/helpers.js +155 -0
- package/dist/datasets/helpers.js.map +1 -0
- package/dist/datasets/normalizeDatasets.d.ts +11 -0
- package/dist/datasets/normalizeDatasets.d.ts.map +1 -0
- package/dist/datasets/normalizeDatasets.js +50 -0
- package/dist/datasets/normalizeDatasets.js.map +1 -0
- package/dist/datasets/tableAdapter.d.ts +11 -0
- package/dist/datasets/tableAdapter.d.ts.map +1 -0
- package/dist/datasets/tableAdapter.js +11 -0
- package/dist/datasets/tableAdapter.js.map +1 -0
- package/dist/datasets/tableDatasetSql.d.ts +16 -0
- package/dist/datasets/tableDatasetSql.d.ts.map +1 -0
- package/dist/datasets/tableDatasetSql.js +49 -0
- package/dist/datasets/tableDatasetSql.js.map +1 -0
- package/dist/datasets/types.d.ts +40 -0
- package/dist/datasets/types.d.ts.map +1 -0
- package/dist/datasets/types.js +2 -0
- package/dist/datasets/types.js.map +1 -0
- package/dist/datasets/usePreparedDatasetStates.d.ts +16 -0
- package/dist/datasets/usePreparedDatasetStates.d.ts.map +1 -0
- package/dist/datasets/usePreparedDatasetStates.js +59 -0
- package/dist/datasets/usePreparedDatasetStates.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/json/aggregateWaypoints.d.ts +14 -0
- package/dist/json/aggregateWaypoints.d.ts.map +1 -0
- package/dist/json/aggregateWaypoints.js +190 -0
- package/dist/json/aggregateWaypoints.js.map +1 -0
- package/dist/json/colorScaleFunction.d.ts +27 -0
- package/dist/json/colorScaleFunction.d.ts.map +1 -0
- package/dist/json/colorScaleFunction.js +46 -0
- package/dist/json/colorScaleFunction.js.map +1 -0
- package/dist/json/compileColorScale.d.ts +12 -0
- package/dist/json/compileColorScale.d.ts.map +1 -0
- package/dist/json/compileColorScale.js +125 -0
- package/dist/json/compileColorScale.js.map +1 -0
- package/dist/json/compileGeoArrowAccessor.d.ts +18 -0
- package/dist/json/compileGeoArrowAccessor.d.ts.map +1 -0
- package/dist/json/compileGeoArrowAccessor.js +129 -0
- package/dist/json/compileGeoArrowAccessor.js.map +1 -0
- package/dist/json/createDeckJsonConfiguration.d.ts +9 -0
- package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -0
- package/dist/json/createDeckJsonConfiguration.js +315 -0
- package/dist/json/createDeckJsonConfiguration.js.map +1 -0
- package/dist/json/defaultClasses.d.ts +12 -0
- package/dist/json/defaultClasses.d.ts.map +1 -0
- package/dist/json/defaultClasses.js +35 -0
- package/dist/json/defaultClasses.js.map +1 -0
- package/dist/json/extractColorScaleLegends.d.ts +8 -0
- package/dist/json/extractColorScaleLegends.d.ts.map +1 -0
- package/dist/json/extractColorScaleLegends.js +86 -0
- package/dist/json/extractColorScaleLegends.js.map +1 -0
- package/dist/json/heatmapDefaults.d.ts +8 -0
- package/dist/json/heatmapDefaults.d.ts.map +1 -0
- package/dist/json/heatmapDefaults.js +14 -0
- package/dist/json/heatmapDefaults.js.map +1 -0
- package/dist/json/layerCompatibility.d.ts +21 -0
- package/dist/json/layerCompatibility.d.ts.map +1 -0
- package/dist/json/layerCompatibility.js +168 -0
- package/dist/json/layerCompatibility.js.map +1 -0
- package/dist/json/layerConfig.d.ts +14 -0
- package/dist/json/layerConfig.d.ts.map +1 -0
- package/dist/json/layerConfig.js +54 -0
- package/dist/json/layerConfig.js.map +1 -0
- package/dist/json/layers/DeckColumnLayer.d.ts +10 -0
- package/dist/json/layers/DeckColumnLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckColumnLayer.js +26 -0
- package/dist/json/layers/DeckColumnLayer.js.map +1 -0
- package/dist/json/layers/DeckH3HexagonLayer.d.ts +37 -0
- package/dist/json/layers/DeckH3HexagonLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckH3HexagonLayer.js +118 -0
- package/dist/json/layers/DeckH3HexagonLayer.js.map +1 -0
- package/dist/json/layers/DeckTripsLayer.d.ts +46 -0
- package/dist/json/layers/DeckTripsLayer.d.ts.map +1 -0
- package/dist/json/layers/DeckTripsLayer.js +170 -0
- package/dist/json/layers/DeckTripsLayer.js.map +1 -0
- package/dist/json/layers/createTableToRecordBatchAdapter.d.ts +20 -0
- package/dist/json/layers/createTableToRecordBatchAdapter.d.ts.map +1 -0
- package/dist/json/layers/createTableToRecordBatchAdapter.js +81 -0
- package/dist/json/layers/createTableToRecordBatchAdapter.js.map +1 -0
- package/dist/json/layers/index.d.ts +5 -0
- package/dist/json/layers/index.d.ts.map +1 -0
- package/dist/json/layers/index.js +5 -0
- package/dist/json/layers/index.js.map +1 -0
- package/dist/json/rewriteGeoArrowAccessors.d.ts +7 -0
- package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -0
- package/dist/json/rewriteGeoArrowAccessors.js +55 -0
- package/dist/json/rewriteGeoArrowAccessors.js.map +1 -0
- package/dist/mapAiConfig.d.ts +111 -0
- package/dist/mapAiConfig.d.ts.map +1 -0
- package/dist/mapAiConfig.js +69 -0
- package/dist/mapAiConfig.js.map +1 -0
- package/dist/mapConfig.d.ts +73 -0
- package/dist/mapConfig.d.ts.map +1 -0
- package/dist/mapConfig.js +47 -0
- package/dist/mapConfig.js.map +1 -0
- package/dist/mapConfigUtils.d.ts +111 -0
- package/dist/mapConfigUtils.d.ts.map +1 -0
- package/dist/mapConfigUtils.js +502 -0
- package/dist/mapConfigUtils.js.map +1 -0
- package/dist/mapDataPolicy.d.ts +9 -0
- package/dist/mapDataPolicy.d.ts.map +1 -0
- package/dist/mapDataPolicy.js +25 -0
- package/dist/mapDataPolicy.js.map +1 -0
- package/dist/mapFit.d.ts +62 -0
- package/dist/mapFit.d.ts.map +1 -0
- package/dist/mapFit.js +325 -0
- package/dist/mapFit.js.map +1 -0
- package/dist/mapLayerConfigUtils.d.ts +54 -0
- package/dist/mapLayerConfigUtils.d.ts.map +1 -0
- package/dist/mapLayerConfigUtils.js +296 -0
- package/dist/mapLayerConfigUtils.js.map +1 -0
- package/dist/mapResourceAuthoring.d.ts +40 -0
- package/dist/mapResourceAuthoring.d.ts.map +1 -0
- package/dist/mapResourceAuthoring.js +266 -0
- package/dist/mapResourceAuthoring.js.map +1 -0
- package/dist/mosaic.d.ts +9 -0
- package/dist/mosaic.d.ts.map +1 -0
- package/dist/mosaic.js +8 -0
- package/dist/mosaic.js.map +1 -0
- package/dist/prepare/detectGeometryColumn.d.ts +19 -0
- package/dist/prepare/detectGeometryColumn.d.ts.map +1 -0
- package/dist/prepare/detectGeometryColumn.js +126 -0
- package/dist/prepare/detectGeometryColumn.js.map +1 -0
- package/dist/prepare/geoarrow.d.ts +18 -0
- package/dist/prepare/geoarrow.d.ts.map +1 -0
- package/dist/prepare/geoarrow.js +114 -0
- package/dist/prepare/geoarrow.js.map +1 -0
- package/dist/prepare/geometryDecoder.d.ts +8 -0
- package/dist/prepare/geometryDecoder.d.ts.map +1 -0
- package/dist/prepare/geometryDecoder.js +2 -0
- package/dist/prepare/geometryDecoder.js.map +1 -0
- package/dist/prepare/prepareDeckDataset.d.ts +57 -0
- package/dist/prepare/prepareDeckDataset.d.ts.map +1 -0
- package/dist/prepare/prepareDeckDataset.js +112 -0
- package/dist/prepare/prepareDeckDataset.js.map +1 -0
- package/dist/prepare/toGeoJsonBinary.d.ts +9 -0
- package/dist/prepare/toGeoJsonBinary.d.ts.map +1 -0
- package/dist/prepare/toGeoJsonBinary.js +26 -0
- package/dist/prepare/toGeoJsonBinary.js.map +1 -0
- package/dist/prepare/types.d.ts +25 -0
- package/dist/prepare/types.d.ts.map +1 -0
- package/dist/prepare/types.js +2 -0
- package/dist/prepare/types.js.map +1 -0
- package/dist/prepare/wkbDecoder.d.ts +3 -0
- package/dist/prepare/wkbDecoder.d.ts.map +1 -0
- package/dist/prepare/wkbDecoder.js +419 -0
- package/dist/prepare/wkbDecoder.js.map +1 -0
- package/dist/prepare/wkbParser.d.ts +24 -0
- package/dist/prepare/wkbParser.d.ts.map +1 -0
- package/dist/prepare/wkbParser.js +139 -0
- package/dist/prepare/wkbParser.js.map +1 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/useDeckMapDatasetSchema.d.ts +33 -0
- package/dist/useDeckMapDatasetSchema.d.ts.map +1 -0
- package/dist/useDeckMapDatasetSchema.js +138 -0
- package/dist/useDeckMapDatasetSchema.js.map +1 -0
- package/dist/useDeckMapDatasets.d.ts +17 -0
- package/dist/useDeckMapDatasets.d.ts.map +1 -0
- package/dist/useDeckMapDatasets.js +69 -0
- package/dist/useDeckMapDatasets.js.map +1 -0
- package/dist/useDeckMapFitToBounds.d.ts +31 -0
- package/dist/useDeckMapFitToBounds.d.ts.map +1 -0
- package/dist/useDeckMapFitToBounds.js +58 -0
- package/dist/useDeckMapFitToBounds.js.map +1 -0
- package/package.json +98 -0
package/dist/block.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { getTableIdentity, } from '@sqlrooms/duckdb';
|
|
3
|
+
import { useBlockSettingsStore } from '@sqlrooms/documents';
|
|
4
|
+
import { Button, Tooltip, TooltipContent, TooltipTrigger } from '@sqlrooms/ui';
|
|
5
|
+
import { FocusIcon, MapIcon, SlidersVerticalIcon } from 'lucide-react';
|
|
6
|
+
import { Component, useCallback, useEffect, useState, } from 'react';
|
|
7
|
+
import { DeckMapSurface, directDeckMapDataAdapter, } from './DeckMapSurface';
|
|
8
|
+
import { useStoreWithDeckMaps } from './DeckMapsSlice';
|
|
9
|
+
import { createEmptyDeckMapConfig } from './mapConfig';
|
|
10
|
+
import { createDeckMapConfigForTable, findGeometryColumn, findLongitudeLatitudeColumns, } from './mapConfigUtils';
|
|
11
|
+
class DeckMapResourceErrorBoundary extends Component {
|
|
12
|
+
state = {
|
|
13
|
+
resetKey: this.props.resetKey,
|
|
14
|
+
};
|
|
15
|
+
static getDerivedStateFromError(error) {
|
|
16
|
+
return { error };
|
|
17
|
+
}
|
|
18
|
+
static getDerivedStateFromProps(props, state) {
|
|
19
|
+
return Object.is(props.resetKey, state.resetKey)
|
|
20
|
+
? null
|
|
21
|
+
: { error: undefined, resetKey: props.resetKey };
|
|
22
|
+
}
|
|
23
|
+
componentDidCatch(error, errorInfo) {
|
|
24
|
+
console.error('[DeckMapResourceErrorBoundary] Map render failed', error, errorInfo);
|
|
25
|
+
this.props.onError(error);
|
|
26
|
+
}
|
|
27
|
+
render() {
|
|
28
|
+
if (this.state.error) {
|
|
29
|
+
return (_jsxs("div", { className: "text-muted-foreground flex h-full min-h-[320px] items-center justify-center p-4 text-center text-sm", children: ["Map failed to render: ", this.state.error.message] }));
|
|
30
|
+
}
|
|
31
|
+
return this.props.children;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Ensures a first-class map resource, optionally seeded from geospatial data. */
|
|
35
|
+
export function ensureDeckMapResourceState(state, mapId, title) {
|
|
36
|
+
if (state.deckMaps.getMap(mapId))
|
|
37
|
+
return;
|
|
38
|
+
const table = state.db.tables.find((candidate) => Boolean(findLongitudeLatitudeColumns(candidate)) ||
|
|
39
|
+
Boolean(findGeometryColumn(candidate)));
|
|
40
|
+
state.deckMaps.ensureMap(mapId, {
|
|
41
|
+
title: title ?? 'Map',
|
|
42
|
+
config: table
|
|
43
|
+
? createDeckMapConfigForTable({
|
|
44
|
+
tableName: table.tableName,
|
|
45
|
+
columns: table.columns,
|
|
46
|
+
tableReference: table.table,
|
|
47
|
+
})
|
|
48
|
+
: createEmptyDeckMapConfig(),
|
|
49
|
+
});
|
|
50
|
+
if (table)
|
|
51
|
+
state.deckMaps.setSelectedTable(mapId, getTableIdentity(table.table));
|
|
52
|
+
}
|
|
53
|
+
/** Mosaic-free worksheet map renderer backed only by `deckMaps`. */
|
|
54
|
+
export function DeckMapBlockRenderer({ mapId, title, caption, onCaptionChange, selected, readOnly, headerActions, dataAdapter = directDeckMapDataAdapter, }) {
|
|
55
|
+
const map = useStoreWithDeckMaps((state) => state.deckMaps.config.mapsById[mapId]);
|
|
56
|
+
const tables = useStoreWithDeckMaps((state) => state.db.tables);
|
|
57
|
+
const ensureMap = useStoreWithDeckMaps((state) => state.deckMaps.ensureMap);
|
|
58
|
+
const updateMap = useStoreWithDeckMaps((state) => state.deckMaps.updateMap);
|
|
59
|
+
const setSelectedTable = useStoreWithDeckMaps((state) => state.deckMaps.setSelectedTable);
|
|
60
|
+
const reportMapIssue = useStoreWithDeckMaps((state) => state.deckMaps.reportMapIssue);
|
|
61
|
+
const clearMapIssue = useStoreWithDeckMaps((state) => state.deckMaps.clearMapIssue);
|
|
62
|
+
const requestOpenSettingsPanel = useBlockSettingsStore((state) => state.blockSettings.requestOpenSettingsPanel);
|
|
63
|
+
const requestCloseSettingsPanel = useBlockSettingsStore((state) => state.blockSettings.requestCloseSettingsPanel);
|
|
64
|
+
const isSettingsPanelOpen = useBlockSettingsStore((state) => state.blockSettings.runtime.isSettingsPanelOpen);
|
|
65
|
+
const isSettingsShown = Boolean(selected && isSettingsPanelOpen);
|
|
66
|
+
const [fitRequestVersion, setFitRequestVersion] = useState(0);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (mapId && !map)
|
|
69
|
+
ensureMap(mapId, { title: title ?? 'Embedded Map' });
|
|
70
|
+
}, [ensureMap, map, mapId, title]);
|
|
71
|
+
const handleTableChange = useCallback((table) => {
|
|
72
|
+
setSelectedTable(mapId, getTableIdentity(table.table));
|
|
73
|
+
const hasGeo = Boolean(findLongitudeLatitudeColumns(table)) ||
|
|
74
|
+
Boolean(findGeometryColumn(table));
|
|
75
|
+
updateMap(mapId, {
|
|
76
|
+
config: hasGeo
|
|
77
|
+
? createDeckMapConfigForTable({
|
|
78
|
+
tableName: table.tableName,
|
|
79
|
+
columns: table.columns,
|
|
80
|
+
tableReference: table.table,
|
|
81
|
+
})
|
|
82
|
+
: createEmptyDeckMapConfig(),
|
|
83
|
+
});
|
|
84
|
+
}, [mapId, setSelectedTable, updateMap]);
|
|
85
|
+
if (!map) {
|
|
86
|
+
return (_jsx("div", { className: "text-muted-foreground flex h-full min-h-[320px] items-center justify-center", children: "Preparing map..." }));
|
|
87
|
+
}
|
|
88
|
+
const hasDatasets = Object.keys(map.config.datasets).length > 0;
|
|
89
|
+
const canFitView = Boolean(map.config.fitToData && hasDatasets);
|
|
90
|
+
const fitViewLabel = canFitView
|
|
91
|
+
? 'Fit map view to data'
|
|
92
|
+
: 'Fit view unavailable for this map';
|
|
93
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsxs("div", { className: "border-border flex shrink-0 items-center justify-between gap-2 border-b px-3 py-2", children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [_jsx(MapIcon, { className: "h-4 w-4 shrink-0" }), _jsx("input", { className: "min-w-0 flex-1 bg-transparent text-sm outline-none", value: caption ?? map.title, readOnly: readOnly, placeholder: map.selectedTable ?? title ?? 'Map caption', onChange: (event) => onCaptionChange?.(event.target.value || undefined) })] }), _jsxs("div", { className: "flex items-center gap-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "inline-flex", tabIndex: canFitView ? undefined : 0, "aria-label": canFitView ? undefined : fitViewLabel, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-6 w-6", "aria-label": fitViewLabel, disabled: !canFitView, onClick: () => setFitRequestVersion((version) => version + 1), children: _jsx(FocusIcon, { className: "h-3.5 w-3.5" }) }) }) }), _jsx(TooltipContent, { children: fitViewLabel })] }), _jsx(Button, { type: "button", variant: isSettingsShown ? 'secondary' : 'ghost', size: "icon", className: "h-6 w-6", "aria-label": isSettingsShown ? 'Close map settings' : 'Open map settings', onClick: () => isSettingsShown
|
|
94
|
+
? requestCloseSettingsPanel()
|
|
95
|
+
: requestOpenSettingsPanel(), children: _jsx(SlidersVerticalIcon, { className: "h-3.5 w-3.5" }) }), headerActions] })] }), _jsx("div", { className: "min-h-0 flex-1", children: hasDatasets ? (_jsx(DeckMapResourceErrorBoundary, { resetKey: map.config, onError: (error) => reportMapIssue(mapId, {
|
|
96
|
+
kind: 'render-error',
|
|
97
|
+
message: error.message,
|
|
98
|
+
recoverable: true,
|
|
99
|
+
}), children: _jsx(DeckMapSurface, { mapId: mapId, map: map, readOnly: readOnly, selected: selected, onUpdateMap: (patch) => updateMap(mapId, patch), onReportIssue: (issue) => reportMapIssue(mapId, issue), onClearIssue: (kind) => clearMapIssue(mapId, kind), fitRequestVersion: fitRequestVersion, dataAdapter: dataAdapter }) })) : (_jsx("div", { className: "flex h-full min-h-[320px] items-center justify-center p-4", children: _jsxs("select", { className: "border-border bg-background rounded border px-3 py-2 text-sm", value: map.selectedTable ?? '', disabled: readOnly, onChange: (event) => {
|
|
100
|
+
const table = tables.find((candidate) => getTableIdentity(candidate.table) === event.target.value);
|
|
101
|
+
if (table)
|
|
102
|
+
handleTableChange(table);
|
|
103
|
+
}, children: [_jsx("option", { value: "", children: "Select a table" }), tables.map((table) => (_jsx("option", { value: getTableIdentity(table.table), children: table.tableName }, getTableIdentity(table.table))))] }) })) })] }));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block.js","sourceRoot":"","sources":["../src/block.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n getTableIdentity,\n type DataTable,\n type DuckDbSliceState,\n} from '@sqlrooms/duckdb';\nimport {useBlockSettingsStore} from '@sqlrooms/documents';\nimport {Button, Tooltip, TooltipContent, TooltipTrigger} from '@sqlrooms/ui';\nimport {FocusIcon, MapIcon, SlidersVerticalIcon} from 'lucide-react';\nimport {\n Component,\n useCallback,\n useEffect,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from 'react';\nimport {\n DeckMapSurface,\n directDeckMapDataAdapter,\n type DeckMapDataAdapter,\n} from './DeckMapSurface';\nimport {type DeckMapsSliceState, useStoreWithDeckMaps} from './DeckMapsSlice';\nimport {createEmptyDeckMapConfig} from './mapConfig';\nimport {\n createDeckMapConfigForTable,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n} from './mapConfigUtils';\n\ntype DeckMapResourceState = DeckMapsSliceState & DuckDbSliceState;\n\ntype DeckMapResourceErrorBoundaryProps = {\n children: ReactNode;\n onError: (error: Error) => void;\n resetKey: unknown;\n};\n\ntype DeckMapResourceErrorBoundaryState = {\n error?: Error;\n resetKey: unknown;\n};\n\nclass DeckMapResourceErrorBoundary extends Component<\n DeckMapResourceErrorBoundaryProps,\n DeckMapResourceErrorBoundaryState\n> {\n state: DeckMapResourceErrorBoundaryState = {\n resetKey: this.props.resetKey,\n };\n static getDerivedStateFromError(error: Error) {\n return {error};\n }\n static getDerivedStateFromProps(\n props: DeckMapResourceErrorBoundaryProps,\n state: DeckMapResourceErrorBoundaryState,\n ) {\n return Object.is(props.resetKey, state.resetKey)\n ? null\n : {error: undefined, resetKey: props.resetKey};\n }\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\n '[DeckMapResourceErrorBoundary] Map render failed',\n error,\n errorInfo,\n );\n this.props.onError(error);\n }\n render() {\n if (this.state.error) {\n return (\n <div className=\"text-muted-foreground flex h-full min-h-[320px] items-center justify-center p-4 text-center text-sm\">\n Map failed to render: {this.state.error.message}\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n/** Ensures a first-class map resource, optionally seeded from geospatial data. */\nexport function ensureDeckMapResourceState(\n state: DeckMapResourceState,\n mapId: string,\n title?: string,\n) {\n if (state.deckMaps.getMap(mapId)) return;\n const table = state.db.tables.find(\n (candidate) =>\n Boolean(findLongitudeLatitudeColumns(candidate)) ||\n Boolean(findGeometryColumn(candidate)),\n );\n state.deckMaps.ensureMap(mapId, {\n title: title ?? 'Map',\n config: table\n ? createDeckMapConfigForTable({\n tableName: table.tableName,\n columns: table.columns,\n tableReference: table.table,\n })\n : createEmptyDeckMapConfig(),\n });\n if (table)\n state.deckMaps.setSelectedTable(mapId, getTableIdentity(table.table));\n}\n\nexport type DeckMapBlockRendererProps = {\n mapId: string;\n title?: string;\n caption?: string;\n onCaptionChange?: (caption: string | undefined) => void;\n selected?: boolean;\n readOnly?: boolean;\n headerActions?: ReactNode;\n dataAdapter?: DeckMapDataAdapter;\n};\n\n/** Mosaic-free worksheet map renderer backed only by `deckMaps`. */\nexport function DeckMapBlockRenderer({\n mapId,\n title,\n caption,\n onCaptionChange,\n selected,\n readOnly,\n headerActions,\n dataAdapter = directDeckMapDataAdapter,\n}: DeckMapBlockRendererProps) {\n const map = useStoreWithDeckMaps(\n (state) => state.deckMaps.config.mapsById[mapId],\n );\n const tables = useStoreWithDeckMaps((state) => state.db.tables);\n const ensureMap = useStoreWithDeckMaps((state) => state.deckMaps.ensureMap);\n const updateMap = useStoreWithDeckMaps((state) => state.deckMaps.updateMap);\n const setSelectedTable = useStoreWithDeckMaps(\n (state) => state.deckMaps.setSelectedTable,\n );\n const reportMapIssue = useStoreWithDeckMaps(\n (state) => state.deckMaps.reportMapIssue,\n );\n const clearMapIssue = useStoreWithDeckMaps(\n (state) => state.deckMaps.clearMapIssue,\n );\n const requestOpenSettingsPanel = useBlockSettingsStore(\n (state) => state.blockSettings.requestOpenSettingsPanel,\n );\n const requestCloseSettingsPanel = useBlockSettingsStore(\n (state) => state.blockSettings.requestCloseSettingsPanel,\n );\n const isSettingsPanelOpen = useBlockSettingsStore(\n (state) => state.blockSettings.runtime.isSettingsPanelOpen,\n );\n const isSettingsShown = Boolean(selected && isSettingsPanelOpen);\n const [fitRequestVersion, setFitRequestVersion] = useState(0);\n\n useEffect(() => {\n if (mapId && !map) ensureMap(mapId, {title: title ?? 'Embedded Map'});\n }, [ensureMap, map, mapId, title]);\n\n const handleTableChange = useCallback(\n (table: DataTable) => {\n setSelectedTable(mapId, getTableIdentity(table.table));\n const hasGeo =\n Boolean(findLongitudeLatitudeColumns(table)) ||\n Boolean(findGeometryColumn(table));\n updateMap(mapId, {\n config: hasGeo\n ? createDeckMapConfigForTable({\n tableName: table.tableName,\n columns: table.columns,\n tableReference: table.table,\n })\n : createEmptyDeckMapConfig(),\n });\n },\n [mapId, setSelectedTable, updateMap],\n );\n\n if (!map) {\n return (\n <div className=\"text-muted-foreground flex h-full min-h-[320px] items-center justify-center\">\n Preparing map...\n </div>\n );\n }\n const hasDatasets = Object.keys(map.config.datasets).length > 0;\n const canFitView = Boolean(map.config.fitToData && hasDatasets);\n const fitViewLabel = canFitView\n ? 'Fit map view to data'\n : 'Fit view unavailable for this map';\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"border-border flex shrink-0 items-center justify-between gap-2 border-b px-3 py-2\">\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <MapIcon className=\"h-4 w-4 shrink-0\" />\n <input\n className=\"min-w-0 flex-1 bg-transparent text-sm outline-none\"\n value={caption ?? map.title}\n readOnly={readOnly}\n placeholder={map.selectedTable ?? title ?? 'Map caption'}\n onChange={(event) =>\n onCaptionChange?.(event.target.value || undefined)\n }\n />\n </div>\n <div className=\"flex items-center gap-0.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <span\n className=\"inline-flex\"\n tabIndex={canFitView ? undefined : 0}\n aria-label={canFitView ? undefined : fitViewLabel}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n aria-label={fitViewLabel}\n disabled={!canFitView}\n onClick={() => setFitRequestVersion((version) => version + 1)}\n >\n <FocusIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </span>\n </TooltipTrigger>\n <TooltipContent>{fitViewLabel}</TooltipContent>\n </Tooltip>\n <Button\n type=\"button\"\n variant={isSettingsShown ? 'secondary' : 'ghost'}\n size=\"icon\"\n className=\"h-6 w-6\"\n aria-label={\n isSettingsShown ? 'Close map settings' : 'Open map settings'\n }\n onClick={() =>\n isSettingsShown\n ? requestCloseSettingsPanel()\n : requestOpenSettingsPanel()\n }\n >\n <SlidersVerticalIcon className=\"h-3.5 w-3.5\" />\n </Button>\n {headerActions}\n </div>\n </div>\n <div className=\"min-h-0 flex-1\">\n {hasDatasets ? (\n <DeckMapResourceErrorBoundary\n resetKey={map.config}\n onError={(error) =>\n reportMapIssue(mapId, {\n kind: 'render-error',\n message: error.message,\n recoverable: true,\n })\n }\n >\n <DeckMapSurface\n mapId={mapId}\n map={map}\n readOnly={readOnly}\n selected={selected}\n onUpdateMap={(patch) => updateMap(mapId, patch)}\n onReportIssue={(issue) => reportMapIssue(mapId, issue)}\n onClearIssue={(kind) => clearMapIssue(mapId, kind)}\n fitRequestVersion={fitRequestVersion}\n dataAdapter={dataAdapter}\n />\n </DeckMapResourceErrorBoundary>\n ) : (\n <div className=\"flex h-full min-h-[320px] items-center justify-center p-4\">\n <select\n className=\"border-border bg-background rounded border px-3 py-2 text-sm\"\n value={map.selectedTable ?? ''}\n disabled={readOnly}\n onChange={(event) => {\n const table = tables.find(\n (candidate) =>\n getTableIdentity(candidate.table) === event.target.value,\n );\n if (table) handleTableChange(table);\n }}\n >\n <option value=\"\">Select a table</option>\n {tables.map((table) => (\n <option\n key={getTableIdentity(table.table)}\n value={getTableIdentity(table.table)}\n >\n {table.tableName}\n </option>\n ))}\n </select>\n </div>\n )}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { BlockDocumentStatefulBlockCommandType, BlockDocumentStatefulBlockType } from '@sqlrooms/documents';
|
|
2
|
+
import type { DuckDbSliceState } from '@sqlrooms/duckdb';
|
|
3
|
+
import type { DeckMapsSliceState } from './DeckMapsSlice';
|
|
4
|
+
export declare const DECK_MAP_BLOCK_TYPE = "map";
|
|
5
|
+
export declare const DECK_MAP_BLOCK_DEFAULT_TITLE = "Embedded Map";
|
|
6
|
+
export declare const DECK_MAP_BLOCK_DEFAULT_HEIGHT = 560;
|
|
7
|
+
/**
|
|
8
|
+
* Options for configuring Deck map block document registration. Hosts pass
|
|
9
|
+
* these to `createDeckMapBlockDocumentType` / `createDeckMapBlockDocumentCommandType`.
|
|
10
|
+
*/
|
|
11
|
+
export type DeckMapBlockDocumentRegistrationOptions<TState> = {
|
|
12
|
+
/** Product label for the map block (defaults to "Map"). */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Description shown in block pickers. */
|
|
15
|
+
description?: string;
|
|
16
|
+
/** Default caption/title used when ensuring state. */
|
|
17
|
+
defaultTitle?: string;
|
|
18
|
+
/** Default height in pixels for the map block. */
|
|
19
|
+
defaultHeight?: number;
|
|
20
|
+
/** Minimum resizable height in pixels. */
|
|
21
|
+
minHeight?: number;
|
|
22
|
+
/** Maximum resizable height in pixels. */
|
|
23
|
+
maxHeight?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Called after Deck map state is ensured. Hosts can add product-specific
|
|
26
|
+
* side effects; delete/remove stays host-owned.
|
|
27
|
+
*/
|
|
28
|
+
afterEnsureState?: (options: {
|
|
29
|
+
state: TState;
|
|
30
|
+
blockInstanceId: string;
|
|
31
|
+
title: string;
|
|
32
|
+
}) => void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Builds the shared TipTap/UI registration metadata for a Deck map stateful
|
|
36
|
+
* block. Hosts still own renderer maps, delete handlers, and product labels.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createDeckMapBlockDocumentType<TState extends DeckMapsSliceState & DuckDbSliceState>(options: DeckMapBlockDocumentRegistrationOptions<TState> & {
|
|
39
|
+
getState: () => TState;
|
|
40
|
+
}): BlockDocumentStatefulBlockType;
|
|
41
|
+
/**
|
|
42
|
+
* Builds the shared command-type registration for a Deck map stateful block.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createDeckMapBlockDocumentCommandType<TState extends DeckMapsSliceState & DuckDbSliceState>(options?: DeckMapBlockDocumentRegistrationOptions<TState>): BlockDocumentStatefulBlockCommandType<TState>;
|
|
45
|
+
//# sourceMappingURL=blockDocumentRegistration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockDocumentRegistration.d.ts","sourceRoot":"","sources":["../src/blockDocumentRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qCAAqC,EACrC,8BAA8B,EAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAIxD,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAC3D,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD;;;GAGG;AACH,MAAM,MAAM,uCAAuC,CAAC,MAAM,IAAI;IAC5D,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC3B,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,IAAI,CAAC;CACZ,CAAC;AAEF;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,SAAS,kBAAkB,GAAG,gBAAgB,EAEpD,OAAO,EAAE,uCAAuC,CAAC,MAAM,CAAC,GAAG;IACzD,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB,GACA,8BAA8B,CA8ChC;AAED;;GAEG;AACH,wBAAgB,qCAAqC,CACnD,MAAM,SAAS,kBAAkB,GAAG,gBAAgB,EAEpD,OAAO,GAAE,uCAAuC,CAAC,MAAM,CAAM,GAC5D,qCAAqC,CAAC,MAAM,CAAC,CAyB/C"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DeckMapBlockSettings } from './BlockMapSettings';
|
|
2
|
+
import { ensureDeckMapResourceState } from './block';
|
|
3
|
+
export const DECK_MAP_BLOCK_TYPE = 'map';
|
|
4
|
+
export const DECK_MAP_BLOCK_DEFAULT_TITLE = 'Embedded Map';
|
|
5
|
+
export const DECK_MAP_BLOCK_DEFAULT_HEIGHT = 560;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the shared TipTap/UI registration metadata for a Deck map stateful
|
|
8
|
+
* block. Hosts still own renderer maps, delete handlers, and product labels.
|
|
9
|
+
*/
|
|
10
|
+
export function createDeckMapBlockDocumentType(options) {
|
|
11
|
+
const { getState, label = 'Map', description = 'Embedded Deck.gl map', defaultTitle = DECK_MAP_BLOCK_DEFAULT_TITLE, defaultHeight = DECK_MAP_BLOCK_DEFAULT_HEIGHT, minHeight = 360, maxHeight = 1600, afterEnsureState, } = options;
|
|
12
|
+
return {
|
|
13
|
+
blockType: DECK_MAP_BLOCK_TYPE,
|
|
14
|
+
label,
|
|
15
|
+
description,
|
|
16
|
+
resizableHeight: true,
|
|
17
|
+
defaultHeight,
|
|
18
|
+
minHeight,
|
|
19
|
+
maxHeight,
|
|
20
|
+
requireScrollModifier: true,
|
|
21
|
+
scrollHintLabel: 'this map',
|
|
22
|
+
settings: DeckMapBlockSettings,
|
|
23
|
+
hasOwnHeaderActions: true,
|
|
24
|
+
createNode: (blockId) => {
|
|
25
|
+
const state = getState();
|
|
26
|
+
ensureDeckMapResourceState(state, blockId, defaultTitle);
|
|
27
|
+
afterEnsureState?.({
|
|
28
|
+
state,
|
|
29
|
+
blockInstanceId: blockId,
|
|
30
|
+
title: defaultTitle,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
type: 'blockDocumentStatefulBlock',
|
|
34
|
+
attrs: {
|
|
35
|
+
id: blockId,
|
|
36
|
+
blockType: DECK_MAP_BLOCK_TYPE,
|
|
37
|
+
blockInstanceId: blockId,
|
|
38
|
+
ownership: 'owned',
|
|
39
|
+
caption: '',
|
|
40
|
+
height: defaultHeight,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Builds the shared command-type registration for a Deck map stateful block.
|
|
48
|
+
*/
|
|
49
|
+
export function createDeckMapBlockDocumentCommandType(options = {}) {
|
|
50
|
+
const { label = 'Map', description = 'Embedded Deck.gl map', defaultTitle = DECK_MAP_BLOCK_DEFAULT_TITLE, defaultHeight = DECK_MAP_BLOCK_DEFAULT_HEIGHT, afterEnsureState, } = options;
|
|
51
|
+
return {
|
|
52
|
+
blockType: DECK_MAP_BLOCK_TYPE,
|
|
53
|
+
label,
|
|
54
|
+
description,
|
|
55
|
+
defaultTitle,
|
|
56
|
+
defaultHeight,
|
|
57
|
+
ensureState: ({ state, blockInstanceId, title }) => {
|
|
58
|
+
const resolvedTitle = title ?? defaultTitle;
|
|
59
|
+
ensureDeckMapResourceState(state, blockInstanceId, resolvedTitle);
|
|
60
|
+
afterEnsureState?.({
|
|
61
|
+
state,
|
|
62
|
+
blockInstanceId,
|
|
63
|
+
title: resolvedTitle,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=blockDocumentRegistration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockDocumentRegistration.js","sourceRoot":"","sources":["../src/blockDocumentRegistration.ts"],"names":[],"mappings":"AAMA,OAAO,EAAC,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAC,0BAA0B,EAAC,MAAM,SAAS,CAAC;AAEnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AACzC,MAAM,CAAC,MAAM,4BAA4B,GAAG,cAAc,CAAC;AAC3D,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AA8BjD;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAG5C,OAEC;IAED,MAAM,EACJ,QAAQ,EACR,KAAK,GAAG,KAAK,EACb,WAAW,GAAG,sBAAsB,EACpC,YAAY,GAAG,4BAA4B,EAC3C,aAAa,GAAG,6BAA6B,EAC7C,SAAS,GAAG,GAAG,EACf,SAAS,GAAG,IAAI,EAChB,gBAAgB,GACjB,GAAG,OAAO,CAAC;IAEZ,OAAO;QACL,SAAS,EAAE,mBAAmB;QAC9B,KAAK;QACL,WAAW;QACX,eAAe,EAAE,IAAI;QACrB,aAAa;QACb,SAAS;QACT,SAAS;QACT,qBAAqB,EAAE,IAAI;QAC3B,eAAe,EAAE,UAAU;QAC3B,QAAQ,EAAE,oBAAoB;QAC9B,mBAAmB,EAAE,IAAI;QACzB,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE;YACtB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;YACzB,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;YACzD,gBAAgB,EAAE,CAAC;gBACjB,KAAK;gBACL,eAAe,EAAE,OAAO;gBACxB,KAAK,EAAE,YAAY;aACpB,CAAC,CAAC;YAEH,OAAO;gBACL,IAAI,EAAE,4BAA4B;gBAClC,KAAK,EAAE;oBACL,EAAE,EAAE,OAAO;oBACX,SAAS,EAAE,mBAAmB;oBAC9B,eAAe,EAAE,OAAO;oBACxB,SAAS,EAAE,OAAO;oBAClB,OAAO,EAAE,EAAE;oBACX,MAAM,EAAE,aAAa;iBACtB;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qCAAqC,CAGnD,UAA2D,EAAE;IAE7D,MAAM,EACJ,KAAK,GAAG,KAAK,EACb,WAAW,GAAG,sBAAsB,EACpC,YAAY,GAAG,4BAA4B,EAC3C,aAAa,GAAG,6BAA6B,EAC7C,gBAAgB,GACjB,GAAG,OAAO,CAAC;IAEZ,OAAO;QACL,SAAS,EAAE,mBAAmB;QAC9B,KAAK;QACL,WAAW;QACX,YAAY;QACZ,aAAa;QACb,WAAW,EAAE,CAAC,EAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAC,EAAE,EAAE;YAC/C,MAAM,aAAa,GAAG,KAAK,IAAI,YAAY,CAAC;YAC5C,0BAA0B,CAAC,KAAK,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;YAClE,gBAAgB,EAAE,CAAC;gBACjB,KAAK;gBACL,eAAe;gBACf,KAAK,EAAE,aAAa;aACrB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type {\n BlockDocumentStatefulBlockCommandType,\n BlockDocumentStatefulBlockType,\n} from '@sqlrooms/documents';\nimport type {DuckDbSliceState} from '@sqlrooms/duckdb';\nimport type {DeckMapsSliceState} from './DeckMapsSlice';\nimport {DeckMapBlockSettings} from './BlockMapSettings';\nimport {ensureDeckMapResourceState} from './block';\n\nexport const DECK_MAP_BLOCK_TYPE = 'map';\nexport const DECK_MAP_BLOCK_DEFAULT_TITLE = 'Embedded Map';\nexport const DECK_MAP_BLOCK_DEFAULT_HEIGHT = 560;\n\n/**\n * Options for configuring Deck map block document registration. Hosts pass\n * these to `createDeckMapBlockDocumentType` / `createDeckMapBlockDocumentCommandType`.\n */\nexport type DeckMapBlockDocumentRegistrationOptions<TState> = {\n /** Product label for the map block (defaults to \"Map\"). */\n label?: string;\n /** Description shown in block pickers. */\n description?: string;\n /** Default caption/title used when ensuring state. */\n defaultTitle?: string;\n /** Default height in pixels for the map block. */\n defaultHeight?: number;\n /** Minimum resizable height in pixels. */\n minHeight?: number;\n /** Maximum resizable height in pixels. */\n maxHeight?: number;\n /**\n * Called after Deck map state is ensured. Hosts can add product-specific\n * side effects; delete/remove stays host-owned.\n */\n afterEnsureState?: (options: {\n state: TState;\n blockInstanceId: string;\n title: string;\n }) => void;\n};\n\n/**\n * Builds the shared TipTap/UI registration metadata for a Deck map stateful\n * block. Hosts still own renderer maps, delete handlers, and product labels.\n */\nexport function createDeckMapBlockDocumentType<\n TState extends DeckMapsSliceState & DuckDbSliceState,\n>(\n options: DeckMapBlockDocumentRegistrationOptions<TState> & {\n getState: () => TState;\n },\n): BlockDocumentStatefulBlockType {\n const {\n getState,\n label = 'Map',\n description = 'Embedded Deck.gl map',\n defaultTitle = DECK_MAP_BLOCK_DEFAULT_TITLE,\n defaultHeight = DECK_MAP_BLOCK_DEFAULT_HEIGHT,\n minHeight = 360,\n maxHeight = 1600,\n afterEnsureState,\n } = options;\n\n return {\n blockType: DECK_MAP_BLOCK_TYPE,\n label,\n description,\n resizableHeight: true,\n defaultHeight,\n minHeight,\n maxHeight,\n requireScrollModifier: true,\n scrollHintLabel: 'this map',\n settings: DeckMapBlockSettings,\n hasOwnHeaderActions: true,\n createNode: (blockId) => {\n const state = getState();\n ensureDeckMapResourceState(state, blockId, defaultTitle);\n afterEnsureState?.({\n state,\n blockInstanceId: blockId,\n title: defaultTitle,\n });\n\n return {\n type: 'blockDocumentStatefulBlock',\n attrs: {\n id: blockId,\n blockType: DECK_MAP_BLOCK_TYPE,\n blockInstanceId: blockId,\n ownership: 'owned',\n caption: '',\n height: defaultHeight,\n },\n };\n },\n };\n}\n\n/**\n * Builds the shared command-type registration for a Deck map stateful block.\n */\nexport function createDeckMapBlockDocumentCommandType<\n TState extends DeckMapsSliceState & DuckDbSliceState,\n>(\n options: DeckMapBlockDocumentRegistrationOptions<TState> = {},\n): BlockDocumentStatefulBlockCommandType<TState> {\n const {\n label = 'Map',\n description = 'Embedded Deck.gl map',\n defaultTitle = DECK_MAP_BLOCK_DEFAULT_TITLE,\n defaultHeight = DECK_MAP_BLOCK_DEFAULT_HEIGHT,\n afterEnsureState,\n } = options;\n\n return {\n blockType: DECK_MAP_BLOCK_TYPE,\n label,\n description,\n defaultTitle,\n defaultHeight,\n ensureState: ({state, blockInstanceId, title}) => {\n const resolvedTitle = title ?? defaultTitle;\n ensureDeckMapResourceState(state, blockInstanceId, resolvedTitle);\n afterEnsureState?.({\n state,\n blockInstanceId,\n title: resolvedTitle,\n });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CreateDeckJsonSpecFromDatasetsOptions, DeckJsonMapSpec } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a conservative starter Deck JSON spec from SQLRooms datasets.
|
|
4
|
+
*
|
|
5
|
+
* The helper favors predictable defaults:
|
|
6
|
+
* native point/line/polygon datasets become the matching GeoArrow layer, while
|
|
7
|
+
* mixed or unsupported inputs fall back to `GeoJsonLayer`. Callers can provide
|
|
8
|
+
* semantic hints for special layers such as trips, arcs, H3, or heatmaps.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createDeckJsonSpecFromDatasets(options: CreateDeckJsonSpecFromDatasetsOptions): DeckJsonMapSpec;
|
|
11
|
+
//# sourceMappingURL=createDeckJsonSpecFromDatasets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDeckJsonSpecFromDatasets.d.ts","sourceRoot":"","sources":["../src/createDeckJsonSpecFromDatasets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qCAAqC,EACrC,eAAe,EAEhB,MAAM,SAAS,CAAC;AAuFjB;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,qCAAqC,GAC7C,eAAe,CAcjB"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { toArrowTable } from './datasets/tableAdapter';
|
|
2
|
+
import { prepareDeckDataset } from './prepare/prepareDeckDataset';
|
|
3
|
+
function buildLayerConfig(options) {
|
|
4
|
+
const { datasetId, input, hint } = options;
|
|
5
|
+
return {
|
|
6
|
+
dataset: datasetId,
|
|
7
|
+
geometryColumn: input.geometryColumn,
|
|
8
|
+
geometryEncodingHint: input.geometryEncodingHint,
|
|
9
|
+
sourceGeometryColumn: hint?.sourceGeometryColumn,
|
|
10
|
+
targetGeometryColumn: hint?.targetGeometryColumn,
|
|
11
|
+
timestampColumn: hint?.timestampColumn,
|
|
12
|
+
hexagonColumn: hint?.hexagonColumn,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function resolveExplicitLayerType(hint) {
|
|
16
|
+
if (hint?.type) {
|
|
17
|
+
return hint.type;
|
|
18
|
+
}
|
|
19
|
+
if (hint?.prefer === 'heatmap') {
|
|
20
|
+
return 'GeoArrowHeatmapLayer';
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
function isArrowTableDatasetInput(input) {
|
|
25
|
+
return Boolean(input && typeof input === 'object' && 'arrowTable' in input);
|
|
26
|
+
}
|
|
27
|
+
function chooseDefaultLayerType(datasetId, input, hint) {
|
|
28
|
+
const explicitType = resolveExplicitLayerType(hint);
|
|
29
|
+
if (explicitType) {
|
|
30
|
+
return explicitType;
|
|
31
|
+
}
|
|
32
|
+
if (!isArrowTableDatasetInput(input) || !input.arrowTable) {
|
|
33
|
+
return 'GeoJsonLayer';
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const prepared = prepareDeckDataset({
|
|
37
|
+
datasetId,
|
|
38
|
+
table: toArrowTable(input.arrowTable),
|
|
39
|
+
geometryColumn: input.geometryColumn,
|
|
40
|
+
geometryEncodingHint: input.geometryEncodingHint,
|
|
41
|
+
});
|
|
42
|
+
const resolved = prepared.resolveGeometry();
|
|
43
|
+
switch (resolved.encoding) {
|
|
44
|
+
case 'geoarrow.point':
|
|
45
|
+
case 'geoarrow.multipoint':
|
|
46
|
+
return hint?.prefer === 'heatmap'
|
|
47
|
+
? 'GeoArrowHeatmapLayer'
|
|
48
|
+
: 'GeoArrowScatterplotLayer';
|
|
49
|
+
case 'geoarrow.linestring':
|
|
50
|
+
case 'geoarrow.multilinestring':
|
|
51
|
+
return 'GeoArrowPathLayer';
|
|
52
|
+
case 'geoarrow.polygon':
|
|
53
|
+
case 'geoarrow.multipolygon':
|
|
54
|
+
return 'GeoArrowPolygonLayer';
|
|
55
|
+
default:
|
|
56
|
+
return 'GeoJsonLayer';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return 'GeoJsonLayer';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Generate a conservative starter Deck JSON spec from SQLRooms datasets.
|
|
65
|
+
*
|
|
66
|
+
* The helper favors predictable defaults:
|
|
67
|
+
* native point/line/polygon datasets become the matching GeoArrow layer, while
|
|
68
|
+
* mixed or unsupported inputs fall back to `GeoJsonLayer`. Callers can provide
|
|
69
|
+
* semantic hints for special layers such as trips, arcs, H3, or heatmaps.
|
|
70
|
+
*/
|
|
71
|
+
export function createDeckJsonSpecFromDatasets(options) {
|
|
72
|
+
const { datasets, hints } = options;
|
|
73
|
+
return {
|
|
74
|
+
layers: Object.entries(datasets).map(([datasetId, input]) => ({
|
|
75
|
+
'@@type': chooseDefaultLayerType(datasetId, input, hints?.[datasetId]),
|
|
76
|
+
id: datasetId,
|
|
77
|
+
_sqlroomsBinding: buildLayerConfig({
|
|
78
|
+
datasetId,
|
|
79
|
+
input,
|
|
80
|
+
hint: hints?.[datasetId],
|
|
81
|
+
}),
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=createDeckJsonSpecFromDatasets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDeckJsonSpecFromDatasets.js","sourceRoot":"","sources":["../src/createDeckJsonSpecFromDatasets.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n DeckArrowTableDatasetInput,\n CreateDeckJsonSpecFromDatasetsOptions,\n DeckJsonMapSpec,\n DeckJsonSpecDatasetHint,\n} from './types';\nimport type {GeometryEncodingHint} from './prepare/types';\nimport {toArrowTable} from './datasets/tableAdapter';\nimport {prepareDeckDataset} from './prepare/prepareDeckDataset';\n\nfunction buildLayerConfig(options: {\n datasetId: string;\n input: {geometryColumn?: string; geometryEncodingHint?: GeometryEncodingHint};\n hint?: DeckJsonSpecDatasetHint;\n}) {\n const {datasetId, input, hint} = options;\n\n return {\n dataset: datasetId,\n geometryColumn: input.geometryColumn,\n geometryEncodingHint: input.geometryEncodingHint,\n sourceGeometryColumn: hint?.sourceGeometryColumn,\n targetGeometryColumn: hint?.targetGeometryColumn,\n timestampColumn: hint?.timestampColumn,\n hexagonColumn: hint?.hexagonColumn,\n };\n}\n\nfunction resolveExplicitLayerType(hint?: DeckJsonSpecDatasetHint) {\n if (hint?.type) {\n return hint.type;\n }\n\n if (hint?.prefer === 'heatmap') {\n return 'GeoArrowHeatmapLayer' as const;\n }\n\n return undefined;\n}\n\nfunction isArrowTableDatasetInput(\n input: unknown,\n): input is DeckArrowTableDatasetInput {\n return Boolean(input && typeof input === 'object' && 'arrowTable' in input);\n}\n\nfunction chooseDefaultLayerType(\n datasetId: string,\n input: {\n geometryColumn?: string;\n geometryEncodingHint?: GeometryEncodingHint;\n },\n hint?: DeckJsonSpecDatasetHint,\n) {\n const explicitType = resolveExplicitLayerType(hint);\n if (explicitType) {\n return explicitType;\n }\n\n if (!isArrowTableDatasetInput(input) || !input.arrowTable) {\n return 'GeoJsonLayer' as const;\n }\n\n try {\n const prepared = prepareDeckDataset({\n datasetId,\n table: toArrowTable(input.arrowTable),\n geometryColumn: input.geometryColumn,\n geometryEncodingHint: input.geometryEncodingHint,\n });\n const resolved = prepared.resolveGeometry();\n\n switch (resolved.encoding) {\n case 'geoarrow.point':\n case 'geoarrow.multipoint':\n return hint?.prefer === 'heatmap'\n ? ('GeoArrowHeatmapLayer' as const)\n : ('GeoArrowScatterplotLayer' as const);\n case 'geoarrow.linestring':\n case 'geoarrow.multilinestring':\n return 'GeoArrowPathLayer' as const;\n case 'geoarrow.polygon':\n case 'geoarrow.multipolygon':\n return 'GeoArrowPolygonLayer' as const;\n default:\n return 'GeoJsonLayer' as const;\n }\n } catch {\n return 'GeoJsonLayer' as const;\n }\n}\n\n/**\n * Generate a conservative starter Deck JSON spec from SQLRooms datasets.\n *\n * The helper favors predictable defaults:\n * native point/line/polygon datasets become the matching GeoArrow layer, while\n * mixed or unsupported inputs fall back to `GeoJsonLayer`. Callers can provide\n * semantic hints for special layers such as trips, arcs, H3, or heatmaps.\n */\nexport function createDeckJsonSpecFromDatasets(\n options: CreateDeckJsonSpecFromDatasetsOptions,\n): DeckJsonMapSpec {\n const {datasets, hints} = options;\n\n return {\n layers: Object.entries(datasets).map(([datasetId, input]) => ({\n '@@type': chooseDefaultLayerType(datasetId, input, hints?.[datasetId]),\n id: datasetId,\n _sqlroomsBinding: buildLayerConfig({\n datasetId,\n input,\n hint: hints?.[datasetId],\n }),\n })),\n };\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { DeckMapResource } from './DeckMapsSlice';
|
|
2
|
+
import type { DeckMapConfig } from './mapConfig';
|
|
3
|
+
/**
|
|
4
|
+
* Host callbacks used to coordinate a durable Deck map resource with its block
|
|
5
|
+
* document container, table registry, and optional config preparation.
|
|
6
|
+
*/
|
|
7
|
+
export type CreateOrUpdateDeckMapResourceHost = {
|
|
8
|
+
ensureBlockDocument: (blockDocumentId: string) => void;
|
|
9
|
+
findMapBlock: (blockDocumentId: string, mapId: string) => {
|
|
10
|
+
blockId: string;
|
|
11
|
+
mapId: string;
|
|
12
|
+
caption?: string;
|
|
13
|
+
} | undefined;
|
|
14
|
+
findMap: (mapId: string) => DeckMapResource | undefined;
|
|
15
|
+
createMapBlock: (options: {
|
|
16
|
+
blockDocumentId: string;
|
|
17
|
+
mapId: string;
|
|
18
|
+
title: string;
|
|
19
|
+
caption?: string;
|
|
20
|
+
intent?: string;
|
|
21
|
+
height?: number;
|
|
22
|
+
}) => Promise<{
|
|
23
|
+
blockId: string;
|
|
24
|
+
mapId: string;
|
|
25
|
+
}>;
|
|
26
|
+
updateBlockMetadata: (options: {
|
|
27
|
+
blockDocumentId: string;
|
|
28
|
+
blockId: string;
|
|
29
|
+
caption?: string;
|
|
30
|
+
intent?: string;
|
|
31
|
+
height?: number;
|
|
32
|
+
}) => void | Promise<void>;
|
|
33
|
+
ensureMap: (mapId: string, title: string) => void;
|
|
34
|
+
writeMap: (options: {
|
|
35
|
+
mapId: string;
|
|
36
|
+
title: string;
|
|
37
|
+
config: DeckMapConfig;
|
|
38
|
+
selectedTable?: string;
|
|
39
|
+
}) => void | Promise<void>;
|
|
40
|
+
findTable: (tableName: string) => {
|
|
41
|
+
tableIdentity: string;
|
|
42
|
+
} | undefined;
|
|
43
|
+
prepareConfig?: (options: {
|
|
44
|
+
config: DeckMapConfig;
|
|
45
|
+
existingMapConfig?: DeckMapConfig;
|
|
46
|
+
tableName?: string;
|
|
47
|
+
replaceLayers?: boolean;
|
|
48
|
+
replaceDatasets?: boolean;
|
|
49
|
+
}) => DeckMapConfig | Promise<DeckMapConfig>;
|
|
50
|
+
};
|
|
51
|
+
/** Input for creating or updating a Deck map resource and its owning block. */
|
|
52
|
+
export type CreateOrUpdateDeckMapResourceParams = {
|
|
53
|
+
blockDocumentId: string;
|
|
54
|
+
config: DeckMapConfig;
|
|
55
|
+
mapId?: string;
|
|
56
|
+
tableName?: string;
|
|
57
|
+
title?: string;
|
|
58
|
+
caption?: string;
|
|
59
|
+
intent?: string;
|
|
60
|
+
height?: number;
|
|
61
|
+
/** Treat `config.spec.layers` as the complete replacement layer list. */
|
|
62
|
+
replaceLayers?: boolean;
|
|
63
|
+
/** Treat `config.datasets` as the complete replacement dataset registry. */
|
|
64
|
+
replaceDatasets?: boolean;
|
|
65
|
+
requireTableNameForSqlOnlyUpdate?: boolean;
|
|
66
|
+
artifactLabel?: string;
|
|
67
|
+
createMapId?: () => string;
|
|
68
|
+
missingMapBlockBehavior?: 'throw' | 'create';
|
|
69
|
+
};
|
|
70
|
+
/** Result identities and resolved table selection from a map resource write. */
|
|
71
|
+
export type CreateOrUpdateDeckMapResourceResult = {
|
|
72
|
+
blockDocumentId: string;
|
|
73
|
+
blockId: string;
|
|
74
|
+
mapId: string;
|
|
75
|
+
selectedTable?: string;
|
|
76
|
+
message: string;
|
|
77
|
+
created: boolean;
|
|
78
|
+
};
|
|
79
|
+
/** Resource-native worksheet map orchestration with metadata-after-map-write ordering. */
|
|
80
|
+
export declare function createOrUpdateDeckMapResource(host: CreateOrUpdateDeckMapResourceHost, params: CreateOrUpdateDeckMapResourceParams): Promise<CreateOrUpdateDeckMapResourceResult>;
|
|
81
|
+
//# sourceMappingURL=createOrUpdateDeckMapResource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createOrUpdateDeckMapResource.d.ts","sourceRoot":"","sources":["../src/createOrUpdateDeckMapResource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getFirstDatasetSourceTableName, hasSqlOnlyDatasetSource, } from './datasetSourceUtils';
|
|
2
|
+
import { assertDeckMapResourceConfig } from './mapResourceAuthoring';
|
|
3
|
+
/** Resource-native worksheet map orchestration with metadata-after-map-write ordering. */
|
|
4
|
+
export async function createOrUpdateDeckMapResource(host, params) {
|
|
5
|
+
const artifactLabel = params.artifactLabel ?? 'block document';
|
|
6
|
+
host.ensureBlockDocument(params.blockDocumentId);
|
|
7
|
+
const existingBlock = params.mapId
|
|
8
|
+
? host.findMapBlock(params.blockDocumentId, params.mapId)
|
|
9
|
+
: undefined;
|
|
10
|
+
const missingBehavior = params.missingMapBlockBehavior ?? 'throw';
|
|
11
|
+
if (params.mapId && !existingBlock && missingBehavior === 'throw') {
|
|
12
|
+
throw new Error(`${artifactLabel} map block ${params.mapId} was not found in ${params.blockDocumentId}`);
|
|
13
|
+
}
|
|
14
|
+
const mapId = existingBlock?.mapId ?? params.mapId ?? params.createMapId?.();
|
|
15
|
+
if (!mapId)
|
|
16
|
+
throw new Error('mapId is required when creating a map block');
|
|
17
|
+
const existingMap = host.findMap(mapId);
|
|
18
|
+
const requestedTable = params.tableName ?? getFirstDatasetSourceTableName(params.config);
|
|
19
|
+
const preparedConfig = host.prepareConfig
|
|
20
|
+
? await host.prepareConfig({
|
|
21
|
+
config: params.config,
|
|
22
|
+
existingMapConfig: existingMap?.config,
|
|
23
|
+
tableName: requestedTable,
|
|
24
|
+
replaceLayers: params.replaceLayers,
|
|
25
|
+
replaceDatasets: params.replaceDatasets,
|
|
26
|
+
})
|
|
27
|
+
: params.config;
|
|
28
|
+
assertDeckMapResourceConfig(preparedConfig);
|
|
29
|
+
const tableName = requestedTable ?? getFirstDatasetSourceTableName(preparedConfig);
|
|
30
|
+
if ((params.requireTableNameForSqlOnlyUpdate ?? true) &&
|
|
31
|
+
existingBlock &&
|
|
32
|
+
!tableName &&
|
|
33
|
+
hasSqlOnlyDatasetSource(params.config)) {
|
|
34
|
+
throw new Error(`tableName is required when updating a ${artifactLabel} map block with SQL-only dataset sources.`);
|
|
35
|
+
}
|
|
36
|
+
const table = tableName ? host.findTable(tableName) : undefined;
|
|
37
|
+
if (tableName && !table)
|
|
38
|
+
throw new Error(`Table "${tableName}" was not found.`);
|
|
39
|
+
const caption = params.caption?.trim() ||
|
|
40
|
+
params.title?.trim() ||
|
|
41
|
+
existingBlock?.caption?.trim() ||
|
|
42
|
+
existingMap?.title?.trim() ||
|
|
43
|
+
'Map';
|
|
44
|
+
const title = params.title?.trim() || caption;
|
|
45
|
+
const created = !existingBlock;
|
|
46
|
+
const block = existingBlock ??
|
|
47
|
+
(await host.createMapBlock({
|
|
48
|
+
blockDocumentId: params.blockDocumentId,
|
|
49
|
+
mapId,
|
|
50
|
+
title,
|
|
51
|
+
caption,
|
|
52
|
+
intent: params.intent,
|
|
53
|
+
height: params.height,
|
|
54
|
+
}));
|
|
55
|
+
host.ensureMap(block.mapId, title);
|
|
56
|
+
await host.writeMap({
|
|
57
|
+
mapId: block.mapId,
|
|
58
|
+
title,
|
|
59
|
+
config: preparedConfig,
|
|
60
|
+
selectedTable: table?.tableIdentity,
|
|
61
|
+
});
|
|
62
|
+
if (existingBlock) {
|
|
63
|
+
await host.updateBlockMetadata({
|
|
64
|
+
blockDocumentId: params.blockDocumentId,
|
|
65
|
+
blockId: block.blockId,
|
|
66
|
+
caption,
|
|
67
|
+
intent: params.intent,
|
|
68
|
+
height: params.height,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
blockDocumentId: params.blockDocumentId,
|
|
73
|
+
blockId: block.blockId,
|
|
74
|
+
mapId: block.mapId,
|
|
75
|
+
selectedTable: table?.tableIdentity,
|
|
76
|
+
created,
|
|
77
|
+
message: created
|
|
78
|
+
? `Added ${artifactLabel} map block "${title}".`
|
|
79
|
+
: `Updated ${artifactLabel} map block "${title}".`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=createOrUpdateDeckMapResource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createOrUpdateDeckMapResource.js","sourceRoot":"","sources":["../src/createOrUpdateDeckMapResource.ts"],"names":[],"mappings":"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","sourcesContent":["import type {DeckMapResource} from './DeckMapsSlice';\nimport type {DeckMapConfig} from './mapConfig';\nimport {\n getFirstDatasetSourceTableName,\n hasSqlOnlyDatasetSource,\n} from './datasetSourceUtils';\nimport {assertDeckMapResourceConfig} from './mapResourceAuthoring';\n\n/**\n * Host callbacks used to coordinate a durable Deck map resource with its block\n * document container, table registry, and optional config preparation.\n */\nexport type CreateOrUpdateDeckMapResourceHost = {\n ensureBlockDocument: (blockDocumentId: string) => void;\n findMapBlock: (\n blockDocumentId: string,\n mapId: string,\n ) => {blockId: string; mapId: string; caption?: string} | undefined;\n findMap: (mapId: string) => DeckMapResource | undefined;\n createMapBlock: (options: {\n blockDocumentId: string;\n mapId: string;\n title: string;\n caption?: string;\n intent?: string;\n height?: number;\n }) => Promise<{blockId: string; mapId: string}>;\n updateBlockMetadata: (options: {\n blockDocumentId: string;\n blockId: string;\n caption?: string;\n intent?: string;\n height?: number;\n }) => void | Promise<void>;\n ensureMap: (mapId: string, title: string) => void;\n writeMap: (options: {\n mapId: string;\n title: string;\n config: DeckMapConfig;\n selectedTable?: string;\n }) => void | Promise<void>;\n findTable: (tableName: string) => {tableIdentity: string} | undefined;\n prepareConfig?: (options: {\n config: DeckMapConfig;\n existingMapConfig?: DeckMapConfig;\n tableName?: string;\n replaceLayers?: boolean;\n replaceDatasets?: boolean;\n }) => DeckMapConfig | Promise<DeckMapConfig>;\n};\n\n/** Input for creating or updating a Deck map resource and its owning block. */\nexport type CreateOrUpdateDeckMapResourceParams = {\n blockDocumentId: string;\n config: DeckMapConfig;\n mapId?: string;\n tableName?: string;\n title?: string;\n caption?: string;\n intent?: string;\n height?: number;\n /** Treat `config.spec.layers` as the complete replacement layer list. */\n replaceLayers?: boolean;\n /** Treat `config.datasets` as the complete replacement dataset registry. */\n replaceDatasets?: boolean;\n requireTableNameForSqlOnlyUpdate?: boolean;\n artifactLabel?: string;\n createMapId?: () => string;\n missingMapBlockBehavior?: 'throw' | 'create';\n};\n\n/** Result identities and resolved table selection from a map resource write. */\nexport type CreateOrUpdateDeckMapResourceResult = {\n blockDocumentId: string;\n blockId: string;\n mapId: string;\n selectedTable?: string;\n message: string;\n created: boolean;\n};\n\n/** Resource-native worksheet map orchestration with metadata-after-map-write ordering. */\nexport async function createOrUpdateDeckMapResource(\n host: CreateOrUpdateDeckMapResourceHost,\n params: CreateOrUpdateDeckMapResourceParams,\n): Promise<CreateOrUpdateDeckMapResourceResult> {\n const artifactLabel = params.artifactLabel ?? 'block document';\n host.ensureBlockDocument(params.blockDocumentId);\n const existingBlock = params.mapId\n ? host.findMapBlock(params.blockDocumentId, params.mapId)\n : undefined;\n const missingBehavior = params.missingMapBlockBehavior ?? 'throw';\n if (params.mapId && !existingBlock && missingBehavior === 'throw') {\n throw new Error(\n `${artifactLabel} map block ${params.mapId} was not found in ${params.blockDocumentId}`,\n );\n }\n const mapId = existingBlock?.mapId ?? params.mapId ?? params.createMapId?.();\n if (!mapId) throw new Error('mapId is required when creating a map block');\n\n const existingMap = host.findMap(mapId);\n const requestedTable =\n params.tableName ?? getFirstDatasetSourceTableName(params.config);\n const preparedConfig = host.prepareConfig\n ? await host.prepareConfig({\n config: params.config,\n existingMapConfig: existingMap?.config,\n tableName: requestedTable,\n replaceLayers: params.replaceLayers,\n replaceDatasets: params.replaceDatasets,\n })\n : params.config;\n assertDeckMapResourceConfig(preparedConfig);\n const tableName =\n requestedTable ?? getFirstDatasetSourceTableName(preparedConfig);\n if (\n (params.requireTableNameForSqlOnlyUpdate ?? true) &&\n existingBlock &&\n !tableName &&\n hasSqlOnlyDatasetSource(params.config)\n ) {\n throw new Error(\n `tableName is required when updating a ${artifactLabel} map block with SQL-only dataset sources.`,\n );\n }\n const table = tableName ? host.findTable(tableName) : undefined;\n if (tableName && !table)\n throw new Error(`Table \"${tableName}\" was not found.`);\n\n const caption =\n params.caption?.trim() ||\n params.title?.trim() ||\n existingBlock?.caption?.trim() ||\n existingMap?.title?.trim() ||\n 'Map';\n const title = params.title?.trim() || caption;\n const created = !existingBlock;\n const block =\n existingBlock ??\n (await host.createMapBlock({\n blockDocumentId: params.blockDocumentId,\n mapId,\n title,\n caption,\n intent: params.intent,\n height: params.height,\n }));\n host.ensureMap(block.mapId, title);\n await host.writeMap({\n mapId: block.mapId,\n title,\n config: preparedConfig,\n selectedTable: table?.tableIdentity,\n });\n if (existingBlock) {\n await host.updateBlockMetadata({\n blockDocumentId: params.blockDocumentId,\n blockId: block.blockId,\n caption,\n intent: params.intent,\n height: params.height,\n });\n }\n return {\n blockDocumentId: params.blockDocumentId,\n blockId: block.blockId,\n mapId: block.mapId,\n selectedTable: table?.tableIdentity,\n created,\n message: created\n ? `Added ${artifactLabel} map block \"${title}\".`\n : `Updated ${artifactLabel} map block \"${title}\".`,\n };\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type MosaicDashboardPanelRenderer } from '@sqlrooms/mosaic';
|
|
2
|
+
import { createDeckMapBoundsQuery } from './useDeckMapFitToBounds';
|
|
3
|
+
export { createDeckMapBoundsQuery };
|
|
4
|
+
export declare const deckMapDashboardPanelRenderer: MosaicDashboardPanelRenderer;
|
|
5
|
+
export declare const deckMapDashboardAddPanelAction: import('@sqlrooms/mosaic').MosaicDashboardAddPanelAction;
|
|
6
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,4BAA4B,EASlC,MAAM,kBAAkB,CAAC;AAwB1B,OAAO,EAGL,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,wBAAwB,EAAC,CAAC;AAimBlC,eAAO,MAAM,6BAA6B,EAAE,4BAK3C,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,OAAO,kBAAkB,EAAE,6BAuBrE,CAAC"}
|