@sqlrooms/kepler 0.28.0-rc.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,103 @@
1
- SQLRooms integration for [Kepler.gl](http://kepler.gl)
1
+ Kepler.gl integration for SQLRooms.
2
2
 
3
- Refer to the [Kepler integration example](https://github.com/sqlrooms/examples/tree/main/kepler).
3
+ Use this package when you want a **map-first analytics experience** in a SQLRooms app, backed by DuckDB tables and SQL.
4
+
5
+ ## What this package provides
6
+
7
+ - `createKeplerSlice()` to add Kepler state/actions to your Room store
8
+ - `KeplerMapContainer` and `KeplerPlotContainer` for rendering maps/overlays
9
+ - `KeplerSidePanels` for layer/filter/interaction UI
10
+ - utilities for map config persistence and dataset synchronization
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @sqlrooms/kepler @sqlrooms/room-shell @sqlrooms/duckdb @sqlrooms/ui
16
+ ```
17
+
18
+ ## Quick start
19
+
20
+ ```tsx
21
+ import {useEffect} from 'react';
22
+ import {
23
+ createKeplerSlice,
24
+ KeplerMapContainer,
25
+ KeplerSliceState,
26
+ } from '@sqlrooms/kepler';
27
+ import {
28
+ createRoomShellSlice,
29
+ createRoomStore,
30
+ RoomShell,
31
+ RoomShellSliceState,
32
+ } from '@sqlrooms/room-shell';
33
+
34
+ type RoomState = RoomShellSliceState & KeplerSliceState;
35
+
36
+ export const {roomStore, useRoomStore} = createRoomStore<RoomState>(
37
+ (set, get, store) => ({
38
+ ...createRoomShellSlice({
39
+ config: {
40
+ dataSources: [
41
+ {
42
+ type: 'url',
43
+ tableName: 'earthquakes',
44
+ url: 'https://huggingface.co/datasets/sqlrooms/earthquakes/resolve/main/earthquakes.parquet',
45
+ },
46
+ ],
47
+ },
48
+ })(set, get, store),
49
+ ...createKeplerSlice()(set, get, store),
50
+ }),
51
+ );
52
+
53
+ function MapPanel() {
54
+ const mapId = useRoomStore((state) => state.kepler.config.currentMapId);
55
+ const addTableToMap = useRoomStore((state) => state.kepler.addTableToMap);
56
+ const isTableReady = useRoomStore((state) =>
57
+ Boolean(state.db.findTableByName('earthquakes')),
58
+ );
59
+
60
+ useEffect(() => {
61
+ if (!isTableReady || !mapId) return;
62
+ void addTableToMap(mapId, 'earthquakes', {
63
+ autoCreateLayers: true,
64
+ centerMap: true,
65
+ });
66
+ }, [isTableReady, mapId, addTableToMap]);
67
+
68
+ if (!mapId) return null;
69
+
70
+ return <KeplerMapContainer mapId={mapId} />;
71
+ }
72
+
73
+ export function App() {
74
+ return (
75
+ <RoomShell roomStore={roomStore} className="h-screen">
76
+ <MapPanel />
77
+ </RoomShell>
78
+ );
79
+ }
80
+ ```
81
+
82
+ ## Common customization
83
+
84
+ Pass options to `createKeplerSlice()`:
85
+
86
+ ```ts
87
+ createKeplerSlice({
88
+ basicKeplerProps: {
89
+ mapboxApiAccessToken: import.meta.env.VITE_MAPBOX_TOKEN,
90
+ },
91
+ actionLogging: false,
92
+ });
93
+ ```
94
+
95
+ ## Related packages
96
+
97
+ - `@sqlrooms/kepler-config` for Zod schemas used by persisted Kepler config
98
+ - `@sqlrooms/room-shell` for Room store composition and UI shell
99
+ - `@sqlrooms/duckdb` for DuckDB-backed table loading/querying
100
+
101
+ ## Examples
102
+
103
+ - Kepler example app: https://github.com/sqlrooms/examples/tree/main/kepler
@@ -1 +1 @@
1
- {"version":3,"file":"CustomInteractionManager.d.ts","sourceRoot":"","sources":["../../src/components/CustomInteractionManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AA2FzC,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA0E9D,CAAC"}
1
+ {"version":3,"file":"CustomInteractionManager.d.ts","sourceRoot":"","sources":["../../src/components/CustomInteractionManager.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6B,MAAM,OAAO,CAAC;AA2FlD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA6E9D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback } from 'react';
2
+ import { useCallback, useMemo } from 'react';
3
3
  import { Switch, Checkbox, useTheme } from '@sqlrooms/ui';
4
4
  import { FormattedMessage } from '@kepler.gl/localization';
5
5
  import { useKeplerStateActions } from '../hooks/useKeplerStateActions';
@@ -18,7 +18,7 @@ const TooltipPanel = ({ tooltipConfig, coordinateConfig, datasets, isDark, handl
18
18
  }, [handleConfigChange]);
19
19
  if (!tooltipConfig)
20
20
  return null;
21
- return (_jsxs("div", { children: [_jsx(SimpleInteractionPanel, { configId: "tooltip", config: tooltipConfig, label: "Tooltip", onConfigChange: handleConfigChange }), tooltipConfig.enabled && (_jsxs("div", { className: "pl-4 pr-2", children: [_jsxs("div", { className: "flex items-center space-x-2 py-2", children: [_jsx(Checkbox, { checked: coordinateConfig?.enabled || false, onCheckedChange: handleCoordinateToggle, className: "shadow-none" }), _jsxs("span", { className: "text-muted-foreground text-xs", children: ["Show ", _jsx(FormattedMessage, { id: "interactions.coordinate" })] })] }), _jsx(CustomTooltipConfig, { datasets: datasets, config: tooltipConfig.config, onChange: handleTooltipConfigChange, onDisplayFormatChange: setColumnDisplayFormat, isDark: isDark })] }))] }));
21
+ return (_jsxs("div", { children: [_jsx(SimpleInteractionPanel, { configId: "tooltip", config: tooltipConfig, label: "Tooltip", onConfigChange: handleConfigChange }), tooltipConfig.enabled && (_jsxs("div", { className: "pr-2 pl-4", children: [_jsxs("div", { className: "flex items-center space-x-2 py-2", children: [_jsx(Checkbox, { checked: coordinateConfig?.enabled || false, onCheckedChange: handleCoordinateToggle, className: "shadow-none" }), _jsxs("span", { className: "text-muted-foreground text-xs", children: ["Show ", _jsx(FormattedMessage, { id: "interactions.coordinate" })] })] }), _jsx(CustomTooltipConfig, { datasets: datasets, config: tooltipConfig.config, onChange: handleTooltipConfigChange, onDisplayFormatChange: setColumnDisplayFormat, isDark: isDark })] }))] }));
22
22
  };
23
23
  export const CustomInteractionManager = ({ mapId, }) => {
24
24
  const { keplerActions, keplerState } = useKeplerStateActions({ mapId });
@@ -27,7 +27,8 @@ export const CustomInteractionManager = ({ mapId, }) => {
27
27
  const isDark = theme === 'dark' ||
28
28
  (theme === 'system' &&
29
29
  window.matchMedia('(prefers-color-scheme: dark)').matches);
30
- const interactionConfig = keplerState?.visState.interactionConfig || {};
30
+ const rawInteractionConfig = keplerState?.visState.interactionConfig;
31
+ const interactionConfig = useMemo(() => rawInteractionConfig ?? {}, [rawInteractionConfig]);
31
32
  const datasets = keplerState?.visState.datasets || {};
32
33
  const { interactionConfigChange, setColumnDisplayFormat } = keplerActions.visStateActions;
33
34
  const handleConfigChange = useCallback((configId, newConfig) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CustomInteractionManager.js","sourceRoot":"","sources":["../../src/components/CustomInteractionManager.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {useCallback} from 'react';\nimport {Switch, Checkbox, useTheme} from '@sqlrooms/ui';\n\nimport {InteractionConfig} from '@kepler.gl/types';\nimport {FormattedMessage} from '@kepler.gl/localization';\n\nimport {useKeplerStateActions} from '../hooks/useKeplerStateActions';\nimport {CustomTooltipConfig} from './CustomTooltipConfig';\n\nconst SimpleInteractionPanel: React.FC<{\n configId: string;\n config: any;\n label: string;\n onConfigChange: (configId: string, newConfig: any) => void;\n}> = ({configId, config, label, onConfigChange}) => {\n const toggleEnableConfig = useCallback(() => {\n onConfigChange(configId, {\n enabled: !config.enabled,\n });\n }, [configId, config.enabled, onConfigChange]);\n\n return (\n <div className=\"flex items-center justify-between p-2\">\n <div className=\"text-muted-foreground text-sm font-medium\">{label}</div>\n <Switch\n checked={config.enabled}\n onCheckedChange={toggleEnableConfig}\n className=\"data-[state=checked]:bg-primary data-[state=unchecked]:bg-secondary\"\n />\n </div>\n );\n};\n\nconst TooltipPanel: React.FC<{\n tooltipConfig: any;\n coordinateConfig: any;\n datasets: any;\n isDark: boolean;\n handleConfigChange: (configId: string, newConfig: any) => void;\n handleCoordinateToggle: () => void;\n setColumnDisplayFormat: (format: any) => void;\n}> = ({\n tooltipConfig,\n coordinateConfig,\n datasets,\n isDark,\n handleConfigChange,\n handleCoordinateToggle,\n setColumnDisplayFormat,\n}) => {\n const handleTooltipConfigChange = useCallback(\n (newConfig: any) => {\n handleConfigChange('tooltip', {config: newConfig});\n },\n [handleConfigChange],\n );\n\n if (!tooltipConfig) return null;\n return (\n <div>\n <SimpleInteractionPanel\n configId=\"tooltip\"\n config={tooltipConfig}\n label=\"Tooltip\"\n onConfigChange={handleConfigChange}\n />\n {tooltipConfig.enabled && (\n <div className=\"pl-4 pr-2\">\n <div className=\"flex items-center space-x-2 py-2\">\n <Checkbox\n checked={coordinateConfig?.enabled || false}\n onCheckedChange={handleCoordinateToggle}\n className=\"shadow-none\"\n />\n <span className=\"text-muted-foreground text-xs\">\n Show <FormattedMessage id=\"interactions.coordinate\" />\n </span>\n </div>\n <CustomTooltipConfig\n datasets={datasets}\n config={tooltipConfig.config}\n onChange={handleTooltipConfigChange}\n onDisplayFormatChange={setColumnDisplayFormat}\n isDark={isDark}\n />\n </div>\n )}\n </div>\n );\n};\n\nexport const CustomInteractionManager: React.FC<{mapId: string}> = ({\n mapId,\n}) => {\n const {keplerActions, keplerState} = useKeplerStateActions({mapId});\n const {theme} = useTheme();\n\n // Determine if dark mode is active\n const isDark =\n theme === 'dark' ||\n (theme === 'system' &&\n window.matchMedia('(prefers-color-scheme: dark)').matches);\n\n const interactionConfig: Partial<InteractionConfig> =\n keplerState?.visState.interactionConfig || {};\n const datasets = keplerState?.visState.datasets || {};\n const {interactionConfigChange, setColumnDisplayFormat} =\n keplerActions.visStateActions;\n\n const handleConfigChange = useCallback(\n (configId: string, newConfig: any) => {\n const currentConfig =\n interactionConfig[configId as keyof InteractionConfig];\n if (currentConfig && typeof currentConfig === 'object') {\n interactionConfigChange({\n ...currentConfig,\n ...newConfig,\n });\n }\n },\n [interactionConfig, interactionConfigChange],\n );\n\n // Handle coordinate display toggle\n const handleCoordinateToggle = useCallback(() => {\n const coordinateConfig = interactionConfig.coordinate;\n if (coordinateConfig && typeof coordinateConfig === 'object') {\n interactionConfigChange({\n ...coordinateConfig,\n enabled: !coordinateConfig.enabled,\n });\n }\n }, [interactionConfig.coordinate, interactionConfigChange]);\n\n return (\n <div className=\"interaction-manager\">\n <div className=\"space-y-2\">\n <TooltipPanel\n tooltipConfig={interactionConfig.tooltip}\n coordinateConfig={interactionConfig.coordinate}\n datasets={datasets}\n isDark={isDark}\n handleConfigChange={handleConfigChange}\n handleCoordinateToggle={handleCoordinateToggle}\n setColumnDisplayFormat={setColumnDisplayFormat}\n />\n {interactionConfig.geocoder && (\n <SimpleInteractionPanel\n configId=\"geocoder\"\n config={interactionConfig.geocoder}\n label=\"Location search\"\n onConfigChange={handleConfigChange}\n />\n )}\n {interactionConfig.brush && (\n <SimpleInteractionPanel\n configId=\"brush\"\n config={interactionConfig.brush}\n label=\"Brush filter\"\n onConfigChange={handleConfigChange}\n />\n )}\n </div>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"CustomInteractionManager.js","sourceRoot":"","sources":["../../src/components/CustomInteractionManager.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {useCallback, useMemo} from 'react';\nimport {Switch, Checkbox, useTheme} from '@sqlrooms/ui';\n\nimport {InteractionConfig} from '@kepler.gl/types';\nimport {FormattedMessage} from '@kepler.gl/localization';\n\nimport {useKeplerStateActions} from '../hooks/useKeplerStateActions';\nimport {CustomTooltipConfig} from './CustomTooltipConfig';\n\nconst SimpleInteractionPanel: React.FC<{\n configId: string;\n config: any;\n label: string;\n onConfigChange: (configId: string, newConfig: any) => void;\n}> = ({configId, config, label, onConfigChange}) => {\n const toggleEnableConfig = useCallback(() => {\n onConfigChange(configId, {\n enabled: !config.enabled,\n });\n }, [configId, config.enabled, onConfigChange]);\n\n return (\n <div className=\"flex items-center justify-between p-2\">\n <div className=\"text-muted-foreground text-sm font-medium\">{label}</div>\n <Switch\n checked={config.enabled}\n onCheckedChange={toggleEnableConfig}\n className=\"data-[state=checked]:bg-primary data-[state=unchecked]:bg-secondary\"\n />\n </div>\n );\n};\n\nconst TooltipPanel: React.FC<{\n tooltipConfig: any;\n coordinateConfig: any;\n datasets: any;\n isDark: boolean;\n handleConfigChange: (configId: string, newConfig: any) => void;\n handleCoordinateToggle: () => void;\n setColumnDisplayFormat: (format: any) => void;\n}> = ({\n tooltipConfig,\n coordinateConfig,\n datasets,\n isDark,\n handleConfigChange,\n handleCoordinateToggle,\n setColumnDisplayFormat,\n}) => {\n const handleTooltipConfigChange = useCallback(\n (newConfig: any) => {\n handleConfigChange('tooltip', {config: newConfig});\n },\n [handleConfigChange],\n );\n\n if (!tooltipConfig) return null;\n return (\n <div>\n <SimpleInteractionPanel\n configId=\"tooltip\"\n config={tooltipConfig}\n label=\"Tooltip\"\n onConfigChange={handleConfigChange}\n />\n {tooltipConfig.enabled && (\n <div className=\"pr-2 pl-4\">\n <div className=\"flex items-center space-x-2 py-2\">\n <Checkbox\n checked={coordinateConfig?.enabled || false}\n onCheckedChange={handleCoordinateToggle}\n className=\"shadow-none\"\n />\n <span className=\"text-muted-foreground text-xs\">\n Show <FormattedMessage id=\"interactions.coordinate\" />\n </span>\n </div>\n <CustomTooltipConfig\n datasets={datasets}\n config={tooltipConfig.config}\n onChange={handleTooltipConfigChange}\n onDisplayFormatChange={setColumnDisplayFormat}\n isDark={isDark}\n />\n </div>\n )}\n </div>\n );\n};\n\nexport const CustomInteractionManager: React.FC<{mapId: string}> = ({\n mapId,\n}) => {\n const {keplerActions, keplerState} = useKeplerStateActions({mapId});\n const {theme} = useTheme();\n\n // Determine if dark mode is active\n const isDark =\n theme === 'dark' ||\n (theme === 'system' &&\n window.matchMedia('(prefers-color-scheme: dark)').matches);\n\n const rawInteractionConfig = keplerState?.visState.interactionConfig;\n const interactionConfig = useMemo<Partial<InteractionConfig>>(\n () => rawInteractionConfig ?? {},\n [rawInteractionConfig],\n );\n const datasets = keplerState?.visState.datasets || {};\n const {interactionConfigChange, setColumnDisplayFormat} =\n keplerActions.visStateActions;\n\n const handleConfigChange = useCallback(\n (configId: string, newConfig: any) => {\n const currentConfig =\n interactionConfig[configId as keyof InteractionConfig];\n if (currentConfig && typeof currentConfig === 'object') {\n interactionConfigChange({\n ...currentConfig,\n ...newConfig,\n });\n }\n },\n [interactionConfig, interactionConfigChange],\n );\n\n // Handle coordinate display toggle\n const handleCoordinateToggle = useCallback(() => {\n const coordinateConfig = interactionConfig.coordinate;\n if (coordinateConfig && typeof coordinateConfig === 'object') {\n interactionConfigChange({\n ...coordinateConfig,\n enabled: !coordinateConfig.enabled,\n });\n }\n }, [interactionConfig.coordinate, interactionConfigChange]);\n\n return (\n <div className=\"interaction-manager\">\n <div className=\"space-y-2\">\n <TooltipPanel\n tooltipConfig={interactionConfig.tooltip}\n coordinateConfig={interactionConfig.coordinate}\n datasets={datasets}\n isDark={isDark}\n handleConfigChange={handleConfigChange}\n handleCoordinateToggle={handleCoordinateToggle}\n setColumnDisplayFormat={setColumnDisplayFormat}\n />\n {interactionConfig.geocoder && (\n <SimpleInteractionPanel\n configId=\"geocoder\"\n config={interactionConfig.geocoder}\n label=\"Location search\"\n onConfigChange={handleConfigChange}\n />\n )}\n {interactionConfig.brush && (\n <SimpleInteractionPanel\n configId=\"brush\"\n config={interactionConfig.brush}\n label=\"Brush filter\"\n onConfigChange={handleConfigChange}\n />\n )}\n </div>\n </div>\n );\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/kepler",
3
- "version": "0.28.0-rc.0",
3
+ "version": "0.28.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -34,11 +34,11 @@
34
34
  "@kepler.gl/types": "3.2.4",
35
35
  "@kepler.gl/utils": "3.2.4",
36
36
  "@paralleldrive/cuid2": "^3.0.0",
37
- "@sqlrooms/duckdb": "0.28.0-rc.0",
38
- "@sqlrooms/kepler-config": "0.28.0-rc.0",
39
- "@sqlrooms/room-shell": "0.28.0-rc.0",
40
- "@sqlrooms/s3-browser": "0.28.0-rc.0",
41
- "@sqlrooms/ui": "0.28.0-rc.0",
37
+ "@sqlrooms/duckdb": "0.28.0",
38
+ "@sqlrooms/kepler-config": "0.28.0",
39
+ "@sqlrooms/room-shell": "0.28.0",
40
+ "@sqlrooms/s3-browser": "0.28.0",
41
+ "@sqlrooms/ui": "0.28.0",
42
42
  "apache-arrow": "17.0.0",
43
43
  "immer": "^11.0.1",
44
44
  "lucide-react": "^0.556.0",
@@ -62,5 +62,5 @@
62
62
  "devDependencies": {
63
63
  "@types/redux-logger": "^3.0.13"
64
64
  },
65
- "gitHead": "87a478edbff690e04c38cc717db8e11e844565c8"
65
+ "gitHead": "dcac54f8adf77240e293c93d224a0ce9fd8142a9"
66
66
  }