@sqlrooms/kepler 0.29.0-rc.0 → 0.29.0-rc.2

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 (36) hide show
  1. package/dist/KeplerSlice.d.ts +22 -6
  2. package/dist/KeplerSlice.d.ts.map +1 -1
  3. package/dist/KeplerSlice.js +273 -45
  4. package/dist/KeplerSlice.js.map +1 -1
  5. package/dist/components/CustomFilterManager.d.ts.map +1 -1
  6. package/dist/components/CustomFilterManager.js +4 -1
  7. package/dist/components/CustomFilterManager.js.map +1 -1
  8. package/dist/components/CustomInteractionManager.d.ts.map +1 -1
  9. package/dist/components/CustomInteractionManager.js +4 -1
  10. package/dist/components/CustomInteractionManager.js.map +1 -1
  11. package/dist/components/CustomLayerManager.d.ts.map +1 -1
  12. package/dist/components/CustomLayerManager.js +138 -17
  13. package/dist/components/CustomLayerManager.js.map +1 -1
  14. package/dist/components/CustomMapDrawPanel.d.ts +8 -0
  15. package/dist/components/CustomMapDrawPanel.d.ts.map +1 -0
  16. package/dist/components/CustomMapDrawPanel.js +28 -0
  17. package/dist/components/CustomMapDrawPanel.js.map +1 -0
  18. package/dist/components/KeplerAddDataDialog.d.ts +2 -3
  19. package/dist/components/KeplerAddDataDialog.d.ts.map +1 -1
  20. package/dist/components/KeplerAddDataDialog.js +18 -8
  21. package/dist/components/KeplerAddDataDialog.js.map +1 -1
  22. package/dist/components/KeplerImageExport.d.ts.map +1 -1
  23. package/dist/components/KeplerImageExport.js +26 -8
  24. package/dist/components/KeplerImageExport.js.map +1 -1
  25. package/dist/components/KeplerInjector.d.ts.map +1 -1
  26. package/dist/components/KeplerInjector.js +3 -1
  27. package/dist/components/KeplerInjector.js.map +1 -1
  28. package/dist/hooks/useKeplerStateActions.d.ts +7 -6
  29. package/dist/hooks/useKeplerStateActions.d.ts.map +1 -1
  30. package/dist/hooks/useKeplerStateActions.js +1 -1
  31. package/dist/hooks/useKeplerStateActions.js.map +1 -1
  32. package/dist/index.d.ts +2 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/package.json +20 -20
@@ -1,7 +1,6 @@
1
1
  import { VectorTileDatasetMetadata } from '@kepler.gl/constants';
2
- import { Layer } from '@kepler.gl/layers';
3
2
  import { KeplerGlState } from '@kepler.gl/reducers';
4
- import { AddDataToMapPayload } from '@kepler.gl/types';
3
+ import { AddDataToMapPayload, MinSavedLayer, ParsedLayer } from '@kepler.gl/types';
5
4
  import { KeplerApplicationConfig } from '@kepler.gl/utils';
6
5
  import { KeplerMapSchema, KeplerSliceConfig } from '@sqlrooms/kepler-config';
7
6
  import { RoomShellSliceState, type StateCreator } from '@sqlrooms/room-shell';
@@ -11,9 +10,15 @@ import { ReduxLoggerOptions } from 'redux-logger';
11
10
  export type KeplerGLBasicProps = {
12
11
  mapboxApiAccessToken?: string;
13
12
  };
