• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

keplergl / kepler.gl / 23880914138

02 Apr 2026 02:34AM UTC coverage: 60.661% (-1.0%) from 61.699%
23880914138

Pull #3271

github

web-flow
Merge f1dfa1060 into bc59e880b
Pull Request #3271: chore: deck.gl 9.2 upgrade & loaders.gl, luma.gl upgrades

6519 of 12785 branches covered (50.99%)

Branch coverage included in aggregate %.

270 of 740 new or added lines in 50 files covered. (36.49%)

102 existing lines in 12 files now uncovered.

13280 of 19854 relevant lines covered (66.89%)

79.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.0
/src/layers/src/editor-layer/editor-layer.ts
1
// SPDX-License-Identifier: MIT
2
// Copyright contributors to the kepler.gl project
3

4
import {EditableGeoJsonLayer} from '@deck.gl-community/editable-layers';
5
import {Layer as DeckLayer, LayerProps as DeckLayerProps} from '@deck.gl/core';
6
import {
7
  DrawPolygonMode,
8
  TranslateMode,
9
  CompositeMode,
10
  DrawRectangleMode,
11
  GeoJsonEditMode
12
} from '@deck.gl-community/editable-layers';
13
import {PathStyleExtension} from '@deck.gl/extensions';
14

15
import {EDITOR_LAYER_ID, EDITOR_MODES, EDITOR_LAYER_PICKING_RADIUS} from '@kepler.gl/constants';
16
import {Viewport, Editor, Feature, FeatureSelectionContext} from '@kepler.gl/types';
17
import {generateHashId} from '@kepler.gl/common-utils';
18

19
import {EDIT_TYPES} from './constants';
20
import {LINE_STYLE, FEATURE_STYLE, EDIT_HANDLE_STYLE} from './feature-styles';
21
import {ModifyModeExtended} from './modify-mode-extended';
22
import {isDrawingActive} from './editor-layer-utils';
23

24
const DEFAULT_COMPOSITE_MODE = new CompositeMode([
13✔
25
  new TranslateMode() as unknown as GeoJsonEditMode,
26
  new ModifyModeExtended() as unknown as GeoJsonEditMode
27
]);
28

29
export type GetEditorLayerProps = {
30
  editorMenuActive: boolean;
31
  editor: Editor;
32
  onSetFeatures: (features: Feature[]) => any;
33
  setSelectedFeature: (feature: Feature | null, selectionContext?: FeatureSelectionContext) => any;
34
  viewport: Viewport;
35
  featureCollection: {
36
    type: string;
37
    features: Feature[];
38
  };
39
  selectedFeatureIndexes: number[];
40
};
41

42
/**
43
 * Returns editable layer to edit polygon filters.
44
 * @param params
45
 * @param params.editorMenuActive Indicates whether the editor side menu is active.
46
 * @param params.editor
47
 * @param params.onSetFeatures A callback to set features.
48
 * @param params.setSelectedFeature A callback to set selected feature and selection context.
49
 * @param params.viewport Current viewport.
50
 * @param params.featureCollection Feature collection with an array of features
51
 * @param params.selectedFeatureIndexes An array with index of currently selected feature.
52
 */
