@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.
Files changed (154) hide show
  1. package/README.md +193 -35
  2. package/dist/BlockMapSettings.d.ts.map +1 -1
  3. package/dist/BlockMapSettings.js +4 -16
  4. package/dist/BlockMapSettings.js.map +1 -1
  5. package/dist/DashboardMapSettings.d.ts.map +1 -1
  6. package/dist/DashboardMapSettings.js +7 -10
  7. package/dist/DashboardMapSettings.js.map +1 -1
  8. package/dist/DeckJsonMap.d.ts.map +1 -1
  9. package/dist/DeckJsonMap.js +75 -23
  10. package/dist/DeckJsonMap.js.map +1 -1
  11. package/dist/DeckJsonMapSpec.d.ts +41 -0
  12. package/dist/DeckJsonMapSpec.d.ts.map +1 -1
  13. package/dist/DeckJsonMapSpec.js +2 -0
  14. package/dist/DeckJsonMapSpec.js.map +1 -1
  15. package/dist/DeckMapBasemapSelect.d.ts +9 -0
  16. package/dist/DeckMapBasemapSelect.d.ts.map +1 -0
  17. package/dist/DeckMapBasemapSelect.js +20 -0
  18. package/dist/DeckMapBasemapSelect.js.map +1 -0
  19. package/dist/DeckMapDefaultStylesProvider.d.ts +13 -19
  20. package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
  21. package/dist/DeckMapDefaultStylesProvider.js +11 -18
  22. package/dist/DeckMapDefaultStylesProvider.js.map +1 -1
  23. package/dist/DeckMapSurface.d.ts +1 -1
  24. package/dist/DeckMapSurface.js +1 -1
  25. package/dist/DeckMapSurface.js.map +1 -1
  26. package/dist/DeckMapsSlice.d.ts +5 -0
  27. package/dist/DeckMapsSlice.d.ts.map +1 -1
  28. package/dist/DeckMapsSlice.js +6 -3
  29. package/dist/DeckMapsSlice.js.map +1 -1
  30. package/dist/MapSettings.d.ts +14 -0
  31. package/dist/MapSettings.d.ts.map +1 -1
  32. package/dist/MapSettings.js +548 -192
  33. package/dist/MapSettings.js.map +1 -1
  34. package/dist/MapSettingsControls.d.ts +8 -1
  35. package/dist/MapSettingsControls.d.ts.map +1 -1
  36. package/dist/MapSettingsControls.js +24 -2
  37. package/dist/MapSettingsControls.js.map +1 -1
  38. package/dist/ai.d.ts.map +1 -1
  39. package/dist/ai.js +20 -12
  40. package/dist/ai.js.map +1 -1
  41. package/dist/aiNormalize.d.ts.map +1 -1
  42. package/dist/aiNormalize.js +2 -1
  43. package/dist/aiNormalize.js.map +1 -1
  44. package/dist/basemap.d.ts +23 -0
  45. package/dist/basemap.d.ts.map +1 -0
  46. package/dist/basemap.js +23 -0
  47. package/dist/basemap.js.map +1 -0
  48. package/dist/block.d.ts +1 -1
  49. package/dist/block.d.ts.map +1 -1
  50. package/dist/block.js +13 -9
  51. package/dist/block.js.map +1 -1
  52. package/dist/createOrUpdateDeckMapResource.d.ts +6 -2
  53. package/dist/createOrUpdateDeckMapResource.d.ts.map +1 -1
  54. package/dist/createOrUpdateDeckMapResource.js +57 -4
  55. package/dist/createOrUpdateDeckMapResource.js.map +1 -1
  56. package/dist/datasets/PreparedDatasetStore.d.ts +3 -4
  57. package/dist/datasets/PreparedDatasetStore.d.ts.map +1 -1
  58. package/dist/datasets/PreparedDatasetStore.js +4 -8
  59. package/dist/datasets/PreparedDatasetStore.js.map +1 -1
  60. package/dist/datasets/helpers.d.ts +39 -2
  61. package/dist/datasets/helpers.d.ts.map +1 -1
  62. package/dist/datasets/helpers.js +86 -3
  63. package/dist/datasets/helpers.js.map +1 -1
  64. package/dist/datasets/usePreparedDatasetStates.d.ts.map +1 -1
  65. package/dist/datasets/usePreparedDatasetStates.js +12 -8
  66. package/dist/datasets/usePreparedDatasetStates.js.map +1 -1
  67. package/dist/index.d.ts +6 -3
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +5 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/json/colorScaleFunction.d.ts +12 -4
  72. package/dist/json/colorScaleFunction.d.ts.map +1 -1
  73. package/dist/json/colorScaleFunction.js.map +1 -1
  74. package/dist/json/compileColorScale.d.ts +3 -2
  75. package/dist/json/compileColorScale.d.ts.map +1 -1
  76. package/dist/json/compileColorScale.js +16 -1
  77. package/dist/json/compileColorScale.js.map +1 -1
  78. package/dist/json/createDeckJsonConfiguration.d.ts.map +1 -1
  79. package/dist/json/createDeckJsonConfiguration.js +235 -175
  80. package/dist/json/createDeckJsonConfiguration.js.map +1 -1
  81. package/dist/json/defaultClasses.d.ts.map +1 -1
  82. package/dist/json/defaultClasses.js +3 -3
  83. package/dist/json/defaultClasses.js.map +1 -1
  84. package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
  85. package/dist/json/extractColorScaleLegends.js +41 -26
  86. package/dist/json/extractColorScaleLegends.js.map +1 -1
  87. package/dist/json/heatmapDefaults.d.ts +17 -7
  88. package/dist/json/heatmapDefaults.d.ts.map +1 -1
  89. package/dist/json/heatmapDefaults.js +54 -12
  90. package/dist/json/heatmapDefaults.js.map +1 -1
  91. package/dist/json/layers/DeckHeatmapLayer.d.ts +32 -0
  92. package/dist/json/layers/DeckHeatmapLayer.d.ts.map +1 -0
  93. package/dist/json/layers/DeckHeatmapLayer.js +69 -0
  94. package/dist/json/layers/DeckHeatmapLayer.js.map +1 -0
  95. package/dist/json/layers/index.d.ts +1 -0
  96. package/dist/json/layers/index.d.ts.map +1 -1
  97. package/dist/json/layers/index.js +1 -0
  98. package/dist/json/layers/index.js.map +1 -1
  99. package/dist/json/rewriteGeoArrowAccessors.d.ts.map +1 -1
  100. package/dist/json/rewriteGeoArrowAccessors.js +13 -5
  101. package/dist/json/rewriteGeoArrowAccessors.js.map +1 -1
  102. package/dist/json/scaleFunction.d.ts +5 -8
  103. package/dist/json/scaleFunction.d.ts.map +1 -1
  104. package/dist/json/scaleFunction.js +30 -5
  105. package/dist/json/scaleFunction.js.map +1 -1
  106. package/dist/mapAiConfig.d.ts +6 -0
  107. package/dist/mapAiConfig.d.ts.map +1 -1
  108. package/dist/mapAiConfig.js +7 -0
  109. package/dist/mapAiConfig.js.map +1 -1
  110. package/dist/mapAiSharedInstructions.d.ts +1 -1
  111. package/dist/mapAiSharedInstructions.d.ts.map +1 -1
  112. package/dist/mapAiSharedInstructions.js +4 -3
  113. package/dist/mapAiSharedInstructions.js.map +1 -1
  114. package/dist/mapConfig.d.ts +6 -1
  115. package/dist/mapConfig.d.ts.map +1 -1
  116. package/dist/mapConfig.js +28 -3
  117. package/dist/mapConfig.js.map +1 -1
  118. package/dist/mapConfigUtils.d.ts +22 -0
  119. package/dist/mapConfigUtils.d.ts.map +1 -1
  120. package/dist/mapConfigUtils.js +152 -5
  121. package/dist/mapConfigUtils.js.map +1 -1
  122. package/dist/mapLayerConfigUtils.d.ts +55 -0
  123. package/dist/mapLayerConfigUtils.d.ts.map +1 -1
  124. package/dist/mapLayerConfigUtils.js +222 -11
  125. package/dist/mapLayerConfigUtils.js.map +1 -1
  126. package/dist/mapResourceAuthoring.d.ts +1 -1
  127. package/dist/mapResourceAuthoring.d.ts.map +1 -1
  128. package/dist/mapResourceAuthoring.js +14 -7
  129. package/dist/mapResourceAuthoring.js.map +1 -1
  130. package/dist/mapStyles.d.ts +16 -0
  131. package/dist/mapStyles.d.ts.map +1 -0
  132. package/dist/mapStyles.js +32 -0
  133. package/dist/mapStyles.js.map +1 -0
  134. package/dist/prepare/prepareDeckDataset.d.ts.map +1 -1
  135. package/dist/prepare/prepareDeckDataset.js +1 -0
  136. package/dist/prepare/prepareDeckDataset.js.map +1 -1
  137. package/dist/prepare/types.d.ts +3 -0
  138. package/dist/prepare/types.d.ts.map +1 -1
  139. package/dist/prepare/types.js.map +1 -1
  140. package/dist/prepare/wkbDecoder.d.ts.map +1 -1
  141. package/dist/prepare/wkbDecoder.js +62 -16
  142. package/dist/prepare/wkbDecoder.js.map +1 -1
  143. package/dist/prepare/wkbParser.d.ts +2 -0
  144. package/dist/prepare/wkbParser.d.ts.map +1 -1
  145. package/dist/prepare/wkbParser.js +1 -0
  146. package/dist/prepare/wkbParser.js.map +1 -1
  147. package/dist/protomapsStyles.d.ts +18 -0
  148. package/dist/protomapsStyles.d.ts.map +1 -0
  149. package/dist/protomapsStyles.js +38 -0
  150. package/dist/protomapsStyles.js.map +1 -0
  151. package/dist/types.d.ts +13 -0
  152. package/dist/types.d.ts.map +1 -1
  153. package/dist/types.js.map +1 -1
  154. package/package.json +11 -9
