Skip to content

fix(deck): improve map layer settings and color scale behavior - #789

Merged
igorDykhta merged 8 commits into
mainfrom
igr/deck-maps-fixes-23
Jul 3, 2026
Merged

igorDykhta merged 8 commits into
mainfrom
igr/deck-maps-fixes-23

Conversation

@igorDykhta

@igorDykhta igorDykhta commented Jul 2, 2026 •

Copy link
Copy Markdown
Collaborator
  • Add elevation scale slider (0.01–10x) for extruded layers
  • Fix extrusion toggle defaulting getElevation to 1 to prevent geometry extruding below zero
  • Fix color scale not resetting visually when disabled (missing updateTriggers for static color props)
  • Fix elevation column changes not applying until scale is adjusted (missing updateTriggers for getElevation)
  • Deduplicate map legends by title
  • Default showLegends to true in dashboard renderer

Summary by CodeRabbit

  • New Features
    • Added an “Elevation scale” control for extruded layers to adjust 3D height intensity.
    • Legends now default to shown unless showLegends is explicitly set to false.
  • Bug Fixes
    • Improved extrusion toggling to preserve an existing elevation setting and restore it when disabling 3D.
    • Refined map update triggers for color scales and elevation so visual styling updates correctly when referenced values change.
  • Documentation
    • Clarified the showLegends configuration default behavior in the dashboard configuration schema.

Ihor Dykhta added 2 commits July 2, 2026 17:35
@coderabbitai

coderabbitai Bot commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e3547883-df95-4e0e-89ff-14b8a28e528e

📥 Commits

Reviewing files that changed from the base of the PR and between c244afe and d96d094.

📒 Files selected for processing (2)
  • packages/deck/src/MapSettings.tsx
  • packages/deck/src/json/createDeckJsonConfiguration.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/deck/src/MapSettings.tsx
  • packages/deck/src/json/createDeckJsonConfiguration.ts

📝 Walkthrough

Walkthrough

This PR updates extrusion handling and elevation scaling in MapSettings, defaults legend display to enabled unless explicitly disabled, and refactors deck JSON preprocessing to centralize color accessor names and updateTriggers for color and elevation accessors.

Changes

Deck map settings and update-trigger fixes

Layer / File(s) Summary
Extrusion elevation defaults and elevation scale slider
packages/deck/src/MapSettings.tsx
Toggling extrusion now seeds or preserves getElevation, and extruded layers now show an elevation scale slider that updates elevationScale.
Legend default handling
packages/deck/src/ai.ts, packages/deck/src/dashboard.tsx
The schema documents legend defaults, and the renderer now passes showLegends as enabled unless it is explicitly false.
Color scale prop names and triggers
packages/deck/src/json/colorScaleFunction.ts, packages/deck/src/json/createDeckJsonConfiguration.ts
Color accessor names are centralized and applyColorScale now preserves existing triggers while adding stable updateTriggers for all known color accessors.
Elevation accessor normalization and triggers
packages/deck/src/json/createDeckJsonConfiguration.ts
preProcessClassProps normalizes getElevation for @@= accessors and extends updateTriggers for get* accessors bound to GeoArrow columns.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • sqlrooms/sqlrooms#781: Also changes the color-scale pipeline and updateTriggers behavior in packages/deck/src/json/createDeckJsonConfiguration.ts.
  • sqlrooms/sqlrooms#569: Touches the same preprocessing path in packages/deck/src/json/createDeckJsonConfiguration.ts.
  • sqlrooms/sqlrooms#746: Modifies preProcessClassProps and related updateTriggers handling in the same JSON preprocessing area.

Suggested reviewers: ilyabo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main map layer settings and color scale behavior changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 igr/deck-maps-fixes-23

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.

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