53
export function getEditorLayer({
54
  editorMenuActive,
55
  editor,
56
  onSetFeatures,
57
  setSelectedFeature,
58
  featureCollection,
59
  selectedFeatureIndexes,
60
  viewport
61
}: GetEditorLayerProps): DeckLayer<DeckLayerProps> {
62
  const {mode: editorMode} = editor;
30✔
63

64
  let mode = DEFAULT_COMPOSITE_MODE;
30✔
65
  if (editorMenuActive) {
30✔
66
    // @ts-ignore
67
    if (editorMode === EDITOR_MODES.DRAW_POLYGON) mode = DrawPolygonMode;
1!
68
    // @ts-ignore
69
    else if (editorMode === EDITOR_MODES.DRAW_RECTANGLE) mode = DrawRectangleMode;
×
70
  }
71

72
  // @ts-ignore
73
  return new EditableGeoJsonLayer({
30✔
74
    id: EDITOR_LAYER_ID,
75
    mode,
76
    // @ts-ignore
77
    data: featureCollection,
78
    selectedFeatureIndexes,
79
    visible: editor.visible,
80
    pickable: true,
81
    pickingRadius: EDITOR_LAYER_PICKING_RADIUS,
82
    modeConfig: {
83
      viewport,
84
      screenSpace: true,
85
      lockRectangles: true
86
    },
87

88
    pickingLineWidthExtraPixels: 5,
89

90
    // Only show fill when polygons are selected,
91
    // there is no way atm to enable fill for only one feature
92
    filled: selectedFeatureIndexes.length > 0,
93

94
    onEdit: ({updatedData, editType}) => {
95
      switch (editType) {
×
96
        case EDIT_TYPES.ADD_FEATURE: {
97
          const {features: _features} = updatedData;
×
98
          if (_features.length) {
×
99
            const lastFeature = _features[_features.length - 1];
×
NEW
100
            if (lastFeature.properties) lastFeature.properties.isClosed = true;
×
101
            lastFeature.id = generateHashId(6);
×
NEW
102
            onSetFeatures(updatedData.features as unknown as Feature[]);
×
NEW
103
            setSelectedFeature(lastFeature as unknown as Feature);
×
104
          }
105
          break;
×
106
        }
107
        case EDIT_TYPES.ADD_POSITION:
108
        case EDIT_TYPES.MOVE_POSITION:
109
        case EDIT_TYPES.TRANSLATING:
NEW
110
          onSetFeatures(updatedData.features as unknown as Feature[]);
×
111
          break;
×
112
        default:
113
          break;
×
114
      }
115
    },
116

117
    // prevent self-highlights with tentative features
118
    autoHighlight: !isDrawingActive(editorMenuActive, editorMode),
119
    // @ts-ignore
120
    highlightColor: info => {
121
      // Note: lines are reported as parent polygon
122
      const {object} = info;
×
123
      if (object) {
×
124
        if (object.id === editor.selectedFeature?.id) {
×
125
          return FEATURE_STYLE.highlightMultiplierNone;
×
126
        }
127

128
        const type = object.properties.editHandleType;
×
129
        if (type === 'intermediate') return EDIT_HANDLE_STYLE.highlightMultiplierNone;
×
130
        else if (type === 'existing') return EDIT_HANDLE_STYLE.highlightMultiplier;
×
131
      }
132

133
      // Note: highlight color affects even transparent filled polygons
134
      return selectedFeatureIndexes.length
×
135
        ? FEATURE_STYLE.highlightMultiplier
136
        : LINE_STYLE.highlightMultiplier;
137
    },
138

139
    extensions: [new PathStyleExtension({dash: true})],
140
    dashGapPickable: true,
141
    getDashArray: feature => {
142
      if (feature?.properties?.guideType === 'tentative') {
×
143
        return LINE_STYLE.dashArray;
×
144
      }
145

146
      if (feature?.id === editor.selectedFeature?.id) return LINE_STYLE.solidArray;
×
147

148
      return LINE_STYLE.dashArray;
×
149
    },
150

151
    getLineColor: LINE_STYLE.getColor,
152
    getFillColor: FEATURE_STYLE.getColor,
153

154
    getRadius: EDIT_HANDLE_STYLE.getRadius,
155
    // @ts-ignore
156
    getLineWidth: LINE_STYLE.getWidth,
157

158
    getEditHandlePointRadius: EDIT_HANDLE_STYLE.getRadius,
159
    getEditHandlePointColor: EDIT_HANDLE_STYLE.getFillColor,
160
    getEditHandlePointOutlineColor: EDIT_HANDLE_STYLE.getOutlineColor,
161

162
    getTentativeLineColor: LINE_STYLE.getTentativeLineColor,
163
    // @ts-ignore
164
    getTentativeLineWidth: LINE_STYLE.getTentativeLineWidth,
165
    getTentativeFillColor: LINE_STYLE.getTentativeFillColor,
166

167
    parameters: {}
168
  });
169
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc