@sqlrooms/kepler 0.29.0-rc.7 → 0.29.0-rc.8

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 (46) hide show
  1. package/LICENSE.md +2 -1
  2. package/README.md +121 -4
  3. package/dist/KeplerSlice.d.ts +55 -2
  4. package/dist/KeplerSlice.d.ts.map +1 -1
  5. package/dist/KeplerSlice.js +92 -15
  6. package/dist/KeplerSlice.js.map +1 -1
  7. package/dist/components/CustomFilterManager.d.ts.map +1 -1
  8. package/dist/components/CustomFilterManager.js +16 -4
  9. package/dist/components/CustomFilterManager.js.map +1 -1
  10. package/dist/components/CustomLayerManager.d.ts.map +1 -1
  11. package/dist/components/CustomLayerManager.js +23 -110
  12. package/dist/components/CustomLayerManager.js.map +1 -1
  13. package/dist/components/CustomMapLegendPanel.d.ts +1 -1
  14. package/dist/components/CustomMapLegendPanel.d.ts.map +1 -1
  15. package/dist/components/CustomMapLegendPanel.js +14 -6
  16. package/dist/components/CustomMapLegendPanel.js.map +1 -1
  17. package/dist/components/CustomSourceDataSelector.d.ts +18 -0
  18. package/dist/components/CustomSourceDataSelector.d.ts.map +1 -0
  19. package/dist/components/CustomSourceDataSelector.js +130 -0
  20. package/dist/components/CustomSourceDataSelector.js.map +1 -0
  21. package/dist/components/KeplerInjector.d.ts.map +1 -1
  22. package/dist/components/KeplerInjector.js +3 -1
  23. package/dist/components/KeplerInjector.js.map +1 -1
  24. package/dist/components/KeplerMapContainer.d.ts.map +1 -1
  25. package/dist/components/KeplerMapContainer.js +9 -2
  26. package/dist/components/KeplerMapContainer.js.map +1 -1
  27. package/dist/components/KeplerProvider.d.ts.map +1 -1
  28. package/dist/components/KeplerProvider.js +3 -1
  29. package/dist/components/KeplerProvider.js.map +1 -1
  30. package/dist/components/KeplerTableSourceSelector.d.ts +20 -0
  31. package/dist/components/KeplerTableSourceSelector.d.ts.map +1 -0
  32. package/dist/components/KeplerTableSourceSelector.js +21 -0
  33. package/dist/components/KeplerTableSourceSelector.js.map +1 -0
  34. package/dist/index.d.ts +6 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/keplerTableSelection.d.ts +142 -0
  39. package/dist/keplerTableSelection.d.ts.map +1 -0
  40. package/dist/keplerTableSelection.js +231 -0
  41. package/dist/keplerTableSelection.js.map +1 -0
  42. package/dist/styles/theme.d.ts +12 -0
  43. package/dist/styles/theme.d.ts.map +1 -1
  44. package/dist/styles/theme.js +12 -0
  45. package/dist/styles/theme.js.map +1 -1
  46. package/package.json +13 -7
package/LICENSE.md CHANGED
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
- Copyright 2025 SQLRooms Contributors
3
+ Copyright 2024-2026 SQLRooms Contributors
4
+ Copyright Vis.gl contributors
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
7
 