@@ -2,13 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { JSONConverter } from '@deck.gl/json';
3
3
  import { MapboxOverlay } from '@deck.gl/mapbox';
4
4
  import { ColorScaleLegend } from '@sqlrooms/color-scales';
5
- import { cn, useTheme } from '@sqlrooms/ui';
5
+ import { useBaseRoomStore } from '@sqlrooms/room-store';
6
+ import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger, useTheme, } from '@sqlrooms/ui';
7
+ import { ChevronRightIcon } from 'lucide-react';
6
8
  import 'maplibre-gl/dist/maplibre-gl.css';
7
- import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
9
+ import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from 'react';
8
10
  import { forwardRef } from 'react';
9
11
  import Map, { useControl } from 'react-map-gl/maplibre';
10
12
  import { DeckJsonMapSpec } from './DeckJsonMapSpec';
11
- import { resolveDeckMapStyle, useDeckMapDefaultStyles, } from './DeckMapDefaultStylesProvider';
13
+ import { resolveDeckMapStyle } from './basemap';
14
+ import { useDeckMapDefaultStyles } from './DeckMapDefaultStylesProvider';
12
15
  import { normalizeDatasets } from './datasets/normalizeDatasets';
13
16
  import { usePreparedDatasetStates } from './datasets/usePreparedDatasetStates';
14
17
  import { createDeckJsonConfiguration } from './json/createDeckJsonConfiguration';
@@ -17,8 +20,8 @@ import { getLayerCompatibility } from './json/layerCompatibility';
17
20
  import { resolveDatasetId } from './json/layerConfig';
18
21
  import { buildDeckMapJumpToOptions } from './mapFit';
19
22
  const DEFAULT_MAP_STYLES = {
20
- light: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
21
- dark: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
23
+ light: 'https://tiles.openfreemap.org/styles/positron',
24
+ dark: 'https://tiles.openfreemap.org/styles/dark',
22
25
  };
