Skip to content

feat: add split map functionality and related context to Kepler - #563

Merged
lixun910 merged 3 commits into
mainfrom
562-keplerslice-add-splitmap-action-to-create-dual-map-view-in-kepler
Apr 27, 2026
Merged

lixun910 merged 3 commits into
mainfrom
562-keplerslice-add-splitmap-action-to-create-dual-map-view-in-kepler

Conversation

@lixun910

@lixun910 lixun910 commented Apr 22, 2026 •

Copy link
Copy Markdown
Collaborator
  • add support for split map functionality in the Kepler map components
  • enable the display and control of multiple map panels side-by-side
  • update the legend and map container components to handle split map state

Summary by CodeRabbit

  • New Features
    • Added split-map mode allowing multiple map panels to be displayed and controlled simultaneously.
    • Map controls for toggling split view and per-panel layer visibility exposed to the UI.
    • Legends now show only the layers relevant to the active split panel.
    • Split-map control is enabled by default in the per-map UI state.

@lixun910 lixun910 linked an issue Apr 22, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Apr 22, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds split-map support: new Kepler slice methods for split-map and per-map layer toggles, default split-map UI state, a SplitMapIndexContext, split-aware rendering of multiple MapContainer instances, and legend components that filter layers by split panel index.

Changes

Cohort / File(s) Summary
Kepler State Management
packages/kepler/src/KeplerSlice.ts
Adds public slice methods kepler.setFilterView, kepler.toggleSplitMap, kepler.toggleLayerForMap. Ensures maps are registered before dispatching actions and initializes mapControls.splitMap with { show: true, active: false }.
Map Container & Context
packages/kepler/src/components/KeplerMapContainer.tsx, packages/kepler/src/components/SplitMapIndexContext.ts
Adds SplitMapIndexContext, detects split mode via visState.splitMaps.length > 1, and conditionally renders multiple MapContainer instances in a flex row with per-split mapFields and context-provided map index.
Legend Components
packages/kepler/src/components/CustomMapLegend.tsx, packages/kepler/src/components/CustomMapLegendPanel.tsx
MapLegend/CustomMapLegendPanel accept an optional mapIndex (or use SplitMapIndexContext) and filter legend items to layers present in the active split panel in split mode.
Barrel Exports
packages/kepler/src/index.ts
Re-exports SplitMapIndexContext for consumer access.

Sequence Diagram

sequenceDiagram
    actor User
    participant KeplerSlice as KeplerSlice (State)
    participant KeplerMapContainer as KeplerMapContainer
    participant SplitMapsContainer as SplitMapsContainer
    participant MapContainer as MapContainer (per-split)
    participant CustomMapLegend as CustomMapLegend
    User->>KeplerSlice: toggleSplitMap(mapId[, index])
    KeplerSlice->>KeplerSlice: register map if needed\nupdate splitMaps state
    KeplerSlice-->>KeplerMapContainer: state change
    KeplerMapContainer->>KeplerMapContainer: compute isSplit (splitMaps.length > 1)
    alt isSplit = true
        KeplerMapContainer->>SplitMapsContainer: render multiple MapContainer instances
        SplitMapsContainer->>MapContainer: provide SplitMapIndexContext (index)
        MapContainer->>CustomMapLegend: render with mapIndex from context
        CustomMapLegend->>CustomMapLegend: filter layers by split panel membership
        CustomMapLegend-->>User: display split-aware legend
    else isSplit = false
        KeplerMapContainer->>MapContainer: render single instance
        MapContainer->>CustomMapLegend: render default legend
        CustomMapLegend-->>User: display full legend
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • ilyabo
  • bdjulbic

Poem

🐰 I split the map to see both sides,
Context carries the index on rides.
Legends shrink to each panel's layers,
Kepler hums with twin-map flairs.
Hop, toggle, and view with joy! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding split map functionality and introducing a context for it.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 562-keplerslice-add-splitmap-action-to-create-dual-map-view-in-kepler

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lixun910
lixun910 requested a review from ilyabo April 22, 2026 22:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/kepler/src/components/CustomMapLegendPanel.tsx (1)

12-21: ⚠️ Potential issue | 🟡 Minor

Don't forward mapIndex into MapLegendPanel.

mapIndex is a custom prop added here, but it's being spread onto MapLegendPanel (from @kepler.gl/components), which doesn't declare it. At best it's ignored; at worst it propagates to a DOM node and triggers a React unknown-attribute warning. Follow the same destructure-then-spread pattern used in CustomMapLegend.tsx (lines 47–52).