package/README.md CHANGED
@@ -63,14 +63,18 @@ function MapPanel() {
63
63
  const mapId = useRoomStore((state) => state.kepler.config.maps[0]?.id);
64
64
  const addTableToMap = useRoomStore((state) => state.kepler.addTableToMap);
65
65
  const isTableReady = useRoomStore((state) =>
66
- Boolean(state.db.findTableByName('earthquakes')),
66
+ Boolean(state.db.findTable('earthquakes')),
67
67
  );
68
68
 
69
69
  useEffect(() => {
70
70
  if (!isTableReady || !mapId) return;
71
- void addTableToMap(mapId, 'earthquakes', {
72
- autoCreateLayers: true,
73
- centerMap: true,
71
+ void addTableToMap({
72
+ mapId,
73
+ tableName: 'earthquakes',
74
+ options: {
75
+ autoCreateLayers: true,
76
+ centerMap: true,
77
+ },
74
78
  });
75
79
  }, [isTableReady, mapId, addTableToMap]);
76
80
 
@@ -88,19 +92,132 @@ export function App() {
88
92
  }
89
93
  ```
90
94
 
95
+ ## Adding tables to maps
96
+
97
+ Use `state.kepler.addTableToMap()` to load a DuckDB table into a Kepler map. The
98
+ preferred API is an object parameter:
99
+
100
+ ```ts
101
+ await state.kepler.addTableToMap({
102
+ mapId,
103
+ tableName: 'earthquakes',
104
+ options: {
105
+ autoCreateLayers: true,
106
+ centerMap: true,
107
+ },
108
+ });
109
+ ```
110
+
111
+ `tableName` is the SQL table reference to load. It can also be a saved Kepler
112
+ dataset id when the configured table-selection policy can resolve that id back
113
+ to a DuckDB table.
114
+
115
+ For normal add-table flows, omit `datasetId`. SQLRooms derives the persisted
116
+ Kepler dataset id from the table-selection policy:
117
+
118
+ ```ts
119
+ await state.kepler.addTableToMap({
120
+ mapId,
121
+ tableName: 'main.places',
122
+ });
123
+ ```
124
+
125
+ Only pass `datasetId` when you need to load a table under an existing Kepler
126
+ `dataId`, such as when restoring a saved map config:
127
+
128
+ ```ts
129
+ await state.kepler.addTableToMap({
130
+ mapId,
131
+ tableName: savedDataId,
132
+ options: {
133
+ autoCreateLayers: false,
134
+ centerMap: false,
135
+ },
136
+ datasetId: savedDataId,
137
+ });
138
+ ```
139
+
140
+ The older positional signature is still accepted for compatibility, but new code
141
+ should use the object form so the table reference, Kepler options, config, and
142
+ dataset-id override remain clear at the call site.
143
+
91
144
  ## Common customization
92
145
 
93
146
  Pass options to `createKeplerSlice()`:
94
147
 
95
148
  ```ts
149
+ import {createKeplerTheme, type KeplerThemeOverrides} from '@sqlrooms/kepler';
150
+
96
151
  createKeplerSlice({
97
152
  basicKeplerProps: {
98
153
  mapboxApiAccessToken: import.meta.env.VITE_MAPBOX_TOKEN,
99
154
  },
155
+ keplerTheme: createKeplerTheme({
156
+ modalOverLayZ: 40,
157
+ } satisfies KeplerThemeOverrides),
158
+ modalPortalTarget: 'body',
100
159
  actionLogging: false,
101
160
  });
102
161
  ```
103
162
 
163
+ Notes:
164
+
165
+ - `basicKeplerProps` is for base Kepler registration/component props.
166
+ - `keplerTheme` (optional) sets the theme passed to Kepler `ThemeProvider`.
167
+ - `modalPortalTarget` controls modal portal placement: `'container'` (default)
168
+ or `'body'`.
169
+
170
+ ### Table selection and dataset ids
171
+
172
+ `tableSelection` controls which DuckDB tables Kepler exposes and how those
173
+ tables are represented in persisted Kepler layer and filter config.
174
+
175
+ ```ts
176
+ createKeplerSlice({
177
+ tableSelection: {
178
+ defaultDbSchema: {
179
+ database: 'project',
180
+ schema: 'main',
181
+ },
182
+ includeTable: (table) => table.table.database === 'project',
183
+ },
184
+ });
185
+ ```
186
+
187
+ By default, tables in `defaultDbSchema` use bare dataset ids such as `places`.
188
+ Tables outside that database/schema use qualified SQL table references. This
189
+ keeps common main-schema project tables readable while preserving enough
190
+ identity for tables from other schemas.
191
+
192
+ Use `includeTable` to hide tables from Kepler's Add Layer UI and to skip matching
193
+ saved dataset ids during dataset synchronization. Host apps commonly use this to
194
+ hide attached databases that will not be available when a project is reopened.
195
+
196
+ If the default dataset-id policy is not right for your app, provide both
197
+ `getDatasetIdForTable` and `findTableForDatasetId` so new layers and restored
198
+ layers agree on the same identity scheme:
199
+
200
+ ```ts
201
+ createKeplerSlice({
202
+ tableSelection: {
203
+ getDatasetIdForTable: (table) =>
204
+ `${table.table.schema}:${table.table.table}`,
205
+ findTableForDatasetId: (tables, datasetId) => {
206
+ const [schema, tableName] = datasetId.split(':');
207
+ return tables.find(
208
+ (table) =>
209
+ table.table.schema === schema && table.table.table === tableName,
210
+ );
211
+ },
212
+ getTableLabel: (table) =>
213
+ [table.table.schema, table.table.table].filter(Boolean).join('.'),
214
+ },
215
+ });
216
+ ```
217
+
218
+ `getTableLabel` only affects display labels in Kepler table selectors. It does
219
+ not change persisted dataset ids.
220
+
104
221
  ## Related packages
105
222
 
106
223
  - `@sqlrooms/artifacts` for artifact-backed map tabs
@@ -7,9 +7,12 @@ import { RoomShellSliceState, type StateCreator } from '@sqlrooms/room-shell';
7
7
  import type { AnyAction, Store as ReduxStore } from 'redux';
8
8
  import { Dispatch, Middleware } from 'redux';
9
9
  import { ReduxLoggerOptions } from 'redux-logger';
10
+ import type { DefaultTheme } from 'styled-components';
11
+ import { type KeplerTableSelectionOptions } from './keplerTableSelection';
10
12
  export type KeplerGLBasicProps = {
11
13
  mapboxApiAccessToken?: string;
12
14
  };
15
+ export type KeplerModalPortalTarget = 'body' | 'container';
13
16
  export type CreateInitialMapKeplerStateContext = {
14
17
  reason: 'initialize' | 'create-map' | 'duplicate-map' | 'register-map' | 'sync-config';
15
18
  defaultInitialMapKeplerState: Partial<KeplerGlState>;
@@ -20,9 +23,26 @@ export type CreateKeplerSliceOptions = {
20
23
  config?: Partial<KeplerSliceConfig>;
21
24
  createInitialMapKeplerState?: (context: CreateInitialMapKeplerStateContext) => Partial<KeplerGlState>;
22
25
  basicKeplerProps?: Partial<KeplerGLBasicProps>;
26
+ /**
27
+ * Theme passed to Kepler's ThemeProvider.
28
+ * Use createKeplerTheme() to merge app-level overrides into the default theme.
29
+ */
30
+ keplerTheme?: DefaultTheme;
31
+ /**
32
+ * Where the Kepler modal (Add Map Style, Export, etc.) should be portaled.
33
+ * - 'body': portals to document.body (escapes stacking contexts)
34
+ * - 'container': portals inside the kepler map container element
35
+ * @default 'container'
36
+ */
37
+ modalPortalTarget?: KeplerModalPortalTarget;
23
38
  actionLogging?: boolean | ReduxLoggerOptions;
24
39
  middlewares?: Middleware[];
25
40
  applicationConfig?: KeplerApplicationConfig;
41
+ /**
42
+ * Controls which DuckDB tables appear in Kepler's Add Layer menu and how
43
+ * those tables are represented in saved Kepler dataset ids.
44
+ */
45
+ tableSelection?: KeplerTableSelectionOptions;
26
46
  /**
27
47
  * Called when a kepler action is dispatched
28
48
  * @param mapId - The map id
@@ -45,11 +65,44 @@ export declare function hasMapId(action: KeplerAction): action is KeplerAction &
45
65
  export type KeplerGlReduxState = {
46
66
  [id: string]: KeplerGlState;
47
67
  };
68
+ export type AddTableToMapLoadOptions = {
69
+ /**
70
+ * Load the table under an explicit Kepler dataset id.
71
+ *
72
+ * Normal callers should omit this so the table-selection policy decides the
73
+ * id. Restore uses it to satisfy already-saved layer/filter dataIds.
74
+ */
75
+ datasetId?: string;
76
+ };
77
+ export type AddTableToMapParams = {
78
+ mapId: string;
79
+ /**
80
+ * Table reference to load. This can also be an existing/saved Kepler dataset
81
+ * id when the table-selection policy can resolve it back to a table.
82
+ */
83
+ tableName: string;
84
+ options?: AddDataToMapPayload['options'];
85
+ config?: AddDataToMapPayload['config'];
86
+ /**
87
+ * Explicit Kepler dataset id to write into `datasets.info.id`.
88
+ *
89
+ * Most callers should omit this so `tableSelection.getDatasetIdForTable`
90
+ * controls new ids. Restore passes it to preserve saved layer/filter dataIds.
91
+ */
92
+ datasetId?: string;
93
+ };
94
+ export type AddTableToMapFn = {
95
+ (params: AddTableToMapParams): Promise<void>;
96
+ (mapId: string, tableName: string, options?: AddDataToMapPayload['options'], config?: AddDataToMapPayload['config'], loadOptions?: AddTableToMapLoadOptions): Promise<void>;
97
+ };
48
98
  export type KeplerSliceState = {
49
99
  kepler: {
50
100
  config: KeplerSliceConfig;
51
101
  map: KeplerGlReduxState;
52
102
  basicKeplerProps?: Partial<KeplerGLBasicProps>;
103
+ keplerTheme?: DefaultTheme;
104
+ modalPortalTarget: KeplerModalPortalTarget;
105
+ tableSelection: KeplerTableSelectionOptions;
53
106
  forwardDispatch: {
54
107
  [mapId: string]: Dispatch;
55
108
  };
@@ -70,7 +123,7 @@ export type KeplerSliceState = {
70
123
  updateTooltipFields: (mapId: string, datasetId: string, fieldNames: string[]) => void;
71
124
  toggleSplitMap: (mapId: string, index?: number) => void;
72
125
  toggleLayerForMap: (mapId: string, mapIndex: number, layerId: string) => void;
73
- addTableToMap: (mapId: string, tableName: string, options?: AddDataToMapPayload['options'], config?: AddDataToMapPayload['config']) => Promise<void>;
126
+ addTableToMap: AddTableToMapFn;
74
127
  addTileSetToMap: (mapId: string, tableName: string, tileset: {
75
128
  name: string;
76
129
  type: string;
@@ -102,7 +155,7 @@ export type KeplerSliceState = {
102
155
  __reduxProviderStore: ReduxStore<KeplerGlReduxState, AnyAction> | undefined;
103
156
  };
104
157
  };
105
- export declare function createKeplerSlice({ basicKeplerProps, config: initialConfigProps, createInitialMapKeplerState, actionLogging, middlewares: additionalMiddlewares, applicationConfig, onAction, }?: CreateKeplerSliceOptions): StateCreator<KeplerSliceState>;
158
+ export declare function createKeplerSlice({ basicKeplerProps, keplerTheme, modalPortalTarget, config: initialConfigProps, createInitialMapKeplerState, actionLogging, middlewares: additionalMiddlewares, applicationConfig, tableSelection, onAction, }?: CreateKeplerSliceOptions): StateCreator<KeplerSliceState>;
106
159
  type RoomStateWithDiscuss = RoomShellSliceState & KeplerSliceState;
107
160
  export declare function useStoreWithKepler<T>(selector: (state: RoomStateWithDiscuss) => T): T;
108
161
  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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"}
@@ -14,6 +14,8 @@ import { produce, setAutoFreeze } from 'immer';
14
14
  import { taskMiddleware } from 'react-palm/tasks';
15
15
  import { compose } from 'redux';
16
16
  import { createLogger } from 'redux-logger';
17
+ import { getUnqualifiedSqlIdentifier } from '@sqlrooms/duckdb-core';
18
+ import { findKeplerTableForDatasetId, getKeplerDatasetIdForTable, getKeplerTableLabel, } from './keplerTableSelection';
17
19
  setAutoFreeze(false); // Kepler attempts to mutate redux state, so we need to disable immer's auto freeze to avoid errors
18
20
  const KeplerGLSchemaManager = new KeplerGLSchemaClass();
19
21
  class DesktopKeplerTable extends KeplerTable {
@@ -29,6 +31,7 @@ function createDefaultMapKeplerState(resolvedTheme) {
29
31
  },
30
32
  uiState: {
31
33
  ...INITIAL_UI_STATE,
34
+ activeSidePanel: null,
32
35
  currentModal: null,
33
36
  mapControls: {
34
37
  visibleLayers: INITIAL_UI_STATE.mapControls.visibleLayers,
@@ -75,6 +78,25 @@ export function hasMapId(action) {
75
78
  action.payload.meta !== null &&
76
79
  '_id_' in action.payload.meta);
77
80
  }
81
+ function normalizeAddTableToMapParams(paramsOrMapId, tableName, options = {}, config = {}, loadOptions = {}) {
82
+ if (typeof paramsOrMapId === 'object') {
83
+ return {
84
+ options: {},
85
+ config: {},
86
+ ...paramsOrMapId,
87
+ };
88
+ }
89
+ if (!tableName) {
90
+ throw new Error('addTableToMap requires a tableName.');
91
+ }
92
+ return {
93
+ mapId: paramsOrMapId,
94
+ tableName,
95
+ options,
96
+ config,
97
+ datasetId: loadOptions.datasetId,
98
+ };
99
+ }
78
100
  // Auto save will be triggered in middleware on every kepler action
79
101
  // skip these actions to avoid unnecessary save
80
102
  const SKIP_AUTO_SAVE_ACTIONS = [
@@ -82,7 +104,7 @@ const SKIP_AUTO_SAVE_ACTIONS = [
82
104
  KeplerActionTypes.UPDATE_MAP,
83
105
  KeplerActionTypes.MOUSE_MOVE,
84
106
  ];
85
- export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfigProps, createInitialMapKeplerState, actionLogging = false, middlewares: additionalMiddlewares = [], applicationConfig, onAction, } = {}) {
107
+ export function createKeplerSlice({ basicKeplerProps = {}, keplerTheme, modalPortalTarget = 'container', config: initialConfigProps, createInitialMapKeplerState, actionLogging = false, middlewares: additionalMiddlewares = [], applicationConfig, tableSelection = {}, onAction, } = {}) {
86
108
  const initialConfig = createDefaultKeplerConfig(initialConfigProps);
87
109
  initApplicationConfig({
88
110
  table: DesktopKeplerTable,
@@ -104,6 +126,23 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
104
126
  }
105
127
  };
106
128
  return createSlice((set, get, _store) => {
129
+ function getDefaultDbSchema() {
130
+ const currentDatabase = get().db.currentDatabase;
131
+ const currentSchema = get().db.currentSchema;
132
+ if (!currentDatabase || !currentSchema) {
133
+ return undefined;
134
+ }
135
+ return {
136
+ database: currentDatabase,
137
+ schema: currentSchema,
138
+ };
139
+ }
140
+ const resolvedTableSelection = {
141
+ ...tableSelection,
142
+ };
143
+ if (!resolvedTableSelection.defaultDbSchema) {
144
+ resolvedTableSelection.defaultDbSchema = getDefaultDbSchema;
145
+ }
107
146
  function resolveInitialMapKeplerState(context) {
108
147
  const resolvedTheme = getTheme();
109
148
  const defaultInitialMapKeplerState = createDefaultMapKeplerState(resolvedTheme);
@@ -148,6 +187,9 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
148
187
  kepler: {
149
188
  config: initialConfig,
150
189
  basicKeplerProps,
190
+ keplerTheme,
191
+ modalPortalTarget,
192
+ tableSelection: resolvedTableSelection,
151
193
  map: {},
152
194
  isRestoringConfig: false,
153
195
  dispatchAction: () => { },
@@ -272,13 +314,25 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
272
314
  get().kepler.registerKeplerMapIfNotExists(mapId);
273
315
  get().kepler.dispatchAction(mapId, toggleLayerForMapAction(mapIndex, layerId));
274
316
  },
275
- addTableToMap: async (mapId, tableName, options = {}, config = {}) => {
317
+ addTableToMap: (async (paramsOrMapId, legacyTableName, legacyOptions, legacyConfig, legacyLoadOptions) => {
318
+ const { mapId, tableName, options, config, datasetId: explicitDatasetId, } = normalizeAddTableToMapParams(paramsOrMapId, legacyTableName, legacyOptions, legacyConfig, legacyLoadOptions);
319
+ const tableSelection = get().kepler.tableSelection;
320
+ const table = findKeplerTableForDatasetId(get().db.tables, tableName, tableSelection);
321
+ const sqlTableName = table ? table.table.toString() : tableName;
322
+ let datasetId = explicitDatasetId;
323
+ if (!datasetId && table) {
324
+ datasetId = getKeplerDatasetIdForTable(table, tableSelection);
325
+ }
326
+ if (!datasetId) {
327
+ datasetId =
328
+ getUnqualifiedSqlIdentifier(String(sqlTableName)) ?? tableName;
329
+ }
276
330
  const connector = await get().db.getConnector();
277
331
  const duckDbColumns = await getDuckDBColumnTypes({
278
332
  query: (query) => connector.query(query).result,
279
- }, tableName);
333
+ }, sqlTableName);
280
334
  const tableDuckDBTypes = getDuckDBColumnTypesMap(duckDbColumns);
281
- const adjustedQuery = castDuckDBTypesForKepler(tableName, duckDbColumns);
335
+ const adjustedQuery = castDuckDBTypesForKepler(sqlTableName, duckDbColumns);
282
336
  const arrowResult = await connector.query(adjustedQuery).result;
283
337
  setGeoArrowWKBExtension(arrowResult, duckDbColumns);
284
338
  // TODO remove once DuckDB doesn't drop geoarrow metadata
@@ -286,14 +340,22 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
286
340
  const fields = arrowSchemaToFields(arrowResult, tableDuckDBTypes);
287
341
  const cols = Array.from({ length: arrowResult.numCols }, (_, i) => arrowResult.getChildAt(i)).filter((col) => col);
288
342
  if (fields && cols) {
343
+ let label = tableName;
344
+ if (table) {
345
+ label = getKeplerTableLabel(table, tableSelection);
346
+ }
347
+ else {
348
+ label =
349
+ getUnqualifiedSqlIdentifier(String(sqlTableName)) ?? tableName;
350
+ }
289
351
  const datasets = {
290
352
  data: { fields, cols, rows: [], arrowTable: arrowResult },
291
- info: { label: tableName, id: tableName },
292
- metadata: { tableName },
353
+ info: { label, id: datasetId },
354
+ metadata: { tableName: sqlTableName },
293
355
  };
294
356
  get().kepler.dispatchAction(mapId, addDataToMap({ datasets, options, config }));
295
357
  }
296
- },
358
+ }),
297
359
  ensureMap: (mapId, name) => {
298
360
  const now = Date.now();
299
361
  set((state) => produce(state, (draft) => {
@@ -355,15 +417,30 @@ export function createKeplerSlice({ basicKeplerProps = {}, config: initialConfig
355
417
  referencedDataIds.add(dataId);
356
418
  }
357
419
  }
358
- const availableTables = new Set(get()
359
- .db.tables.filter((t) => t.table.schema === 'main')
360
- .map((t) => t.table.table));
420
+ const availableTables = get().db.tables;
361
421
  for (const dataId of referencedDataIds) {
362
- if (!keplerDatasets?.[dataId] &&
363
- availableTables.has(dataId)) {
364
- await get().kepler.addTableToMap(mapId, dataId, {
365
- autoCreateLayers: false,
366
- centerMap: false,
422
+ if (keplerDatasets?.[dataId]) {
423
+ continue;
424
+ }
425
+ const table = findKeplerTableForDatasetId(availableTables, dataId, get().kepler.tableSelection);
426
+ if (!table) {
427
+ continue;
428
+ }
429
+ try {
430
+ await get().kepler.addTableToMap({
431
+ mapId,
432
+ tableName: dataId,
433
+ options: {
434
+ autoCreateLayers: false,
435
+ centerMap: false,
436
+ },
437
+ datasetId: dataId,
438
+ });
439
+ }
440
+ catch (e) {
441
+ console.error('syncKeplerDatasets: addTableToMap failed', {
442
+ dataId,
443
+ e,
367
444
  });
368
445
  }
369
446
  }