23
26
  function parseSpec(spec) {
24
27
  try {
@@ -103,6 +106,14 @@ const TripsTimeControl = ({ currentTime, maxTime, playing, onPlayPause, onSeek }
103
106
  }
104
107
  return (_jsxs("div", { className: "bg-background/90 border-border/70 pointer-events-auto relative flex items-center gap-1.5 rounded-md border px-2 py-1.5 pr-7 shadow-sm backdrop-blur-sm", children: [_jsx("button", { type: "button", onClick: onPlayPause, className: "text-foreground hover:bg-accent flex h-5 w-5 shrink-0 items-center justify-center rounded", title: playing ? 'Pause' : 'Play', children: playing ? (_jsxs("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", children: [_jsx("rect", { x: "1", y: "1", width: "3", height: "8" }), _jsx("rect", { x: "6", y: "1", width: "3", height: "8" })] })) : (_jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "currentColor", children: _jsx("polygon", { points: "2,1 9,5 2,9" }) })) }), _jsx("input", { type: "range", min: 0, max: 1000, value: Math.round(progress * 1000), onChange: (e) => onSeek((Number(e.target.value) / 1000) * maxTime), className: "h-1 w-24 flex-1 cursor-pointer" }), _jsx("button", { type: "button", onClick: () => setCollapsed(true), className: "text-muted-foreground hover:text-foreground absolute top-1.5 right-1.5 flex h-4 w-4 items-center justify-center rounded-sm transition-colors", title: "Collapse", children: _jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", children: _jsx("path", { d: "M1 1L7 7M7 1L1 7", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })] }));
105
108
  };
109
+ function getDeckLayerTypeName(layer) {
110
+ if (!layer || typeof layer !== 'object')
111
+ return '?';
112
+ const ctor = layer.constructor;
113
+ // Prefer static layerName: table-to-RecordBatch adapters all share
114
+ // constructor.name "Adapter", which would miss heatmap ↔ scatterplot swaps.
115
+ return ctor?.layerName ?? ctor?.name ?? '?';
116
+ }
106
117
  // Workaround for deck.gl HeatmapLayer not releasing its WebGL framebuffer
107
118
  // when replaced by another layer type (e.g. switching heatmap → scatterplot).
108
119
  // We detect layer class changes and clear layers for one animation frame,
@@ -112,16 +123,15 @@ function DeckOverlayControl({ interleaved, ...deckProps }) {
112
123
  const overlay = useControl(() => new MapboxOverlay({ interleaved }));
113
124
  const prevLayerKeyRef = useRef('');
114
125
  const [clearing, setClearing] = useState(false);
126
+ const captureStatusRef = useRef(null);
115
127
  const layers = deckProps.layers;
128
+ const captureLayers = useMemo(() => (layers?.flat(Infinity).filter(Boolean) ?? []), [layers]);
129
+ useLayoutEffect(() => {
130
+ // A previous frame no longer represents the current layers.
131
+ captureStatusRef.current?.setAttribute('data-sqlrooms-map-loading', 'true');
132
+ }, [layers, clearing]);
116
133
  const layerKey = Array.isArray(layers)
117
- ? layers
118
- .map((l) => {
119
- if (!l || typeof l !== 'object')
120
- return '?';
121
- const ctor = l.constructor;
122
- return ctor?.name ?? '?';
123
- })
124
- .join(',')
134
+ ? layers.map(getDeckLayerTypeName).join(',')
125
135
  : '';
126
136
  useEffect(() => {
127
137
  if (prevLayerKeyRef.current &&
@@ -133,19 +143,44 @@ function DeckOverlayControl({ interleaved, ...deckProps }) {
133
143
  }, [layerKey, clearing]);
134
144
  useEffect(() => {
135
145
  if (clearing && overlay) {
136
- overlay.setProps({ layers: [] });
146
+ // The temporary empty frame must not advertise capture readiness.
147
+ overlay.setProps({ layers: [], onAfterRender: () => { } });
137
148
  requestAnimationFrame(() => setClearing(false));
138
149
  }
139
150
  }, [clearing, overlay]);
140
- if (!clearing && overlay) {
141
- overlay.setProps(deckProps);
142
- }
143
- return null;
151
+ useLayoutEffect(() => {
152
+ if (clearing || !overlay)
153
+ return;
154
+ overlay.setProps({
155
+ ...deckProps,
156
+ onLoad: () => {
157
+ // The separate canvas is created asynchronously. Mark it once deck
158
+ // initializes, including when the host supplies a custom canvas ID.
159
+ overlay.getCanvas()?.setAttribute('data-sqlrooms-deck-canvas', '');
160
+ if (typeof deckProps.onLoad === 'function')
161
+ deckProps.onLoad();
162
+ },
163
+ onAfterRender: (context) => {
164
+ const loaded = captureLayers.every((layer) => layer.isLoaded);
165
+ captureStatusRef.current?.setAttribute('data-sqlrooms-map-loading', String(!loaded));
166
+ if (typeof deckProps.onAfterRender === 'function') {
167
+ deckProps.onAfterRender(context);
168
+ }
169
+ },
170
+ });
171
+ }, [clearing, overlay, deckProps, captureLayers]);
172
+ return (_jsx("span", { hidden: true, ref: captureStatusRef, "data-sqlrooms-map-loading": "true" }));
173
+ }
174
+ function DeckMapRenderingErrorOverlay({ error }) {
175
+ return (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center p-4", children: _jsx("div", { className: "max-w-sm rounded-md border border-red-200 bg-red-50/95 p-4 text-sm text-red-700 shadow-sm", children: _jsxs(Collapsible, { children: [_jsxs("div", { className: "flex items-start gap-1", children: [_jsx("span", { children: "Map couldn't be rendered" }), _jsx(CollapsibleTrigger, { className: "group mt-0.5 shrink-0 rounded p-0.5 hover:bg-red-100", "aria-label": "Show error details", children: _jsx(ChevronRightIcon, { className: "h-3.5 w-3.5 transition-transform group-data-[state=open]:rotate-90" }) })] }), _jsx(CollapsibleContent, { children: _jsx("pre", { className: "mt-2 max-h-40 overflow-auto font-mono text-xs whitespace-pre-wrap", children: error.message }) })] }) }) }));
144
176
  }
145
- export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, mapStyle, interleaved = true, deckProps, mapProps, showLegends = true, className, children, onDatasetStatesChange, onRenderingError, }, ref) {
177
+ export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, mapStyle, basemapProvider, interleaved = true, deckProps, mapProps, showLegends = true, className, children, onDatasetStatesChange, onRenderingError, }, ref) {
146
178
  const normalizedDatasets = useMemo(() => normalizeDatasets(datasets), [datasets]);
147
- const datasetIds = useMemo(() => Object.keys(normalizedDatasets), [normalizedDatasets]);
179
+ const datasetIdKey = JSON.stringify(Object.keys(normalizedDatasets).sort());
180
+ const datasetIds = useMemo(() => JSON.parse(datasetIdKey), [datasetIdKey]);
148
181
  const datasetStates = usePreparedDatasetStates(normalizedDatasets);
182
+ const [mapReady, setMapReady] = useState(false);
183
+ const datasetsLoading = datasetIds.some((id) => !datasetStates[id] || datasetStates[id]?.status === 'loading');
149
184
  const onDatasetStatesChangeRef = useRef(onDatasetStatesChange);
150
185
  const { spec: parsedSpec, error: specError } = useMemo(() => parseSpec(spec), [spec]);
151
186
  const availableSpec = useMemo(() => parsedSpec
@@ -342,11 +377,19 @@ export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, map
342
377
  }, [extraMapProps]);
343
378
  const { resolvedTheme } = useTheme();
344
379
  const hostDefaultMapStyles = useDeckMapDefaultStyles();
380
+ const roomBasemapProvider = useBaseRoomStore((state) => state.deckMaps?.basemapProvider);
345
381
  const mergedMapProps = {
346
382
  ...extraMapProps,
383
+ // DOM image capture reads the canvas after the render frame has ended.
384
+ // Interleaved deck layers share this buffer with the basemap.
385
+ canvasContextAttributes: {
386
+ preserveDrawingBuffer: true,
387
+ ...mapProps?.canvasContextAttributes,
388
+ },
347
389
  mapStyle: resolveDeckMapStyle({
348
390
  mapStyle,
349
391
  mapPropsMapStyle: mapProps?.mapStyle,
392
+ basemapProvider: basemapProvider ?? roomBasemapProvider,
350
393
  hostDefaultStyles: hostDefaultMapStyles,
351
394
  resolvedTheme,
352
395
  fallbackStyles: DEFAULT_MAP_STYLES,
@@ -358,9 +401,18 @@ export const DeckJsonMap = forwardRef(function DeckJsonMap({ spec, datasets, map
358
401
  datasetIds,
359
402
  datasetStates,
360
403
  })
361
- : [], [availableSpec, datasetIds, datasetStates, showLegends]);
362
- return (_jsxs("div", { className: cn('relative h-full w-full', className), children: [hasRenderingError ? (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center p-4", children: _jsx("div", { className: "max-w-sm rounded-md border border-red-200 bg-red-50/95 p-4 text-sm text-red-700 shadow-sm", children: `Map couldn't be rendered. Check the console for details.` }) })) : null, _jsxs(Map, { ref: mapRef, ...mergedMapProps, ...(initialViewState
404
+ : [], [availableSpec, datasetIds, showLegends, datasetStates]);
405
+ return (_jsxs("div", { className: cn('relative h-full w-full', className), "data-sqlrooms-map-loading": !mapReady || datasetsLoading, children: [finalDeckPropsResult.error ? (_jsx(DeckMapRenderingErrorOverlay, { error: finalDeckPropsResult.error })) : null, _jsxs(Map, { ref: mapRef, ...mergedMapProps, ...(initialViewState
363
406
  ? { initialViewState: initialViewState }
364
- : {}), onLoad: handleMapLoad, style: { width: '100%', height: '100%', ...mapProps?.style }, children: [_jsx(DeckOverlayControl, { interleaved: interleaved, ...overlayDeckProps }), children] }), renderDatasetErrorOverlay(datasetStates), !hasRenderingError && showLegends ? (_jsxs("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10 max-w-56", children: [hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "mb-1", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null, _jsx(ColorScaleLegend, { legends: legends })] })) : hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null] }));
407
+ : {}), onLoad: handleMapLoad, onData: (event) => {
408
+ setMapReady(false);
409
+ mapProps?.onData?.(event);
410
+ }, onMoveStart: (event) => {
411
+ setMapReady(false);
412
+ mapProps?.onMoveStart?.(event);
413
+ }, onRender: (event) => {
414
+ setMapReady(event.target.loaded());
415
+ mapProps?.onRender?.(event);
416
+ }, style: { width: '100%', height: '100%', ...mapProps?.style }, children: [_jsx(DeckOverlayControl, { interleaved: interleaved, ...overlayDeckProps }), children] }), renderDatasetErrorOverlay(datasetStates), !hasRenderingError && showLegends ? (_jsxs("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10 max-w-56", children: [hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "mb-1", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null, _jsx(ColorScaleLegend, { legends: legends })] })) : hasTripsLayer && tripsMaxTimeValue > 0 ? (_jsx("div", { className: "pointer-events-none absolute bottom-2 left-2 z-10", children: _jsx(TripsTimeControl, { currentTime: tripsCurrentTime, maxTime: tripsMaxTimeValue, playing: tripsPlaying, onPlayPause: handleTripsPlayPause, onSeek: handleTripsSeek }) })) : null] }));
365
417
  });