♻️ Proposed fix
-  const CustomMapLegendPanel = (
-    props: MapLegendPanelProps & {mapIndex?: number},
-  ) => {
+  const CustomMapLegendPanel = ({
+    mapIndex: _mapIndex,
+    ...props
+  }: MapLegendPanelProps & {mapIndex?: number}) => {
     return (
       <>
         <style>{`.draggable-legend .map-control__panel-header { display: none !important; }`}</style>
         <MapLegendPanel {...props} />
       </>
     );
   };

Note: if the intent is to have the panel actually consume mapIndex (e.g., forward it down to the legend), you'll also need a wiring path — currently nothing reads it here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/kepler/src/components/CustomMapLegendPanel.tsx` around lines 12 -
21, The CustomMapLegendPanel currently spreads props (MapLegendPanelProps &
{mapIndex?: number}) directly into MapLegendPanel, which forwards the custom
mapIndex prop into a component that doesn't expect it; fix this by destructuring
mapIndex out of the incoming props in CustomMapLegendPanel (const {mapIndex,
...rest} = props) and then pass only the rest into MapLegendPanel
(MapLegendPanel {...rest}) so mapIndex is not forwarded to MapLegendPanel or any
DOM node; keep the existing style injection and only remove mapIndex from the
spread.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/kepler/src/KeplerSlice.ts`:
- Around line 595-601: The implementation of toggleSplitMap currently defines
the parameter as (mapId, index) and uses an unsafe cast (index as number);
update the implementation signature to accept an optional index parameter
(mapId, index?) to match the public type (toggleSplitMap: (mapId: string,
index?: number) => void) and remove the unnecessary "as number" cast; ensure the
body still calls get().kepler.registerKeplerMapIfNotExists(mapId) and
get().kepler.dispatchAction(mapId, toggleSplitMapAction(index)) so callers may
omit index safely.

---

Outside diff comments:
In `@packages/kepler/src/components/CustomMapLegendPanel.tsx`:
- Around line 12-21: The CustomMapLegendPanel currently spreads props
(MapLegendPanelProps & {mapIndex?: number}) directly into MapLegendPanel, which
forwards the custom mapIndex prop into a component that doesn't expect it; fix
this by destructuring mapIndex out of the incoming props in CustomMapLegendPanel
(const {mapIndex, ...rest} = props) and then pass only the rest into
MapLegendPanel (MapLegendPanel {...rest}) so mapIndex is not forwarded to
MapLegendPanel or any DOM node; keep the existing style injection and only
remove mapIndex from the spread.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e81da3b2-22c5-4186-b7f1-8fef59d36a7b

📥 Commits

Reviewing files that changed from the base of the PR and between a45a7ec and efb1826.

📒 Files selected for processing (5)
  • packages/kepler/src/KeplerSlice.ts
  • packages/kepler/src/components/CustomMapLegend.tsx
  • packages/kepler/src/components/CustomMapLegendPanel.tsx
  • packages/kepler/src/components/KeplerMapContainer.tsx
  • packages/kepler/src/index.ts

Comment thread packages/kepler/src/KeplerSlice.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/kepler/src/components/CustomMapLegend.tsx (1)

98-108: Use a stable key for legend items.

visibleLayers is a derived/filtered list, so key={index} ties React identity to position rather than to the layer. Toggling visibility, reordering layers, or switching split panels can shift indices and cause LayerLegendItem's local isExpanded state to "leak" between layers. Prefer layer.id.

♻️ Proposed fix
-            {visibleLayers.map((layer, index) => {
-              return (
-                <LayerLegendItem
-                  key={index}
-                  layer={layer}
-                  containerW={containerW}
-                  isExport={isExport}
-                  {...restProps}
-                />
-              );
-            })}
+            {visibleLayers.map((layer) => (
+              <LayerLegendItem
+                key={layer.id}
+                layer={layer}
+                containerW={containerW}
+                isExport={isExport}
+                {...restProps}
+              />
+            ))}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/kepler/src/components/CustomMapLegend.tsx` around lines 98 - 108,
The legend items use array index for React keys which causes identity to shift;
update the mapping over visibleLayers so LayerLegendItem uses a stable unique
key (e.g., layer.id) instead of key={index}. Locate the map where
visibleLayers.map(...) renders <LayerLegendItem ... /> and replace the
index-based key with the layer's unique identifier (layer.id) to prevent local
state (like isExpanded) from leaking between different layers when order or
filtering changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/kepler/src/components/CustomMapLegend.tsx`:
- Around line 98-108: The legend items use array index for React keys which
causes identity to shift; update the mapping over visibleLayers so
LayerLegendItem uses a stable unique key (e.g., layer.id) instead of
key={index}. Locate the map where visibleLayers.map(...) renders
<LayerLegendItem ... /> and replace the index-based key with the layer's unique
identifier (layer.id) to prevent local state (like isExpanded) from leaking
between different layers when order or filtering changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 204fac4a-a10d-4114-bfe8-f79300f07923

📥 Commits

Reviewing files that changed from the base of the PR and between efb1826 and cf183cb.

📒 Files selected for processing (5)
  • packages/kepler/src/KeplerSlice.ts
  • packages/kepler/src/components/CustomMapLegend.tsx
  • packages/kepler/src/components/KeplerMapContainer.tsx
  • packages/kepler/src/components/SplitMapIndexContext.ts
  • packages/kepler/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/kepler/src/components/SplitMapIndexContext.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/kepler/src/index.ts
  • packages/kepler/src/KeplerSlice.ts

@lixun910

Copy link
Copy Markdown
Collaborator Author

@ilyabo

@lixun910
lixun910 merged commit 9328d21 into main Apr 27, 2026
4 checks passed
@lixun910
lixun910 deleted the 562-keplerslice-add-splitmap-action-to-create-dual-map-view-in-kepler branch April 27, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KeplerSlice: add splitMap action to create dual map view in kepler

2 participants