if (propName in result && !(propName in triggers)) {
triggers[propName] = 'static';

P2 Badge Add reset triggers when color accessors are removed

When the user disables a color scale for getLineColor, getColor, getSourceColor, or getTargetColor, clearDeckMapLayerColorScale deletes that accessor instead of replacing it with a constant. Because this reset trigger is only added when propName in result, those cleared accessors produce no updateTriggers entry, so the deck.gl layer can keep the previously computed color attribute until some unrelated change invalidates it—the stale color-scale reset this patch is trying to fix still occurs for the non-fill color controls.


if (rewritten.getElevation !== undefined) {

P2 Badge Invalidate elevation when the accessor is cleared

When an extruded layer already has an elevation column and the user clears the selector, MapSettings writes getElevation: undefined. This guard skips emitting any getElevation update trigger for that transition, so deck.gl has no trigger change to discard the previous elevation attribute and the geometry can remain at the old heights until another layer change forces invalidation; the default/cleared elevation state needs its own stable trigger as well.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Signed-off-by: Ihor Dykhta <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4f607f377

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/deck/src/json/createDeckJsonConfiguration.ts Outdated

@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

🧹 Nitpick comments (2)
packages/deck/src/json/createDeckJsonConfiguration.ts (1)

35-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated color accessor list.

COLOR_ACCESSOR_PROP_NAMES duplicates the exact prop-name list already defined inside getAllColorScales in packages/deck/src/json/colorScaleFunction.ts. Keeping two independent literals risks them drifting out of sync (e.g. a new color accessor added to one list but not the other).

♻️ Suggested consolidation

Export the list (or a getter) from colorScaleFunction.ts and import it here instead of redeclaring it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/deck/src/json/createDeckJsonConfiguration.ts` around lines 35 - 41,
The color accessor prop-name list is duplicated between
createDeckJsonConfiguration and getAllColorScales, so consolidate it by
exporting the shared list (or a getter) from colorScaleFunction.ts and importing
it here. Update COLOR_ACCESSOR_PROP_NAMES in createDeckJsonConfiguration to use
that shared source, and keep getAllColorScales as the single place defining the
accessor names.
packages/deck/src/MapSettings.tsx (1)

879-985: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consolidate duplicate Boolean(activeLayer?.extruded) checks.

The elevation-column block (line 903) and the new elevation-scale block (line 954) both gate on the same Boolean(activeLayer?.extruded) condition. Wrapping both in a single conditional block would avoid repeating the guard and keep the extrusion-only fields grouped together.

♻️ Suggested consolidation
-                {Boolean(activeLayer?.extruded) && dataTable && (
-                  <ColumnsProvider columns={dataTable.columns}>
-                    <Field label="Elevation column">
-                      ...
-                    </Field>
-                  </ColumnsProvider>
-                )}
-
-                {Boolean(activeLayer?.extruded) && (
-                  <Field label={`Elevation scale: ...`}>
-                    ...
-                  </Field>
-                )}
+                {Boolean(activeLayer?.extruded) && (
+                  <>
+                    {dataTable && (
+                      <ColumnsProvider columns={dataTable.columns}>
+                        <Field label="Elevation column">
+                          ...
+                        </Field>
+                      </ColumnsProvider>
+                    )}
+                    <Field label={`Elevation scale: ...`}>
+                      ...
+                    </Field>
+                  </>
+                )}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/deck/src/MapSettings.tsx` around lines 879 - 985, The extrusion
settings UI repeats the same Boolean(activeLayer?.extruded) guard for both the
elevation-column selector and the elevation-scale slider in MapSettings.tsx.
Consolidate these into one shared conditional around the extrusion-only fields
so they stay grouped together, and keep the existing ColumnsProvider, Field,
ColumnSelector.Numeric, and Slider behavior unchanged while moving the
duplicated check to the outer container.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/deck/src/json/createDeckJsonConfiguration.ts`:
- Around line 368-385: The update trigger for getElevation is only being applied
in the GeoArrow branch, so GeoJsonLayer can miss elevation changes and keep
stale extruded geometry. Update createDeckJsonConfiguration so the same
updateTriggers.getElevation merge logic used for rewritten also runs in the
GeoJSON path, using the existing getElevation handling and trigger preservation
pattern already present in the function.

---

Nitpick comments:
In `@packages/deck/src/json/createDeckJsonConfiguration.ts`:
- Around line 35-41: The color accessor prop-name list is duplicated between
createDeckJsonConfiguration and getAllColorScales, so consolidate it by
exporting the shared list (or a getter) from colorScaleFunction.ts and importing
it here. Update COLOR_ACCESSOR_PROP_NAMES in createDeckJsonConfiguration to use
that shared source, and keep getAllColorScales as the single place defining the
accessor names.

In `@packages/deck/src/MapSettings.tsx`:
- Around line 879-985: The extrusion settings UI repeats the same
Boolean(activeLayer?.extruded) guard for both the elevation-column selector and
the elevation-scale slider in MapSettings.tsx. Consolidate these into one shared
conditional around the extrusion-only fields so they stay grouped together, and
keep the existing ColumnsProvider, Field, ColumnSelector.Numeric, and Slider
behavior unchanged while moving the duplicated check to the outer container.
🪄 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: bf081db9-ac6f-41b4-9752-e92de1bab735

📥 Commits

Reviewing files that changed from the base of the PR and between 3997caf and e4f607f.

📒 Files selected for processing (4)
  • packages/deck/src/MapSettings.tsx
  • packages/deck/src/ai.ts
  • packages/deck/src/dashboard.tsx
  • packages/deck/src/json/createDeckJsonConfiguration.ts

Comment thread packages/deck/src/json/createDeckJsonConfiguration.ts Outdated
@igorDykhta igorDykhta self-assigned this Jul 2, 2026
Ihor Dykhta added 2 commits July 2, 2026 18:31
Signed-off-by: Ihor Dykhta <[email protected]>
Signed-off-by: Ihor Dykhta <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38865f7db3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/deck/src/json/createDeckJsonConfiguration.ts Outdated
Comment thread packages/deck/src/json/createDeckJsonConfiguration.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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/deck/src/json/createDeckJsonConfiguration.ts (1)

270-279: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

GeoJsonLayer elevation normalization/trigger is still skipped — regresses a previously-fixed bug.

The getElevation normalization and the new get* @@= accessor trigger-merge logic (lines 300-348) live entirely inside the GeoArrow branch, after the geojson branch already returns at line 279. A previous review on this file flagged exactly this gap: "GeoJsonLayer can also be extruded, so changing the elevation column or scale can leave stale geometry when this trigger is only set in the GeoArrow branch." That was fixed in a prior commit, but this refactor moved the (now more general) accessor-trigger logic back into the GeoArrow-only branch, so extruded GeoJsonLayers changing their elevation column/scale will again render stale/incorrect extruded geometry — directly undermining this PR's stated goal of making "elevation column changes...apply immediately."

Extract the elevation-normalization + accessor-trigger logic into a shared helper usable from both branches.

🩹 Proposed fix — share the logic between both representations
+      function normalizeElevationAndAccessorTriggers(options: {
+        props: Record<string, unknown>;
+        table: arrow.Table;
+      }) {
+        const {props, table} = options;
+        const nextProps: Record<string, unknown> = {...props};
+
+        const rawElev = nextProps.getElevation;
+        if (typeof rawElev === 'string' && rawElev.startsWith('@@=')) {
+          const elevField = rawElev.slice(3).trim();
+          const elevVector = table.getChild(elevField);
+          if (elevVector) {
+            let min = Infinity;
+            for (let i = 0; i < elevVector.length; i++) {
+              const v = Number(elevVector.get(i));
+              if (Number.isFinite(v) && v < min) min = v;
+            }
+            if (Number.isFinite(min) && min !== 0) {
+              nextProps.getElevation = `@@=${elevField} - ${min}`;
+            }
+          }
+        }
+
+        const accessorTriggers: Record<string, string> = {};
+        for (const [propName, propValue] of Object.entries(nextProps)) {
+          if (
+            typeof propValue === 'string' &&
+            propValue.startsWith('@@=') &&
+            propName.startsWith('get')
+          ) {
+            accessorTriggers[propName] = propValue;
+          }
+        }
+        if (Object.keys(accessorTriggers).length > 0) {
+          const existingTriggers =
+            nextProps.updateTriggers &&
+            typeof nextProps.updateTriggers === 'object' &&
+            !Array.isArray(nextProps.updateTriggers)
+              ? (nextProps.updateTriggers as Record<string, unknown>)
+              : {};
+          nextProps.updateTriggers = {...existingTriggers, ...accessorTriggers};
+        }
+        return nextProps;
+      }
+
       if (compatibility.representation === 'geojson') {
         const baseProps = applyColorScale({
           props: strippedProps,
           table: prepared.table,
         });
+        const geojsonProps = normalizeElevationAndAccessorTriggers({
+          props: baseProps,
+          table: prepared.table,
+        });
         return {
-          ...baseProps,
+          ...geojsonProps,
           data: prepared.getGeoJsonBinaryData(geometryColumn),
         };
       }

Then reuse normalizeElevationAndAccessorTriggers for nextProps before calling rewriteGeoArrowAccessors in the GeoArrow branch.

Also applies to: 294-349

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/deck/src/json/createDeckJsonConfiguration.ts` around lines 270 -
279, The elevation normalization and accessor-trigger merge currently only run
in the GeoArrow path, so GeoJsonLayer updates can still skip elevation/scale
changes and render stale extruded geometry. Move the shared `getElevation`
normalization plus the `get*` `@@=` trigger logic out of the GeoArrow-only
branch into a reusable helper in `createDeckJsonConfiguration`, and apply it to
the GeoJSON return path before `prepared.getGeoJsonBinaryData(geometryColumn)`
as well as the GeoArrow path before `rewriteGeoArrowAccessors`.
🧹 Nitpick comments (1)
packages/deck/src/json/createDeckJsonConfiguration.ts (1)

294-349: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add tests for elevation normalization and accessor triggers.
createDeckJsonConfiguration now rewrites getElevation to subtract the column minimum and derives updateTriggers from rewritten @@= accessors, but packages/deck/__tests__/createDeckJsonConfiguration.test.ts doesn’t cover either path yet.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/deck/src/json/createDeckJsonConfiguration.ts` around lines 294 -
349, Add test coverage in createDeckJsonConfiguration for the new elevation
normalization and updateTriggers behavior. Update
packages/deck/__tests__/createDeckJsonConfiguration.test.ts to verify that
createDeckJsonConfiguration rewrites getElevation from a @@= field accessor into
an expression that subtracts the column minimum, and that rewritten accessor
props are copied into rewritten.updateTriggers for any get* property using @@=
syntax. Use the createDeckJsonConfiguration and rewriteGeoArrowAccessors paths
to validate both behaviors end to end.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/deck/src/json/createDeckJsonConfiguration.ts`:
- Around line 300-315: The elevation normalization in
createDeckJsonConfiguration’s preProcessClassProps is doing a full per-row Arrow
scan with elevVector.get(i) on every invocation, which is too expensive on the
hot path. Refactor this block to avoid repeated chunked Vector.get lookups by
converting the elevation column to a flat typed array or equivalent buffered
array first, then compute the minimum from that array before updating
nextProps.getElevation.

---

Duplicate comments:
In `@packages/deck/src/json/createDeckJsonConfiguration.ts`:
- Around line 270-279: The elevation normalization and accessor-trigger merge
currently only run in the GeoArrow path, so GeoJsonLayer updates can still skip
elevation/scale changes and render stale extruded geometry. Move the shared
`getElevation` normalization plus the `get*` `@@=` trigger logic out of the
GeoArrow-only branch into a reusable helper in `createDeckJsonConfiguration`,
and apply it to the GeoJSON return path before
`prepared.getGeoJsonBinaryData(geometryColumn)` as well as the GeoArrow path
before `rewriteGeoArrowAccessors`.

---

Nitpick comments:
In `@packages/deck/src/json/createDeckJsonConfiguration.ts`:
- Around line 294-349: Add test coverage in createDeckJsonConfiguration for the
new elevation normalization and updateTriggers behavior. Update
packages/deck/__tests__/createDeckJsonConfiguration.test.ts to verify that
createDeckJsonConfiguration rewrites getElevation from a @@= field accessor into
an expression that subtracts the column minimum, and that rewritten accessor
props are copied into rewritten.updateTriggers for any get* property using @@=
syntax. Use the createDeckJsonConfiguration and rewriteGeoArrowAccessors paths
to validate both behaviors end to end.
🪄 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: de4dc2b2-2d5f-4b09-9e40-edcb0349f929

📥 Commits

Reviewing files that changed from the base of the PR and between e4f607f and 38865f7.

📒 Files selected for processing (3)
  • packages/deck/src/MapSettings.tsx
  • packages/deck/src/json/colorScaleFunction.ts
  • packages/deck/src/json/createDeckJsonConfiguration.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/deck/src/MapSettings.tsx

Comment thread packages/deck/src/json/createDeckJsonConfiguration.ts Outdated
Signed-off-by: Ihor Dykhta <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c244afe89f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/deck/src/json/createDeckJsonConfiguration.ts Outdated
Ihor Dykhta added 2 commits July 3, 2026 02:39
Signed-off-by: Ihor Dykhta <[email protected]>
Ihor Dykhta Ihor Dykhta
fix
Signed-off-by: Ihor Dykhta <[email protected]>
@igorDykhta
igorDykhta merged commit 73a25d9 into main Jul 3, 2026
4 checks passed
@igorDykhta
igorDykhta deleted the igr/deck-maps-fixes-23 branch July 3, 2026 14:02
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.

2 participants