13
+ export type CreateInitialMapKeplerStateContext = {
14
+ reason: 'initialize' | 'create-map' | 'duplicate-map' | 'register-map' | 'sync-config';
15
+ defaultInitialMapKeplerState: Partial<KeplerGlState>;
16
+ mapId?: string;
17
+ name?: string;
18
+ };
14
19
  export type CreateKeplerSliceOptions = {
15
20
  config?: Partial<KeplerSliceConfig>;
16
- initialKeplerState?: Partial<KeplerGlState>;
21
+ createInitialMapKeplerState?: (context: CreateInitialMapKeplerStateContext) => Partial<KeplerGlState>;
17
22
  basicKeplerProps?: Partial<KeplerGLBasicProps>;
18
23
  actionLogging?: boolean | ReduxLoggerOptions;
19
24
  middlewares?: Middleware[];
@@ -49,14 +54,20 @@ export type KeplerSliceState = {
49
54
  [mapId: string]: Dispatch;
50
55
  };
51
56
  initialize: () => Promise<void>;
57
+ destroy: () => Promise<void>;
52
58
  setConfig: (config: KeplerSliceConfig) => void;
53
59
  /**
54
60
  * Update the datasets in all the kepler map so that they correspond to
55
61
  * the latest table schemas in the database
56
62
  */
57
63
  syncKeplerDatasets: () => Promise<void>;
58
- addLayer: (mapId: string, layer: Layer, datasetId: string) => void;
59
- addTableToMap: (mapId: string, tableName: string, options?: AddDataToMapPayload['options']) => Promise<void>;
64
+ addLayer: (mapId: string, layer: ParsedLayer | MinSavedLayer | undefined, datasetId: string) => void;
65
+ addFilter: (mapId: string, datasetId: string) => void;
66
+ setFilter: (mapId: string, filterIdx: number, prop: string | string[], value: any, valueIndex?: number) => void;
67
+ setFilterAnimationTime: (mapId: string, filterIdx: number, prop: string, value: any) => void;
68
+ setFilterAnimationWindow: (mapId: string, filterId: string, animationWindow: string) => void;
69
+ updateTooltipFields: (mapId: string, datasetId: string, fieldNames: string[]) => void;
70
+ addTableToMap: (mapId: string, tableName: string, options?: AddDataToMapPayload['options'], config?: AddDataToMapPayload['config']) => Promise<void>;
60
71
  addTileSetToMap: (mapId: string, tableName: string, tileset: {
61
72
  name: string;
62
73
  type: string;
@@ -73,6 +84,11 @@ export type KeplerSliceState = {
73
84
  */
74
85
  createMap: (name?: string) => string;
75
86
  deleteMap: (mapId: string) => void;
87
+ duplicateMap: (mapId: string) => Promise<{
88
+ success: boolean;
89
+ message?: string;
90
+ code?: string;
91
+ }>;
76
92
  renameMap: (mapId: string, name: string) => void;
77
93
  closeMap: (mapId: string) => void;
78
94
  setOpenTabs: (tabIds: string[]) => void;
@@ -81,7 +97,7 @@ export type KeplerSliceState = {
81
97
  __reduxProviderStore: ReduxStore<KeplerGlReduxState, AnyAction> | undefined;
82
98
  };
83
99
  };
84
- export declare function createKeplerSlice({ basicKeplerProps, config: initialConfigProps, initialKeplerState, actionLogging, middlewares: additionalMiddlewares, applicationConfig, onAction, }?: CreateKeplerSliceOptions): StateCreator<KeplerSliceState>;
100
+ export declare function createKeplerSlice({ basicKeplerProps, config: initialConfigProps, createInitialMapKeplerState, actionLogging, middlewares: additionalMiddlewares, applicationConfig, onAction, }?: CreateKeplerSliceOptions): StateCreator<KeplerSliceState>;
85
101
  type RoomStateWithDiscuss = RoomShellSliceState & KeplerSliceState;
86
102
  export declare function useStoreWithKepler<T>(selector: (state: RoomStateWithDiscuss) => T): T;
87
103
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"KeplerSlice.d.ts","sourceRoot":"","sources":["../src/KeplerSlice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"KeplerSlice.d.ts","sourceRoot":"","sources":["../src/KeplerSlice.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { addDataToMap, addLayer as addLayerAction, deleteEntry, ActionTypes as KeplerActionTypes, registerEntry, removeDataset, requestMapStyles, wrapTo, } from '@kepler.gl/actions';
1
+ import { addDataToMap, addFilter as addFilterAction, addLayer as addLayerAction, deleteEntry, interactionConfigChange, ActionTypes as KeplerActionTypes, registerEntry, removeDataset, requestMapStyles, setFilter as setFilterAction, setFilterAnimationTime as setFilterAnimationTimeAction, setFilterAnimationWindow as setFilterAnimationWindowAction, wrapTo, } from '@kepler.gl/actions';
2
2
  import { ALL_FIELD_TYPES } from '@kepler.gl/constants';
3
3
  import { castDuckDBTypesForKepler, getDuckDBColumnTypes, getDuckDBColumnTypesMap, restoreGeoarrowMetadata, setGeoArrowWKBExtension, } from '@kepler.gl/duckdb';
4
4
  import { arrowSchemaToFields } from '@kepler.gl/processors';
@@ -7,19 +7,47 @@ import { KeplerGLSchemaClass } from '@kepler.gl/schemas';
7
7
  import { KeplerTable } from '@kepler.gl/table';
8
8
  import { initApplicationConfig, } from '@kepler.gl/utils';
9
9
  import { createId } from '@paralleldrive/cuid2';
10
- import { createSlice, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
10
+ import { createSlice, registerCommandsForOwner, unregisterCommandsForOwner, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
11
+ import { getTheme } from '@sqlrooms/ui';
11
12
  import { produce, setAutoFreeze } from 'immer';
12
13
  import { taskMiddleware } from 'react-palm/tasks';
13
14
  import { compose } from 'redux';
14
15
  import { createLogger } from 'redux-logger';
15
16
  setAutoFreeze(false); // Kepler attempts to mutate redux state, so we need to disable immer's auto freeze to avoid errors
16
17
  const KeplerGLSchemaManager = new KeplerGLSchemaClass();
18
+ const KEPLER_COMMAND_OWNER = '@sqlrooms/kepler';
17
19
  class DesktopKeplerTable extends KeplerTable {
18
20
  static getInputDataValidator = function () {
19
21
  // Default validator accepts only string timestamps
20
22
  return (d) => d;
21
23
  };
22
24
  }
25
+ function createDefaultMapKeplerState(resolvedTheme) {
26
+ return {
27
+ mapStyle: {
28
+ styleType: resolvedTheme === 'dark' ? 'dark-matter' : 'positron',
29
+ },
30
+ uiState: {
31
+ ...INITIAL_UI_STATE,
32
+ currentModal: null,
33
+ mapControls: {
34
+ visibleLayers: INITIAL_UI_STATE.mapControls.visibleLayers,
35
+ mapLegend: {
36
+ show: true,
37
+ active: false,
38
+ },
39
+ toggle3d: {
40
+ show: true,
41
+ active: false,
42
+ },
43
+ mapDraw: {
44
+ show: true,
45
+ active: false,
46
+ },
47
+ },
48
+ },
49
+ };
50
+ }
23
51
  export function createDefaultKeplerConfig(props) {
24
52
  const mapId = createId();
25
53
  return {
@@ -36,6 +64,66 @@ export function createDefaultKeplerConfig(props) {
36
64
  ...props,
37
65
  };
38
66
  }
67
+ function createKeplerCommands() {
68
+ const DUPLICATE_MAP_COMMAND_ID = 'kepler.duplicate-tab';
69
+ // Error codes for internal tracking/logging (kebab-case for consistency)
70
+ const ERROR_CODES = {
71
+ MAP_NOT_FOUND: 'map-not-found',
72
+ MAP_STATE_NOT_INITIALIZED: 'map-state-not-initialized',
73
+ };
74
+ return [
75
+ {
76
+ id: DUPLICATE_MAP_COMMAND_ID,
77
+ name: 'Duplicate Tab',
78
+ description: 'Duplicate the current map tab',
79
+ group: 'Kepler',
80
+ keywords: ['kepler', 'map', 'duplicate', 'tab', 'copy'],
81
+ metadata: {
82
+ readOnly: false,
83
+ idempotent: false,
84
+ riskLevel: 'low',
85
+ },
86
+ execute: async ({ getState }) => {
87
+ const currentMapId = getState().kepler.config.currentMapId;
88
+ const sourceMap = getState().kepler.config.maps.find((m) => m.id === currentMapId);
89
+ if (!sourceMap) {
90
+ return {
91
+ success: false,
92
+ commandId: DUPLICATE_MAP_COMMAND_ID,
93
+ message: 'Unable to duplicate map: current map not found',
94
+ code: ERROR_CODES.MAP_NOT_FOUND,
95
+ };
96
+ }
97
+ // Ensure the map's redux state is registered before attempting to duplicate
98
+ getState().kepler.registerKeplerMapIfNotExists(currentMapId);
99
+ // Re-read state after registration to avoid stale state
100
+ const sourceMapState = getState().kepler.map[currentMapId];
101
+ if (!sourceMapState) {
102
+ return {
103
+ success: false,
104
+ commandId: DUPLICATE_MAP_COMMAND_ID,
105
+ message: 'Unable to duplicate map: map state not initialized',
106
+ code: ERROR_CODES.MAP_STATE_NOT_INITIALIZED,
107
+ };
108
+ }
109
+ const duplicateResult = await getState().kepler.duplicateMap(currentMapId);
110
+ if (!duplicateResult.success) {
111
+ return {
112
+ success: false,
113
+ commandId: DUPLICATE_MAP_COMMAND_ID,
114
+ message: duplicateResult.message,
115
+ code: duplicateResult.code,
116
+ };
117
+ }
118
+ return {
119
+ success: true,
120
+ commandId: DUPLICATE_MAP_COMMAND_ID,
121
+ message: 'Duplicated map tab',
122
+ };
123
+ },
124
+ },
125
+ ];
126
+ }
39
127
  export function hasMapId(action) {
40
128
  return (typeof action.payload === 'object' &&
41
129
  action.payload !== null &&
@@ -51,37 +139,38 @@ const SKIP_AUTO_SAVE_ACTIONS = [
51
139
  KeplerActionTypes.UPDATE_MAP,
52
140
  KeplerActionTypes.MOUSE_MOVE,
53
141
  ];
54
- export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfigProps, initialKeplerState = {
55
- mapStyle: { styleType: 'positron' },
56
- uiState: {
57
- ...INITIAL_UI_STATE,
58
- currentModal: null,
59
- mapControls: {
60
- visibleLayers: INITIAL_UI_STATE.mapControls.visibleLayers,
61
- mapLegend: {
62
- show: true,
63
- active: false,
64
- },
65
- toggle3d: {
66
- show: true,
67
- active: false,
68
- },
69
- },
70
- },
71
- }, actionLogging = false, middlewares: additionalMiddlewares = [], applicationConfig, onAction, } = {}) {
142
+ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfigProps, createInitialMapKeplerState, actionLogging = false, middlewares: additionalMiddlewares = [], applicationConfig, onAction, } = {}) {
72
143
  const initialConfig = createDefaultKeplerConfig(initialConfigProps);
73
144
  initApplicationConfig({
74
145
  table: DesktopKeplerTable,
75
146
  ...applicationConfig,
76
147
  });
148
+ let syncKeplerPromise = null;
149
+ // When a caller arrives while a sync is already in-flight, the in-flight run
150
+ // may have captured a stale snapshot of db.tables/kepler.map (missing maps or
151
+ // tables added by createMap, duplicateMap, etc.). Setting this flag tells the
152
+ // active run to loop once more with a fresh snapshot after it finishes, so
153
+ // late mutations are never silently dropped.
154
+ let pendingKeplerSync = false;
77
155
  const updateMapLastOpenedAt = (maps, mapId, now = Date.now()) => {
78
156
  const map = maps.find((item) => item.id === mapId);
79
157
  if (map) {
80
158
  map.lastOpenedAt = now;
81
159
  }
82
160
  };
83
- return createSlice((set, get) => {
84
- const keplerReducer = keplerGlReducer.initialState(initialKeplerState);
161
+ return createSlice((set, get, store) => {
162
+ function resolveInitialMapKeplerState(context) {
163
+ const resolvedTheme = getTheme();
164
+ const defaultInitialMapKeplerState = createDefaultMapKeplerState(resolvedTheme);
165
+ return (createInitialMapKeplerState?.({
166
+ ...context,
167
+ defaultInitialMapKeplerState,
168
+ }) ?? defaultInitialMapKeplerState);
169
+ }
170
+ function createKeplerReducer(context) {
171
+ return keplerGlReducer.initialState(resolveInitialMapKeplerState(context));
172
+ }
173
+ const keplerReducer = createKeplerReducer({ reason: 'initialize' });
85
174
  const middlewares = [
86
175
  taskMiddleware,
87
176
  saveKeplerConfigMiddleware,
@@ -121,13 +210,16 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
121
210
  }));
122
211
  updateMapReduxStates();
123
212
  updateForwardDispatch();
124
- updateMapConfigs();
125
213
  get().kepler.syncKeplerDatasets();
214
+ updateMapConfigs();
126
215
  },
127
216
  async initialize() {
128
217
  const config = get().kepler.config;
129
218
  const currentMapId = config.currentMapId;
130
- const keplerInitialState = keplerReducer(undefined, registerEntry({ id: currentMapId }));
219
+ const keplerInitialState = createKeplerReducer({
220
+ reason: 'initialize',
221
+ mapId: currentMapId,
222
+ })(undefined, registerEntry({ id: currentMapId }));
131
223
  set({
132
224
  kepler: {
133
225
  ...get().kepler,
@@ -153,15 +245,66 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
153
245
  },
154
246
  });
155
247
  updateForwardDispatch();
156
- updateMapConfigs();
157
248
  await get().kepler.syncKeplerDatasets();
249
+ updateMapConfigs();
158
250
  requestMapStyle(config.currentMapId);
251
+ // Register Kepler commands
252
+ const keplerCommands = createKeplerCommands();
253
+ registerCommandsForOwner(store, KEPLER_COMMAND_OWNER, keplerCommands);
254
+ },
255
+ async destroy() {
256
+ unregisterCommandsForOwner(store, KEPLER_COMMAND_OWNER);
159
257
  },
160
258
  addLayer: (mapId, layer, datasetId) => {
161
259
  get().kepler.registerKeplerMapIfNotExists(mapId);
162
260
  get().kepler.dispatchAction(mapId, addLayerAction(layer, datasetId));
163
261
  },
164
- addTableToMap: async (mapId, tableName, options = {}) => {
262
+ addFilter: (mapId, datasetId) => {
263
+ get().kepler.registerKeplerMapIfNotExists(mapId);
264
+ get().kepler.dispatchAction(mapId, addFilterAction(datasetId));
265
+ },
266
+ setFilter: (mapId, filterIdx, prop, value, valueIndex) => {
267
+ get().kepler.registerKeplerMapIfNotExists(mapId);
268
+ get().kepler.dispatchAction(mapId, setFilterAction(filterIdx, prop, value, valueIndex));
269
+ },
270
+ setFilterAnimationTime: (mapId, filterIdx, prop, value) => {
271
+ get().kepler.registerKeplerMapIfNotExists(mapId);
272
+ get().kepler.dispatchAction(mapId, setFilterAnimationTimeAction(filterIdx, prop, value));
273
+ },
274
+ setFilterAnimationWindow: (mapId, filterId, animationWindow) => {
275
+ get().kepler.registerKeplerMapIfNotExists(mapId);
276
+ get().kepler.dispatchAction(mapId, setFilterAnimationWindowAction({ id: filterId, animationWindow }));
277
+ },
278
+ updateTooltipFields: (mapId, datasetId, fieldNames) => {
279
+ get().kepler.registerKeplerMapIfNotExists(mapId);
280
+ const mapState = get().kepler.map[mapId];
281
+ const tooltipConfig = mapState?.visState?.interactionConfig?.tooltip;
282
+ if (!tooltipConfig)
283
+ return;
284
+ const currentFieldsToShow = tooltipConfig.config?.fieldsToShow || {};
285
+ const existingFields = currentFieldsToShow[datasetId] || [];
286
+ const existingByName = new Map(existingFields.map((field) => [
287
+ field.name,
288
+ field,
289
+ ]));
290
+ const nextFields = Array.from(new Set(fieldNames)).map((name) => existingByName.get(name) ?? { name, format: null });
291
+ if (nextFields.length === existingFields.length &&
292
+ nextFields.every((field, index) => field.name === existingFields[index]?.name &&
293
+ field.format === existingFields[index]?.format)) {
294
+ return;
295
+ }
296
+ get().kepler.dispatchAction(mapId, interactionConfigChange({
297
+ ...tooltipConfig,
298
+ config: {
299
+ ...tooltipConfig.config,
300
+ fieldsToShow: {
301
+ ...currentFieldsToShow,
302
+ [datasetId]: nextFields,
303
+ },
304
+ },
305
+ }));
306
+ },
307
+ addTableToMap: async (mapId, tableName, options = {}, config = {}) => {
165
308
  const connector = await get().db.getConnector();
166
309
  const duckDbColumns = await getDuckDBColumnTypes({
167
310
  query: (query) => connector.query(query).result,
@@ -180,7 +323,7 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
180
323
  info: { label: tableName, id: tableName },
181
324
  metadata: { tableName },
182
325
  };
183
- get().kepler.dispatchAction(mapId, addDataToMap({ datasets, options }));
326
+ get().kepler.dispatchAction(mapId, addDataToMap({ datasets, options, config }));
184
327
  }
185
328
  },
186
329
  getCurrentMap: () => {
@@ -203,7 +346,11 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
203
346
  lastOpenedAt: now,
204
347
  });
205
348
  draft.kepler.config.openTabs.push(mapId);
206
- draft.kepler.map = keplerReducer(draft.kepler.map, registerEntry({ id: mapId }));
349
+ draft.kepler.map = createKeplerReducer({
350
+ reason: 'create-map',
351
+ mapId,
352
+ name,
353
+ })(draft.kepler.map, registerEntry({ id: mapId }));
207
354
  draft.kepler.forwardDispatch[mapId] = getForwardDispatch(mapId);
208
355
  }));
209
356
  requestMapStyle(mapId);
@@ -211,22 +358,53 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
211
358
  return mapId;
212
359
  },
213
360
  async syncKeplerDatasets() {
214
- for (const mapId of Object.keys(get().kepler.map)) {
215
- const keplerDatasets = get().kepler.map[mapId]?.visState.datasets;
216
- for (const { table } of get().db.tables) {
217
- // TODO: remove this once getDuckDBColumnTypesMap can handle qualified table names
218
- // const qualifiedTable = table.toString();
219
- if (
220
- // !table.schema?.startsWith('__') && // skip internal schemas
221
- // !keplerDatasets?.[qualifiedTable]
222
- table.schema === 'main' &&
223
- !keplerDatasets?.[table.table]) {
224
- await get().kepler.addTableToMap(mapId, table.table, {
225
- autoCreateLayers: false,
226
- centerMap: false,
227
- });
361
+ if (syncKeplerPromise) {
362
+ pendingKeplerSync = true;
363
+ return syncKeplerPromise;
364
+ }
365
+ syncKeplerPromise = (async () => {
366
+ // Loop until no new sync was requested during the current pass.
367
+ // Each iteration reads a fresh snapshot of db.tables and kepler.map,
368
+ // so tables/maps added concurrently are picked up on the next pass.
369
+ do {
370
+ pendingKeplerSync = false;
371
+ for (const mapId of Object.keys(get().kepler.map)) {
372
+ const mapState = get().kepler.map[mapId];
373
+ if (!mapState)
374
+ continue;
375
+ const keplerDatasets = mapState.visState.datasets;
376
+ // Only sync tables that are referenced by existing layers or filters
377
+ const referencedDataIds = new Set();
378
+ for (const layer of mapState.visState.layers ?? []) {
379
+ if (layer.config.dataId) {
380
+ referencedDataIds.add(layer.config.dataId);
381
+ }
382
+ }
383
+ for (const filter of mapState.visState.filters ?? []) {
384
+ for (const dataId of filter.dataId ?? []) {
385
+ referencedDataIds.add(dataId);
386
+ }
387
+ }
388
+ const availableTables = new Set(get()
389
+ .db.tables.filter((t) => t.table.schema === 'main')
390
+ .map((t) => t.table.table));
391
+ for (const dataId of referencedDataIds) {
392
+ if (!keplerDatasets?.[dataId] &&
393
+ availableTables.has(dataId)) {
394
+ await get().kepler.addTableToMap(mapId, dataId, {
395
+ autoCreateLayers: false,
396
+ centerMap: false,
397
+ });
398
+ }
399
+ }
228
400
  }
229
- }
401
+ } while (pendingKeplerSync);
402
+ })();
403
+ try {
404
+ await syncKeplerPromise;
405
+ }
406
+ finally {
407
+ syncKeplerPromise = null;
230
408
  }
231
409
  },
232
410
  deleteMap: (mapId) => {
@@ -267,6 +445,49 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
267
445
  delete draft.kepler.forwardDispatch[mapId];
268
446
  }));
269
447
  },
448
+ duplicateMap: async (mapId) => {
449
+ // Ensure the map's redux state is registered, consistent with other kepler actions
450
+ get().kepler.registerKeplerMapIfNotExists(mapId);
451
+ const sourceMap = get().kepler.config.maps.find((m) => m.id === mapId);
452
+ const sourceMapState = get().kepler.map[mapId];
453
+ if (!sourceMap || !sourceMapState) {
454
+ return {
455
+ success: false,
456
+ message: 'Unable to duplicate map: source map or state not found',
457
+ code: 'source-map-not-found',
458
+ };
459
+ }
460
+ const newMapId = createId();
461
+ const now = Date.now();
462
+ // Save the source map state using Kepler's schema manager
463
+ const savedConfig = KeplerGLSchemaManager.getConfigToSave(sourceMapState);
464
+ set((state) => produce(state, (draft) => {
465
+ draft.kepler.config.maps.push({
466
+ id: newMapId,
467
+ name: `Copy of ${sourceMap.name}`,
468
+ config: savedConfig,
469
+ lastOpenedAt: now,
470
+ });
471
+ draft.kepler.config.openTabs.push(newMapId);
472
+ draft.kepler.config.currentMapId = newMapId;
473
+ // Register the new map with empty state, then load the config
474
+ draft.kepler.map = createKeplerReducer({
475
+ reason: 'duplicate-map',
476
+ mapId: newMapId,
477
+ name: `Copy of ${sourceMap.name}`,
478
+ })(draft.kepler.map, registerEntry({ id: newMapId }));
479
+ draft.kepler.forwardDispatch[newMapId] =
480
+ getForwardDispatch(newMapId);
481
+ }));
482
+ // Load the saved config into the new map
483
+ get().kepler.addConfigToMap(newMapId, savedConfig);
484
+ requestMapStyle(newMapId);
485
+ get().kepler.syncKeplerDatasets();
486
+ return {
487
+ success: true,
488
+ message: 'Map duplicated successfully',
489
+ };
490
+ },
270
491
  renameMap: (mapId, name) => {
271
492
  set((state) => produce(state, (draft) => {
272
493
  const map = draft.kepler.config.maps.find((map) => map.id === mapId);
@@ -343,7 +564,10 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
343
564
  set({
344
565
  kepler: {
345
566
  ...get().kepler,
346
- map: keplerReducer(get().kepler.map, registerEntry({ id: mapId })),
567
+ map: createKeplerReducer({
568
+ reason: 'register-map',
569
+ mapId,
570
+ })(get().kepler.map, registerEntry({ id: mapId })),
347
571
  forwardDispatch: {
348
572
  ...get().kepler.forwardDispatch,
349
573
  [mapId]: getForwardDispatch(mapId),
@@ -410,7 +634,11 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
410
634
  // Register redux state of maps that are not in the config
411
635
  for (const map of draft.kepler.config.maps) {
412
636
  if (!draft.kepler.map[map.id]) {
413
- draft.kepler.map = keplerReducer(draft.kepler.map, registerEntry({ id: map.id }));
637
+ draft.kepler.map = createKeplerReducer({
638
+ reason: 'sync-config',
639
+ mapId: map.id,
640
+ name: map.name,
641
+ })(draft.kepler.map, registerEntry({ id: map.id }));
414
642
  draft.kepler.forwardDispatch[map.id] = getForwardDispatch(map.id);
415
643
  }
416
644
  }