366
418
  //# sourceMappingURL=DeckJsonMap.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeckJsonMap.js","sourceRoot":"","sources":["../src/DeckJsonMap.tsx"],"names":[],"mappings":"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","sourcesContent":["import {JSONConverter} from '@deck.gl/json';\nimport {MapboxOverlay} from '@deck.gl/mapbox';\nimport {ColorScaleLegend} from '@sqlrooms/color-scales';\nimport {cn, ResolvedTheme, useTheme} from '@sqlrooms/ui';\nimport 'maplibre-gl/dist/maplibre-gl.css';\nimport {\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type FC,\n} from 'react';\nimport {forwardRef} from 'react';\nimport Map, {useControl} from 'react-map-gl/maplibre';\nimport {ZodError} from 'zod';\nimport {DeckJsonMapSpec} from './DeckJsonMapSpec';\nimport {\n resolveDeckMapStyle,\n useDeckMapDefaultStyles,\n} from './DeckMapDefaultStylesProvider';\nimport {normalizeDatasets} from './datasets/normalizeDatasets';\nimport {usePreparedDatasetStates} from './datasets/usePreparedDatasetStates';\nimport {createDeckJsonConfiguration} from './json/createDeckJsonConfiguration';\nimport {extractColorScaleLegends} from './json/extractColorScaleLegends';\nimport {getLayerCompatibility} from './json/layerCompatibility';\nimport {resolveDatasetId} from './json/layerConfig';\nimport {buildDeckMapJumpToOptions} from './mapFit';\nimport type {\n DeckJsonMapHandle,\n DeckJsonMapProps,\n PreparedDeckDatasetState,\n} from './types';\n\nconst DEFAULT_MAP_STYLES: Record<ResolvedTheme, string> = {\n light: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',\n dark: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',\n};\n\nfunction parseSpec(spec: DeckJsonMapProps['spec']) {\n try {\n const parsedValue = typeof spec === 'string' ? JSON.parse(spec) : spec;\n const validatedSpec = DeckJsonMapSpec.safeParse(parsedValue);\n if (!validatedSpec.success) {\n return {\n spec: null,\n error: new Error(formatSpecValidationError(validatedSpec.error)),\n };\n }\n\n return {\n spec: validatedSpec.data,\n error: null,\n };\n } catch (error) {\n return {\n spec: null,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\nfunction formatSpecValidationError(error: ZodError) {\n const issues = error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : 'spec';\n return `${path}: ${issue.message}`;\n });\n\n return `Invalid DeckJsonMap spec. ${issues.join('; ')}`;\n}\n\nfunction extractFallbackDeckProps(spec: Record<string, unknown> | null) {\n if (!spec) {\n return {};\n }\n\n const fallbackProps: Record<string, unknown> = {};\n for (const key of ['initialViewState', 'viewState', 'controller']) {\n if (key in spec) {\n fallbackProps[key] = spec[key];\n }\n }\n\n return fallbackProps;\n}\n\nfunction filterUnavailableLayers(\n spec: Record<string, unknown>,\n datasetIds: string[],\n datasetStates: Record<string, PreparedDeckDatasetState>,\n) {\n const layers = Array.isArray(spec.layers) ? spec.layers : [];\n const filteredLayers = layers.filter((layer) => {\n if (!layer || typeof layer !== 'object') {\n return true;\n }\n\n const layerProps = layer as Record<string, unknown>;\n const layerName = String(layerProps['@@type'] ?? '');\n const compatibility = getLayerCompatibility(layerName);\n if (!compatibility) {\n return true;\n }\n\n const datasetId = resolveDatasetId(layerProps, datasetIds);\n if (!datasetId) {\n return true;\n }\n\n const datasetState = datasetStates[datasetId];\n if (!datasetState) {\n return false;\n }\n\n return datasetState.status !== 'error';\n });\n\n return {\n ...spec,\n layers: filteredLayers,\n };\n}\n\nfunction renderDatasetErrorOverlay(\n datasetStates: Record<string, PreparedDeckDatasetState>,\n) {\n const failedDatasets = Object.entries(datasetStates).filter(\n (\n entry,\n ): entry is [\n string,\n Extract<PreparedDeckDatasetState, {status: 'error'}>,\n ] => entry[1].status === 'error',\n );\n\n if (!failedDatasets.length) {\n return null;\n }\n\n return (\n <div className=\"pointer-events-none absolute inset-x-4 top-4 z-10 space-y-2\">\n {failedDatasets.map(([datasetId, state]) => (\n <div\n key={datasetId}\n className=\"rounded-md border border-red-200 bg-red-50/95 px-3 py-2 text-sm text-red-700 shadow-sm\"\n >\n {`Dataset \"${datasetId}\" failed: ${state.error.message}`}\n </div>\n ))}\n </div>\n );\n}\n\nconst TripsTimeControl: FC<{\n currentTime: number;\n maxTime: number;\n playing: boolean;\n onPlayPause: () => void;\n onSeek: (time: number) => void;\n}> = ({currentTime, maxTime, playing, onPlayPause, onSeek}) => {\n const [collapsed, setCollapsed] = useState(false);\n const progress = maxTime > 0 ? currentTime / maxTime : 0;\n\n if (collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"border-border/70 bg-background/90 text-muted-foreground hover:text-foreground pointer-events-auto flex w-fit items-center gap-1 rounded-md border px-2 py-1 text-[10px] leading-none font-medium shadow-sm backdrop-blur-sm transition-colors\"\n >\n Timeline\n </button>\n );\n }\n\n return (\n <div className=\"bg-background/90 border-border/70 pointer-events-auto relative flex items-center gap-1.5 rounded-md border px-2 py-1.5 pr-7 shadow-sm backdrop-blur-sm\">\n <button\n type=\"button\"\n onClick={onPlayPause}\n className=\"text-foreground hover:bg-accent flex h-5 w-5 shrink-0 items-center justify-center rounded\"\n title={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\">\n <rect x=\"1\" y=\"1\" width=\"3\" height=\"8\" />\n <rect x=\"6\" y=\"1\" width=\"3\" height=\"8\" />\n </svg>\n ) : (\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\">\n <polygon points=\"2,1 9,5 2,9\" />\n </svg>\n )}\n </button>\n <input\n type=\"range\"\n min={0}\n max={1000}\n value={Math.round(progress * 1000)}\n onChange={(e) => onSeek((Number(e.target.value) / 1000) * maxTime)}\n className=\"h-1 w-24 flex-1 cursor-pointer\"\n />\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-muted-foreground hover:text-foreground absolute top-1.5 right-1.5 flex h-4 w-4 items-center justify-center rounded-sm transition-colors\"\n title=\"Collapse\"\n >\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\">\n <path\n d=\"M1 1L7 7M7 1L1 7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n </div>\n );\n};\n\n// Workaround for deck.gl HeatmapLayer not releasing its WebGL framebuffer\n// when replaced by another layer type (e.g. switching heatmap → scatterplot).\n// We detect layer class changes and clear layers for one animation frame,\n// giving deck.gl a chance to finalize the old layer's resources before\n// initializing the new one.\nfunction DeckOverlayControl({\n interleaved,\n ...deckProps\n}: {interleaved: boolean} & Record<string, unknown>) {\n const overlay = useControl<MapboxOverlay>(\n () => new MapboxOverlay({interleaved}),\n );\n const prevLayerKeyRef = useRef<string>('');\n const [clearing, setClearing] = useState(false);\n\n const layers = deckProps.layers as unknown[] | undefined;\n const layerKey = Array.isArray(layers)\n ? layers\n .map((l) => {\n if (!l || typeof l !== 'object') return '?';\n const ctor = (l as {constructor?: {name?: string}}).constructor;\n return ctor?.name ?? '?';\n })\n .join(',')\n : '';\n\n useEffect(() => {\n if (\n prevLayerKeyRef.current &&\n prevLayerKeyRef.current !== layerKey &&\n !clearing\n ) {\n setClearing(true);\n }\n prevLayerKeyRef.current = layerKey;\n }, [layerKey, clearing]);\n\n useEffect(() => {\n if (clearing && overlay) {\n overlay.setProps({layers: []});\n requestAnimationFrame(() => setClearing(false));\n }\n }, [clearing, overlay]);\n\n if (!clearing && overlay) {\n overlay.setProps(deckProps);\n }\n\n return null;\n}\n\nexport const DeckJsonMap = forwardRef<DeckJsonMapHandle, DeckJsonMapProps>(\n function DeckJsonMap(\n {\n spec,\n datasets,\n mapStyle,\n interleaved = true,\n deckProps,\n mapProps,\n showLegends = true,\n className,\n children,\n onDatasetStatesChange,\n onRenderingError,\n },\n ref,\n ) {\n const normalizedDatasets = useMemo(\n () => normalizeDatasets(datasets),\n [datasets],\n );\n const datasetIds = useMemo(\n () => Object.keys(normalizedDatasets),\n [normalizedDatasets],\n );\n const datasetStates = usePreparedDatasetStates(normalizedDatasets);\n const onDatasetStatesChangeRef = useRef(onDatasetStatesChange);\n\n const {spec: parsedSpec, error: specError} = useMemo(\n () => parseSpec(spec),\n [spec],\n );\n\n const availableSpec = useMemo(\n () =>\n parsedSpec\n ? filterUnavailableLayers(parsedSpec, datasetIds, datasetStates)\n : null,\n [parsedSpec, datasetIds, datasetStates],\n );\n\n const converter = useMemo(\n () =>\n new JSONConverter({\n configuration: createDeckJsonConfiguration({\n datasetStates,\n datasetIds,\n }),\n onJSONChange: () => {},\n }),\n [datasetIds, datasetStates],\n );\n\n const convertedDeckPropsResult = useMemo(() => {\n if (!availableSpec) {\n return {props: null, error: specError};\n }\n\n try {\n return {\n props: converter.convert(availableSpec) as Record<string, unknown>,\n error: null,\n };\n } catch (error) {\n return {\n props: null,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n }, [availableSpec, converter, specError]);\n\n // Animation for TripsLayer — update currentTime on each frame.\n // Only activate when the trips dataset is ready to avoid spinning the RAF\n // loop while data is still loading.\n const hasTripsLayer = useMemo(() => {\n if (!availableSpec || !Array.isArray(availableSpec.layers)) return false;\n return availableSpec.layers.some((l: unknown) => {\n if (\n !l ||\n typeof l !== 'object' ||\n (l as {'@@type'?: string})['@@type'] !== 'GeoArrowTripsLayer'\n )\n return false;\n const dsId = resolveDatasetId(l as Record<string, unknown>, datasetIds);\n if (!dsId) return true;\n const state = datasetStates[dsId];\n return state?.status === 'ready';\n });\n }, [availableSpec, datasetIds, datasetStates]);\n\n const [tripsTime, setTripsTime] = useState(0);\n const [tripsPlaying, setTripsPlaying] = useState(true);\n const tripsTimeRef = useRef(0);\n\n useEffect(() => {\n if (!hasTripsLayer || !tripsPlaying) return;\n let raf: number;\n let lastFrame = Date.now();\n const tick = () => {\n const now = Date.now();\n tripsTimeRef.current += now - lastFrame;\n lastFrame = now;\n setTripsTime(tripsTimeRef.current);\n raf = requestAnimationFrame(tick);\n };\n lastFrame = Date.now();\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [hasTripsLayer, tripsPlaying]);\n\n const handleTripsPlayPause = useCallback(() => {\n setTripsPlaying((p) => !p);\n }, []);\n\n const handleTripsSeek = useCallback((time: number) => {\n const rawTime = time * 30;\n tripsTimeRef.current = rawTime;\n setTripsTime(rawTime);\n }, []);\n\n const finalDeckPropsResult = convertedDeckPropsResult;\n\n const onRenderingErrorRef = useRef(onRenderingError);\n useEffect(() => {\n onRenderingErrorRef.current = onRenderingError;\n }, [onRenderingError]);\n\n useEffect(() => {\n if (finalDeckPropsResult.error) {\n console.error(finalDeckPropsResult.error);\n onRenderingErrorRef.current?.(finalDeckPropsResult.error);\n }\n }, [finalDeckPropsResult.error]);\n\n useEffect(() => {\n onDatasetStatesChangeRef.current = onDatasetStatesChange;\n }, [onDatasetStatesChange]);\n\n useEffect(() => {\n onDatasetStatesChangeRef.current?.(datasetStates);\n }, [datasetStates]);\n\n const fallbackDeckProps = useMemo(\n () => extractFallbackDeckProps(availableSpec),\n [availableSpec],\n );\n const convertedDeckProps = (finalDeckPropsResult.props ??\n fallbackDeckProps ??\n {}) as Record<string, unknown>;\n const extraDeckProps = (deckProps ?? {}) as Record<string, unknown>;\n const extraMapProps = (mapProps ?? {}) as Record<string, unknown>;\n const hasRenderingError = Boolean(finalDeckPropsResult.error);\n\n // Separate stable layer analysis from per-frame animation to avoid\n // re-running .map() over all layers 60 times per second.\n const baseLayers = useMemo(() => {\n const mergedLayers = hasRenderingError\n ? []\n : (deckProps?.layers ??\n (convertedDeckProps.layers as unknown[] | undefined) ??\n []);\n if (!hasTripsLayer || !Array.isArray(mergedLayers))\n return {layers: mergedLayers, maxTs: 0, tripsIndices: [] as number[]};\n let computedMaxTs = 0;\n const tripsIndices: number[] = [];\n for (let i = 0; i < mergedLayers.length; i++) {\n const layer = mergedLayers[i];\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as {props?: Record<string, unknown>};\n const maxTs = (layerObj.props as Record<string, unknown> | undefined)\n ?._tripsMaxTimestamp as number | undefined;\n if (maxTs && maxTs > 0) {\n computedMaxTs = Math.max(computedMaxTs, maxTs);\n tripsIndices.push(i);\n }\n }\n return {layers: mergedLayers, maxTs: computedMaxTs, tripsIndices};\n }, [\n hasTripsLayer,\n hasRenderingError,\n deckProps?.layers,\n convertedDeckProps.layers,\n ]);\n\n // Per-frame: only clone trips layers with updated currentTime\n const animatedLayers = useMemo(() => {\n const {layers, tripsIndices} = baseLayers;\n if (!tripsIndices.length) return layers;\n if (!Array.isArray(layers)) return layers;\n const result = layers.slice();\n for (const idx of tripsIndices) {\n const layer = result[idx];\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as {\n props?: Record<string, unknown>;\n clone?: (props: Record<string, unknown>) => unknown;\n };\n if (!layerObj.clone) continue;\n const props = layerObj.props as Record<string, unknown> | undefined;\n const maxTs = (props?._tripsMaxTimestamp as number | undefined) ?? 0;\n const trailFraction =\n (props?._trailLengthFactor as number | undefined) ?? 0.4;\n const widthPx = (props?.widthMinPixels as number | undefined) ?? 3;\n const animationSpeed = 30;\n const currentTime = (tripsTime / animationSpeed) % maxTs;\n result[idx] = layerObj.clone({\n currentTime,\n trailLength: maxTs * trailFraction,\n widthMinPixels: widthPx,\n });\n }\n return result;\n }, [baseLayers, tripsTime]);\n const tripsMaxTimeValue = baseLayers.maxTs;\n\n const tripsCurrentTime = useMemo(() => {\n if (!tripsMaxTimeValue || tripsMaxTimeValue <= 0) return 0;\n return (tripsTime / 30) % tripsMaxTimeValue;\n }, [tripsTime, tripsMaxTimeValue]);\n\n const mergedDeckProps = {\n ...convertedDeckProps,\n ...extraDeckProps,\n layers: animatedLayers,\n };\n\n // overlayDeckProps should not contain viewState/initialViewState\n const {\n initialViewState,\n viewState: _vs,\n onViewStateChange: _onViewStateChange,\n ...overlayDeckProps\n } = mergedDeckProps as Record<string, unknown>;\n void _vs;\n void _onViewStateChange;\n\n const mapRef = useRef<{jumpTo: (opts: object) => void} | null>(null);\n const pendingJumpRef = useRef<object | null>(null);\n\n useImperativeHandle(\n ref,\n () => ({\n jumpTo(opts) {\n const jumpOpts = buildDeckMapJumpToOptions(opts);\n if (mapRef.current) {\n mapRef.current.jumpTo(jumpOpts);\n } else {\n pendingJumpRef.current = jumpOpts;\n }\n },\n }),\n [],\n );\n\n const handleMapLoad = useCallback(\n (event?: unknown) => {\n if (pendingJumpRef.current && mapRef.current) {\n mapRef.current.jumpTo(pendingJumpRef.current);\n pendingJumpRef.current = null;\n }\n const externalOnLoad = (\n extraMapProps as {onLoad?: (e?: unknown) => void}\n ).onLoad;\n externalOnLoad?.(event);\n },\n [extraMapProps],\n );\n\n const {resolvedTheme} = useTheme();\n const hostDefaultMapStyles = useDeckMapDefaultStyles();\n\n const mergedMapProps = {\n ...extraMapProps,\n mapStyle: resolveDeckMapStyle({\n mapStyle,\n mapPropsMapStyle: mapProps?.mapStyle,\n hostDefaultStyles: hostDefaultMapStyles,\n resolvedTheme,\n fallbackStyles: DEFAULT_MAP_STYLES,\n }),\n };\n const legends = useMemo(\n () =>\n showLegends\n ? extractColorScaleLegends({\n spec: availableSpec,\n datasetIds,\n datasetStates,\n })\n : [],\n [availableSpec, datasetIds, datasetStates, showLegends],\n );\n\n return (\n <div className={cn('relative h-full w-full', className)}>\n {hasRenderingError ? (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center p-4\">\n <div className=\"max-w-sm rounded-md border border-red-200 bg-red-50/95 p-4 text-sm text-red-700 shadow-sm\">\n {`Map couldn't be rendered. Check the console for details.`}\n </div>\n </div>\n ) : null}\n\n <Map\n ref={mapRef as any}\n {...(mergedMapProps as object)}\n {...(initialViewState\n ? {initialViewState: initialViewState as object}\n : {})}\n onLoad={handleMapLoad}\n style={{width: '100%', height: '100%', ...mapProps?.style}}\n >\n <DeckOverlayControl interleaved={interleaved} {...overlayDeckProps} />\n {children}\n </Map>\n\n {renderDatasetErrorOverlay(datasetStates)}\n {!hasRenderingError && showLegends ? (\n <div className=\"pointer-events-none absolute bottom-2 left-2 z-10 max-w-56\">\n {hasTripsLayer && tripsMaxTimeValue > 0 ? (\n <div className=\"mb-1\">\n <TripsTimeControl\n currentTime={tripsCurrentTime}\n maxTime={tripsMaxTimeValue}\n playing={tripsPlaying}\n onPlayPause={handleTripsPlayPause}\n onSeek={handleTripsSeek}\n />\n </div>\n ) : null}\n <ColorScaleLegend legends={legends} />\n </div>\n ) : hasTripsLayer && tripsMaxTimeValue > 0 ? (\n <div className=\"pointer-events-none absolute bottom-2 left-2 z-10\">\n <TripsTimeControl\n currentTime={tripsCurrentTime}\n maxTime={tripsMaxTimeValue}\n playing={tripsPlaying}\n onPlayPause={handleTripsPlayPause}\n onSeek={handleTripsSeek}\n />\n </div>\n ) : null}\n </div>\n );\n },\n);\n"]}
