= {
// Callback used to update cursor
onUpdateCursor: (cursor: string | null | undefined) => void;
+
+ onSelectionChanged: (event: SelectionContext) => void;
};
diff --git a/modules/editor/src/index.ts b/modules/editor/src/index.ts
index 4835a404a..4f7bc424c 100644
--- a/modules/editor/src/index.ts
+++ b/modules/editor/src/index.ts
@@ -3,3 +3,4 @@ export { ExportModal } from './export-modal';
export { ExportComponent } from './export-component';
export { ImportModal } from './import-modal';
export { ImportComponent } from './import-component';
+export { OverlappingSelection } from './overlapping-selection';
diff --git a/modules/editor/src/overlapping-selection.tsx b/modules/editor/src/overlapping-selection.tsx
new file mode 100644
index 000000000..5a2b81d59
--- /dev/null
+++ b/modules/editor/src/overlapping-selection.tsx
@@ -0,0 +1,57 @@
+import * as React from 'react';
+import styled from 'styled-components';
+import { SelectionContext } from '@nebula.gl/edit-modes';
+
+const Button = styled.button<{ active?: boolean; kind?: string }>`
+ color: #fff;
+ background: ${({ kind, active }) =>
+ kind === 'danger' ? 'rgb(180, 40, 40)' : active ? 'rgb(0, 105, 217)' : 'rgb(90, 98, 94)'};
+ font-size: 1em;
+ font-weight: 400;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
+ 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
+ border: 1px solid transparent;
+ border-radius: 0.25em;
+ margin: 0.05em;
+ padding: 0.1em 0.2em;
+ :hover {
+ background: rgb(128, 137, 133);
+ }
+`;
+
+export type Props = {
+ data: any;
+ selection: SelectionContext;
+ onSetSelection: (selection: SelectionContext) => unknown;
+};
+
+export function OverlappingSelection({ data, selection, onSetSelection }: Props) {
+ const { selectedIndexes, selectContext } = selection;
+ if (!selectedIndexes || selectedIndexes.length < 2) {
+ return null;
+ }
+
+ const left = selectContext ? selectContext.screenCoords[0] : 30;
+ const top = selectContext ? selectContext.screenCoords[1] : 30;
+
+ return (
+
+ {selectedIndexes.map((index) => {
+ const feature = data.features[index];
+ return (
+
+ );
+ })}
+
+ );
+}
diff --git a/modules/editor/src/toolbox.tsx b/modules/editor/src/toolbox.tsx
index 655ccc495..b14d4a732 100644
--- a/modules/editor/src/toolbox.tsx
+++ b/modules/editor/src/toolbox.tsx
@@ -1,11 +1,12 @@
import * as React from 'react';
import {
- ViewMode,
+ SelectMode,
DrawPointMode,
DrawLineStringMode,
DrawPolygonMode,
DrawCircleFromCenterMode,
DrawRectangleMode,
+ ModifyMode,
MeasureDistanceMode,
MeasureAngleMode,
MeasureAreaMode,
@@ -58,15 +59,17 @@ export type Props = {
mode: any;
modeConfig: any;
geoJson: any;
+ selectedIndexes: number[];
onSetMode: (mode: any) => unknown;
onSetModeConfig: (modeConfig: any) => unknown;
onSetGeoJson: (geojson: any) => unknown;
+ onSetSelectedIndexes: (selectedIndexes: number[]) => unknown;
onImport: (imported: any) => unknown;
};
const MODE_GROUPS = [
{
- modes: [{ mode: ViewMode, content: }],
+ modes: [{ mode: SelectMode, content: }],
},
{
modes: [{ mode: DrawPointMode, content: }],
@@ -86,6 +89,9 @@ const MODE_GROUPS = [
{ mode: DrawCircleFromCenterMode, content: },
],
},
+ {
+ modes: [{ mode: ModifyMode, content: }],
+ },
{
modes: [
{ mode: MeasureDistanceMode, content: },
diff --git a/modules/layers/src/layers/editable-geojson-layer.ts b/modules/layers/src/layers/editable-geojson-layer.ts
index c72d6c1d0..9cfec940b 100644
--- a/modules/layers/src/layers/editable-geojson-layer.ts
+++ b/modules/layers/src/layers/editable-geojson-layer.ts
@@ -26,6 +26,7 @@ import {
SnappableMode,
TransformMode,
EditAction,
+ SelectionContext,
ClickEvent,
StartDraggingEvent,
StopDraggingEvent,
@@ -106,6 +107,8 @@ const defaultProps = {
// Edit and interaction events
onEdit: () => {},
+ onSelectionChanged: () => {},
+
pickable: true,
pickingRadius: 10,
pickingDepth: 5,
@@ -191,7 +194,8 @@ const modeNameMapping = {
type Props = {
mode: string | GeoJsonEditModeConstructor | GeoJsonEditModeType;
- onEdit: (arg0: EditAction) => void;
+ onEdit: (event: EditAction) => unknown;
+ onSelectionChanged?: (event: SelectionContext) => unknown;
// TODO: type the rest
[key: string]: any;
@@ -346,6 +350,11 @@ export default class EditableGeoJsonLayer extends EditableLayer {
onUpdateCursor: (cursor: string | null | undefined) => {
this.setState({ cursor });
},
+ onSelectionChanged: (selectedIndexes) => {
+ if (props.onSelectionChanged) {
+ props.onSelectionChanged(selectedIndexes);
+ }
+ },
};
}
diff --git a/modules/main/src/index.ts b/modules/main/src/index.ts
index bbb53b833..28947c45a 100644
--- a/modules/main/src/index.ts
+++ b/modules/main/src/index.ts
@@ -55,6 +55,7 @@ export { ImmutableFeatureCollection } from '@nebula.gl/edit-modes';
// Other modes
export { ViewMode } from '@nebula.gl/edit-modes';
+export { SelectMode } from '@nebula.gl/edit-modes';
export { MeasureDistanceMode } from '@nebula.gl/edit-modes';
export { MeasureAreaMode } from '@nebula.gl/edit-modes';
export { MeasureAngleMode } from '@nebula.gl/edit-modes';