1
+ {"version":3,"file":"DeckJsonMap.js","sourceRoot":"","sources":["../src/DeckJsonMap.tsx"],"names":[],"mappings":"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","sourcesContent":["import type {Layer} from '@deck.gl/core';\nimport {JSONConverter} from '@deck.gl/json';\nimport {MapboxOverlay} from '@deck.gl/mapbox';\nimport {ColorScaleLegend} from '@sqlrooms/color-scales';\nimport {useBaseRoomStore} from '@sqlrooms/room-store';\nimport {\n cn,\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n useTheme,\n} from '@sqlrooms/ui';\nimport {ChevronRightIcon} from 'lucide-react';\nimport 'maplibre-gl/dist/maplibre-gl.css';\nimport {\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type FC,\n} from 'react';\nimport {forwardRef} from 'react';\nimport Map, {useControl} from 'react-map-gl/maplibre';\nimport {ZodError} from 'zod';\nimport {DeckJsonMapSpec} from './DeckJsonMapSpec';\nimport {resolveDeckMapStyle, type DeckMapBasemapProvider} from './basemap';\nimport {useDeckMapDefaultStyles} from './DeckMapDefaultStylesProvider';\nimport type {DeckMapsSliceState} from './DeckMapsSlice';\nimport {normalizeDatasets} from './datasets/normalizeDatasets';\nimport {usePreparedDatasetStates} from './datasets/usePreparedDatasetStates';\nimport {createDeckJsonConfiguration} from './json/createDeckJsonConfiguration';\nimport {extractColorScaleLegends} from './json/extractColorScaleLegends';\nimport {getLayerCompatibility} from './json/layerCompatibility';\nimport {resolveDatasetId} from './json/layerConfig';\nimport {buildDeckMapJumpToOptions} from './mapFit';\nimport type {\n DeckJsonMapHandle,\n DeckJsonMapProps,\n PreparedDeckDatasetState,\n} from './types';\n\nconst DEFAULT_MAP_STYLES = {\n light: 'https://tiles.openfreemap.org/styles/positron',\n dark: 'https://tiles.openfreemap.org/styles/dark',\n} as const;\n\nfunction parseSpec(spec: DeckJsonMapProps['spec']) {\n try {\n const parsedValue = typeof spec === 'string' ? JSON.parse(spec) : spec;\n const validatedSpec = DeckJsonMapSpec.safeParse(parsedValue);\n if (!validatedSpec.success) {\n return {\n spec: null,\n error: new Error(formatSpecValidationError(validatedSpec.error)),\n };\n }\n\n return {\n spec: validatedSpec.data,\n error: null,\n };\n } catch (error) {\n return {\n spec: null,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\nfunction formatSpecValidationError(error: ZodError) {\n const issues = error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : 'spec';\n return `${path}: ${issue.message}`;\n });\n\n return `Invalid DeckJsonMap spec. ${issues.join('; ')}`;\n}\n\nfunction extractFallbackDeckProps(spec: Record<string, unknown> | null) {\n if (!spec) {\n return {};\n }\n\n const fallbackProps: Record<string, unknown> = {};\n for (const key of ['initialViewState', 'viewState', 'controller']) {\n if (key in spec) {\n fallbackProps[key] = spec[key];\n }\n }\n\n return fallbackProps;\n}\n\nfunction filterUnavailableLayers(\n spec: Record<string, unknown>,\n datasetIds: string[],\n datasetStates: Record<string, PreparedDeckDatasetState>,\n) {\n const layers = Array.isArray(spec.layers) ? spec.layers : [];\n const filteredLayers = layers.filter((layer) => {\n if (!layer || typeof layer !== 'object') {\n return true;\n }\n\n const layerProps = layer as Record<string, unknown>;\n const layerName = String(layerProps['@@type'] ?? '');\n const compatibility = getLayerCompatibility(layerName);\n if (!compatibility) {\n return true;\n }\n\n const datasetId = resolveDatasetId(layerProps, datasetIds);\n if (!datasetId) {\n return true;\n }\n\n const datasetState = datasetStates[datasetId];\n if (!datasetState) {\n return false;\n }\n\n return datasetState.status !== 'error';\n });\n\n return {\n ...spec,\n layers: filteredLayers,\n };\n}\n\nfunction renderDatasetErrorOverlay(\n datasetStates: Record<string, PreparedDeckDatasetState>,\n) {\n const failedDatasets = Object.entries(datasetStates).filter(\n (\n entry,\n ): entry is [\n string,\n Extract<PreparedDeckDatasetState, {status: 'error'}>,\n ] => entry[1].status === 'error',\n );\n\n if (!failedDatasets.length) {\n return null;\n }\n\n return (\n <div className=\"pointer-events-none absolute inset-x-4 top-4 z-10 space-y-2\">\n {failedDatasets.map(([datasetId, state]) => (\n <div\n key={datasetId}\n className=\"rounded-md border border-red-200 bg-red-50/95 px-3 py-2 text-sm text-red-700 shadow-sm\"\n >\n {`Dataset \"${datasetId}\" failed: ${state.error.message}`}\n </div>\n ))}\n </div>\n );\n}\n\nconst TripsTimeControl: FC<{\n currentTime: number;\n maxTime: number;\n playing: boolean;\n onPlayPause: () => void;\n onSeek: (time: number) => void;\n}> = ({currentTime, maxTime, playing, onPlayPause, onSeek}) => {\n const [collapsed, setCollapsed] = useState(false);\n const progress = maxTime > 0 ? currentTime / maxTime : 0;\n\n if (collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"border-border/70 bg-background/90 text-muted-foreground hover:text-foreground pointer-events-auto flex w-fit items-center gap-1 rounded-md border px-2 py-1 text-[10px] leading-none font-medium shadow-sm backdrop-blur-sm transition-colors\"\n >\n Timeline\n </button>\n );\n }\n\n return (\n <div className=\"bg-background/90 border-border/70 pointer-events-auto relative flex items-center gap-1.5 rounded-md border px-2 py-1.5 pr-7 shadow-sm backdrop-blur-sm\">\n <button\n type=\"button\"\n onClick={onPlayPause}\n className=\"text-foreground hover:bg-accent flex h-5 w-5 shrink-0 items-center justify-center rounded\"\n title={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\">\n <rect x=\"1\" y=\"1\" width=\"3\" height=\"8\" />\n <rect x=\"6\" y=\"1\" width=\"3\" height=\"8\" />\n </svg>\n ) : (\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"currentColor\">\n <polygon points=\"2,1 9,5 2,9\" />\n </svg>\n )}\n </button>\n <input\n type=\"range\"\n min={0}\n max={1000}\n value={Math.round(progress * 1000)}\n onChange={(e) => onSeek((Number(e.target.value) / 1000) * maxTime)}\n className=\"h-1 w-24 flex-1 cursor-pointer\"\n />\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-muted-foreground hover:text-foreground absolute top-1.5 right-1.5 flex h-4 w-4 items-center justify-center rounded-sm transition-colors\"\n title=\"Collapse\"\n >\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\">\n <path\n d=\"M1 1L7 7M7 1L1 7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n </div>\n );\n};\n\nfunction getDeckLayerTypeName(layer: unknown): string {\n if (!layer || typeof layer !== 'object') return '?';\n const ctor = (\n layer as {\n constructor?: {layerName?: string; name?: string};\n }\n ).constructor;\n // Prefer static layerName: table-to-RecordBatch adapters all share\n // constructor.name \"Adapter\", which would miss heatmap ↔ scatterplot swaps.\n return ctor?.layerName ?? ctor?.name ?? '?';\n}\n\n// Workaround for deck.gl HeatmapLayer not releasing its WebGL framebuffer\n// when replaced by another layer type (e.g. switching heatmap → scatterplot).\n// We detect layer class changes and clear layers for one animation frame,\n// giving deck.gl a chance to finalize the old layer's resources before\n// initializing the new one.\nfunction DeckOverlayControl({\n interleaved,\n ...deckProps\n}: {interleaved: boolean} & Record<string, unknown>) {\n const overlay = useControl<MapboxOverlay>(\n () => new MapboxOverlay({interleaved}),\n );\n const prevLayerKeyRef = useRef<string>('');\n const [clearing, setClearing] = useState(false);\n const captureStatusRef = useRef<HTMLSpanElement>(null);\n\n const layers = deckProps.layers as unknown[] | undefined;\n const captureLayers = useMemo(\n () => (layers?.flat(Infinity).filter(Boolean) ?? []) as Layer[],\n [layers],\n );\n useLayoutEffect(() => {\n // A previous frame no longer represents the current layers.\n captureStatusRef.current?.setAttribute('data-sqlrooms-map-loading', 'true');\n }, [layers, clearing]);\n const layerKey = Array.isArray(layers)\n ? layers.map(getDeckLayerTypeName).join(',')\n : '';\n\n useEffect(() => {\n if (\n prevLayerKeyRef.current &&\n prevLayerKeyRef.current !== layerKey &&\n !clearing\n ) {\n setClearing(true);\n }\n prevLayerKeyRef.current = layerKey;\n }, [layerKey, clearing]);\n\n useEffect(() => {\n if (clearing && overlay) {\n // The temporary empty frame must not advertise capture readiness.\n overlay.setProps({layers: [], onAfterRender: () => {}});\n requestAnimationFrame(() => setClearing(false));\n }\n }, [clearing, overlay]);\n\n useLayoutEffect(() => {\n if (clearing || !overlay) return;\n overlay.setProps({\n ...deckProps,\n onLoad: () => {\n // The separate canvas is created asynchronously. Mark it once deck\n // initializes, including when the host supplies a custom canvas ID.\n overlay.getCanvas()?.setAttribute('data-sqlrooms-deck-canvas', '');\n if (typeof deckProps.onLoad === 'function') deckProps.onLoad();\n },\n onAfterRender: (context) => {\n const loaded = captureLayers.every((layer) => layer.isLoaded);\n captureStatusRef.current?.setAttribute(\n 'data-sqlrooms-map-loading',\n String(!loaded),\n );\n if (typeof deckProps.onAfterRender === 'function') {\n deckProps.onAfterRender(context);\n }\n },\n });\n }, [clearing, overlay, deckProps, captureLayers]);\n\n return (\n <span hidden ref={captureStatusRef} data-sqlrooms-map-loading=\"true\" />\n );\n}\n\nfunction DeckMapRenderingErrorOverlay({error}: {error: Error}) {\n return (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center p-4\">\n <div className=\"max-w-sm rounded-md border border-red-200 bg-red-50/95 p-4 text-sm text-red-700 shadow-sm\">\n <Collapsible>\n <div className=\"flex items-start gap-1\">\n <span>{\"Map couldn't be rendered\"}</span>\n <CollapsibleTrigger\n className=\"group mt-0.5 shrink-0 rounded p-0.5 hover:bg-red-100\"\n aria-label=\"Show error details\"\n >\n <ChevronRightIcon className=\"h-3.5 w-3.5 transition-transform group-data-[state=open]:rotate-90\" />\n </CollapsibleTrigger>\n </div>\n <CollapsibleContent>\n <pre className=\"mt-2 max-h-40 overflow-auto font-mono text-xs whitespace-pre-wrap\">\n {error.message}\n </pre>\n </CollapsibleContent>\n </Collapsible>\n </div>\n </div>\n );\n}\n\nexport const DeckJsonMap = forwardRef<DeckJsonMapHandle, DeckJsonMapProps>(\n function DeckJsonMap(\n {\n spec,\n datasets,\n mapStyle,\n basemapProvider,\n interleaved = true,\n deckProps,\n mapProps,\n showLegends = true,\n className,\n children,\n onDatasetStatesChange,\n onRenderingError,\n },\n ref,\n ) {\n const normalizedDatasets = useMemo(\n () => normalizeDatasets(datasets),\n [datasets],\n );\n const datasetIdKey = JSON.stringify(Object.keys(normalizedDatasets).sort());\n const datasetIds = useMemo(\n () => JSON.parse(datasetIdKey) as string[],\n [datasetIdKey],\n );\n const datasetStates = usePreparedDatasetStates(normalizedDatasets);\n const [mapReady, setMapReady] = useState(false);\n const datasetsLoading = datasetIds.some(\n (id) => !datasetStates[id] || datasetStates[id]?.status === 'loading',\n );\n const onDatasetStatesChangeRef = useRef(onDatasetStatesChange);\n\n const {spec: parsedSpec, error: specError} = useMemo(\n () => parseSpec(spec),\n [spec],\n );\n\n const availableSpec = useMemo(\n () =>\n parsedSpec\n ? filterUnavailableLayers(parsedSpec, datasetIds, datasetStates)\n : null,\n [parsedSpec, datasetIds, datasetStates],\n );\n\n const converter = useMemo(\n () =>\n new JSONConverter({\n configuration: createDeckJsonConfiguration({\n datasetStates,\n datasetIds,\n }),\n onJSONChange: () => {},\n }),\n [datasetIds, datasetStates],\n );\n\n const convertedDeckPropsResult = useMemo(() => {\n if (!availableSpec) {\n return {props: null, error: specError};\n }\n\n try {\n return {\n props: converter.convert(availableSpec) as Record<string, unknown>,\n error: null,\n };\n } catch (error) {\n return {\n props: null,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n }, [availableSpec, converter, specError]);\n\n // Animation for TripsLayer — update currentTime on each frame.\n // Only activate when the trips dataset is ready to avoid spinning the RAF\n // loop while data is still loading.\n const hasTripsLayer = useMemo(() => {\n if (!availableSpec || !Array.isArray(availableSpec.layers)) return false;\n return availableSpec.layers.some((l: unknown) => {\n if (\n !l ||\n typeof l !== 'object' ||\n (l as {'@@type'?: string})['@@type'] !== 'GeoArrowTripsLayer'\n )\n return false;\n const dsId = resolveDatasetId(l as Record<string, unknown>, datasetIds);\n if (!dsId) return true;\n const state = datasetStates[dsId];\n return state?.status === 'ready';\n });\n }, [availableSpec, datasetIds, datasetStates]);\n\n const [tripsTime, setTripsTime] = useState(0);\n const [tripsPlaying, setTripsPlaying] = useState(true);\n const tripsTimeRef = useRef(0);\n\n useEffect(() => {\n if (!hasTripsLayer || !tripsPlaying) return;\n let raf: number;\n let lastFrame = Date.now();\n const tick = () => {\n const now = Date.now();\n tripsTimeRef.current += now - lastFrame;\n lastFrame = now;\n setTripsTime(tripsTimeRef.current);\n raf = requestAnimationFrame(tick);\n };\n lastFrame = Date.now();\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [hasTripsLayer, tripsPlaying]);\n\n const handleTripsPlayPause = useCallback(() => {\n setTripsPlaying((p) => !p);\n }, []);\n\n const handleTripsSeek = useCallback((time: number) => {\n const rawTime = time * 30;\n tripsTimeRef.current = rawTime;\n setTripsTime(rawTime);\n }, []);\n\n const finalDeckPropsResult = convertedDeckPropsResult;\n\n const onRenderingErrorRef = useRef(onRenderingError);\n useEffect(() => {\n onRenderingErrorRef.current = onRenderingError;\n }, [onRenderingError]);\n\n useEffect(() => {\n if (finalDeckPropsResult.error) {\n console.error(finalDeckPropsResult.error);\n onRenderingErrorRef.current?.(finalDeckPropsResult.error);\n }\n }, [finalDeckPropsResult.error]);\n\n useEffect(() => {\n onDatasetStatesChangeRef.current = onDatasetStatesChange;\n }, [onDatasetStatesChange]);\n\n useEffect(() => {\n onDatasetStatesChangeRef.current?.(datasetStates);\n }, [datasetStates]);\n\n const fallbackDeckProps = useMemo(\n () => extractFallbackDeckProps(availableSpec),\n [availableSpec],\n );\n const convertedDeckProps = (finalDeckPropsResult.props ??\n fallbackDeckProps ??\n {}) as Record<string, unknown>;\n const extraDeckProps = (deckProps ?? {}) as Record<string, unknown>;\n const extraMapProps = (mapProps ?? {}) as Record<string, unknown>;\n const hasRenderingError = Boolean(finalDeckPropsResult.error);\n\n // Separate stable layer analysis from per-frame animation to avoid\n // re-running .map() over all layers 60 times per second.\n const baseLayers = useMemo(() => {\n const mergedLayers = hasRenderingError\n ? []\n : (deckProps?.layers ??\n (convertedDeckProps.layers as unknown[] | undefined) ??\n []);\n if (!hasTripsLayer || !Array.isArray(mergedLayers))\n return {layers: mergedLayers, maxTs: 0, tripsIndices: [] as number[]};\n let computedMaxTs = 0;\n const tripsIndices: number[] = [];\n for (let i = 0; i < mergedLayers.length; i++) {\n const layer = mergedLayers[i];\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as {props?: Record<string, unknown>};\n const maxTs = (layerObj.props as Record<string, unknown> | undefined)\n ?._tripsMaxTimestamp as number | undefined;\n if (maxTs && maxTs > 0) {\n computedMaxTs = Math.max(computedMaxTs, maxTs);\n tripsIndices.push(i);\n }\n }\n return {layers: mergedLayers, maxTs: computedMaxTs, tripsIndices};\n }, [\n hasTripsLayer,\n hasRenderingError,\n deckProps?.layers,\n convertedDeckProps.layers,\n ]);\n\n // Per-frame: only clone trips layers with updated currentTime\n const animatedLayers = useMemo(() => {\n const {layers, tripsIndices} = baseLayers;\n if (!tripsIndices.length) return layers;\n if (!Array.isArray(layers)) return layers;\n const result = layers.slice();\n for (const idx of tripsIndices) {\n const layer = result[idx];\n if (!layer || typeof layer !== 'object') continue;\n const layerObj = layer as {\n props?: Record<string, unknown>;\n clone?: (props: Record<string, unknown>) => unknown;\n };\n if (!layerObj.clone) continue;\n const props = layerObj.props as Record<string, unknown> | undefined;\n const maxTs = (props?._tripsMaxTimestamp as number | undefined) ?? 0;\n const trailFraction =\n (props?._trailLengthFactor as number | undefined) ?? 0.4;\n const widthPx = (props?.widthMinPixels as number | undefined) ?? 3;\n const animationSpeed = 30;\n const currentTime = (tripsTime / animationSpeed) % maxTs;\n result[idx] = layerObj.clone({\n currentTime,\n trailLength: maxTs * trailFraction,\n widthMinPixels: widthPx,\n });\n }\n return result;\n }, [baseLayers, tripsTime]);\n const tripsMaxTimeValue = baseLayers.maxTs;\n\n const tripsCurrentTime = useMemo(() => {\n if (!tripsMaxTimeValue || tripsMaxTimeValue <= 0) return 0;\n return (tripsTime / 30) % tripsMaxTimeValue;\n }, [tripsTime, tripsMaxTimeValue]);\n\n const mergedDeckProps = {\n ...convertedDeckProps,\n ...extraDeckProps,\n layers: animatedLayers,\n };\n\n // overlayDeckProps should not contain viewState/initialViewState\n const {\n initialViewState,\n viewState: _vs,\n onViewStateChange: _onViewStateChange,\n ...overlayDeckProps\n } = mergedDeckProps as Record<string, unknown>;\n void _vs;\n void _onViewStateChange;\n\n const mapRef = useRef<{jumpTo: (opts: object) => void} | null>(null);\n const pendingJumpRef = useRef<object | null>(null);\n\n useImperativeHandle(\n ref,\n () => ({\n jumpTo(opts) {\n const jumpOpts = buildDeckMapJumpToOptions(opts);\n if (mapRef.current) {\n mapRef.current.jumpTo(jumpOpts);\n } else {\n pendingJumpRef.current = jumpOpts;\n }\n },\n }),\n [],\n );\n\n const handleMapLoad = useCallback(\n (event?: unknown) => {\n if (pendingJumpRef.current && mapRef.current) {\n mapRef.current.jumpTo(pendingJumpRef.current);\n pendingJumpRef.current = null;\n }\n const externalOnLoad = (\n extraMapProps as {onLoad?: (e?: unknown) => void}\n ).onLoad;\n externalOnLoad?.(event);\n },\n [extraMapProps],\n );\n\n const {resolvedTheme} = useTheme();\n const hostDefaultMapStyles = useDeckMapDefaultStyles();\n const roomBasemapProvider = useBaseRoomStore<\n Partial<DeckMapsSliceState>,\n DeckMapBasemapProvider | undefined\n >((state) => state.deckMaps?.basemapProvider);\n\n const mergedMapProps = {\n ...extraMapProps,\n // DOM image capture reads the canvas after the render frame has ended.\n // Interleaved deck layers share this buffer with the basemap.\n canvasContextAttributes: {\n preserveDrawingBuffer: true,\n ...mapProps?.canvasContextAttributes,\n },\n mapStyle: resolveDeckMapStyle({\n mapStyle,\n mapPropsMapStyle: mapProps?.mapStyle,\n basemapProvider: basemapProvider ?? roomBasemapProvider,\n hostDefaultStyles: hostDefaultMapStyles,\n resolvedTheme,\n fallbackStyles: DEFAULT_MAP_STYLES,\n }),\n };\n const legends = useMemo(\n () =>\n showLegends\n ? extractColorScaleLegends({\n spec: availableSpec,\n datasetIds,\n datasetStates,\n })\n : [],\n [availableSpec, datasetIds, showLegends, datasetStates],\n );\n\n return (\n <div\n className={cn('relative h-full w-full', className)}\n data-sqlrooms-map-loading={!mapReady || datasetsLoading}\n >\n {finalDeckPropsResult.error ? (\n <DeckMapRenderingErrorOverlay error={finalDeckPropsResult.error} />\n ) : null}\n\n <Map\n ref={mapRef as any}\n {...(mergedMapProps as object)}\n {...(initialViewState\n ? {initialViewState: initialViewState as object}\n : {})}\n onLoad={handleMapLoad}\n onData={(event) => {\n setMapReady(false);\n mapProps?.onData?.(event);\n }}\n onMoveStart={(event) => {\n setMapReady(false);\n mapProps?.onMoveStart?.(event);\n }}\n onRender={(event) => {\n setMapReady(event.target.loaded());\n mapProps?.onRender?.(event);\n }}\n style={{width: '100%', height: '100%', ...mapProps?.style}}\n >\n <DeckOverlayControl interleaved={interleaved} {...overlayDeckProps} />\n {children}\n </Map>\n\n {renderDatasetErrorOverlay(datasetStates)}\n {!hasRenderingError && showLegends ? (\n <div className=\"pointer-events-none absolute bottom-2 left-2 z-10 max-w-56\">\n {hasTripsLayer && tripsMaxTimeValue > 0 ? (\n <div className=\"mb-1\">\n <TripsTimeControl\n currentTime={tripsCurrentTime}\n maxTime={tripsMaxTimeValue}\n playing={tripsPlaying}\n onPlayPause={handleTripsPlayPause}\n onSeek={handleTripsSeek}\n />\n </div>\n ) : null}\n <ColorScaleLegend legends={legends} />\n </div>\n ) : hasTripsLayer && tripsMaxTimeValue > 0 ? (\n <div className=\"pointer-events-none absolute bottom-2 left-2 z-10\">\n <TripsTimeControl\n currentTime={tripsCurrentTime}\n maxTime={tripsMaxTimeValue}\n playing={tripsPlaying}\n onPlayPause={handleTripsPlayPause}\n onSeek={handleTripsSeek}\n />\n </div>\n ) : null}\n </div>\n );\n },\n);\n"]}