Skip to content

Commit 3231e55

Browse files
Merge pull request #2 from Agriculture-Intelligence/main
Add Typescript Definitions / Enable Existing Layer Edit
2 parents ae716f0 + 97e749c commit 3231e55

File tree

3 files changed

+169
-83
lines changed

3 files changed

+169
-83
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ Install with npm
2424
| Hook returned methods | Returns | Description |
2525
|---------------------------------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
2626
| drawing() | boolean | Return true if any drawing action is ongoing. |
27-
| stopDrawing() | | When you need to stop any ongoing drawing, without needing to know which editor is active. |
28-
| commitDrawing() | | When you need to commit any ongoing drawing, without needing to know which editor is active. |
27+
| stopDrawing() | void | When you need to stop any ongoing drawing, without needing to know which editor is active. |
28+
| commitDrawing() | void | When you need to commit any ongoing drawing, without needing to know which editor is active. |
2929
| startPolyline(<L.LatLng> latlng, <hash> options) | L.Polyline | Start drawing a Polyline. If latlng is given, a first point will be added. In any case, continuing on user click. If options is given, it will be passed to the Polyline class constructor. |
3030
| startPolygon(<L.LatLng> latlng, <hash> options) | L.Polygon | Start drawing a Polygon. If latlng is given, a first point will be added. In any case, continuing on user click. If options is given, it will be passed to the Polygon class constructor. |
3131
| startMarker(<L.LatLng> latlng, <hash> options) | L.Marker | Start adding a Marker. If latlng is given, the Marker will be shown first at this point. In any case, it will follow the user mouse, and will have a final latlng on next click (or touch). If options is given, it will be passed to the Marker class constructor. |
3232
| startRectangle(<L.LatLng> latlng, <hash> options) | L.Rectangle | Start drawing a Rectangle. If latlng is given, the Rectangle anchor will be added. In any case, continuing on user drag. If options is given, it will be passed to the Rectangle class constructor. |
3333
| startCircle(<L.LatLng> latlng, <hash> options) | L.Circle | Start drawing a Circle. If latlng is given, the Circle anchor will be added. In any case, continuing on user drag. If options is given, it will be passed to the Circle class constructor. |
34+
| enableEdit(feature: L.Layer) | void | Enable editing, by creating an editor if not existing, and then calling enable on it. |
35+
| disableEdit(feature: L.Layer) | void | Disable editing, also remove the editor property reference. |
3436

3537

3638
| Events |
@@ -39,9 +41,9 @@ Install with npm
3941
| onEnable |
4042
| onDisable |
4143
| onEditing |
42-
| onDragstart |
44+
| onDragStart |
4345
| onDrag |
44-
| onDragend |
46+
| onDragEnd |
4547
| onDrawingStart |
4648
| onDrawingEnd |
4749
| onDrawingCancel |
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
Layer,
3+
LayerEventHandlerFn,
4+
LeafletEventHandlerFn,
5+
VertexEventHandlerFn,
6+
CancelableEventHandlerFn,
7+
ShapeEventHandlerFn,
8+
Editable,
9+
} from "leaflet";
10+
11+
export interface LeafletEditableEventHandlers {
12+
onCreated?: LayerEventHandlerFn;
13+
onEnable?: LeafletEventHandlerFn;
14+
onDisable?: LeafletEventHandlerFn;
15+
onEditing?: LeafletEventHandlerFn;
16+
onDragStart?: LeafletEventHandlerFn;
17+
onDrag?: LeafletEventHandlerFn;
18+
onDragEnd?: LeafletEventHandlerFn;
19+
onDrawingStart?: LeafletEventHandlerFn;
20+
onDrawingEnd?: LeafletEventHandlerFn;
21+
onDrawingCancel?: LeafletEventHandlerFn;
22+
onDrawingCommit?: LeafletEventHandlerFn;
23+
onDrawingMousedown?: LeafletEventHandlerFn;
24+
onDrawingMouseup?: LeafletEventHandlerFn;
25+
onDrawingClick?: CancelableEventHandlerFn;
26+
onDrawingMove?: LeafletEventHandlerFn;
27+
onDrawingClicked?: LeafletEventHandlerFn;
28+
onVertexNew?: VertexEventHandlerFn;
29+
onVertexClick?: CancelableEventHandlerFn;
30+
onVertexClicked?: VertexEventHandlerFn;
31+
onVertexRawclick?: CancelableEventHandlerFn;
32+
onVertexDeleted?: VertexEventHandlerFn;
33+
onVertexCtrlclick?: VertexEventHandlerFn;
34+
onVertexShiftclick?: VertexEventHandlerFn;
35+
onVertexMetakeyclick?: VertexEventHandlerFn;
36+
onVertexAltclick?: VertexEventHandlerFn;
37+
onVertexContextmenu?: VertexEventHandlerFn;
38+
onVertexMousedown?: VertexEventHandlerFn;
39+
onVertexDrag?: VertexEventHandlerFn;
40+
onVertexDragstart?: VertexEventHandlerFn;
41+
onVertexDragend?: VertexEventHandlerFn;
42+
onMiddlemarkerMousedown?: VertexEventHandlerFn;
43+
onShapeNew?: ShapeEventHandlerFn;
44+
onShapeDelete?: CancelableEventHandlerFn;
45+
onShapeDeleted?: ShapeEventHandlerFn;
46+
}
47+
48+
export interface UseLeafletEditableOptions {
49+
events: LeafletEditableEventHandlers;
50+
}
51+
52+
export function useLeafletEditable(
53+
options: UseLeafletEditableOptions,
54+
): Editable & {
55+
enableEdit: (feature: Layer) => void;
56+
disableEdit: (feature: Layer) => void;
57+
};

leaflet-editable-hook/src/hooks/useLeafletEditable.js

Lines changed: 106 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,136 @@
1-
import React from 'react';
2-
import { useMap } from 'react-leaflet';
1+
import { useCallback, useEffect } from "react";
2+
import { Polyline, Marker, Polygon, Circle, Rectangle } from "leaflet";
3+
import { useMap } from "react-leaflet";
34

45
const eventHandlers = Object.freeze({
5-
onCreated: 'editable:created',
6-
onEnable: 'editable:enable',
7-
onDisable: 'editable:disable',
8-
onEditing: 'editable:editing',
9-
onDragstart: 'editable:dragstart',
10-
onDrag: 'editable:drag',
11-
onDragend: 'editable:dragend',
12-
onDrawingStart: 'editable:drawing:start',
13-
onDrawingEnd: 'editable:drawing:end',
14-
onDrawingCancel: 'editable:drawing:cancel',
15-
onDrawingCommit: 'editable:drawing:commit',
16-
onDrawingMousedown: 'editable:drawing:mousedown',
17-
onDrawingMouseup: 'editable:drawing:mouseup',
18-
onDrawingClick: 'editable:drawing:click',
19-
onDrawingMove: 'editable:drawing:move',
20-
onDrawingClicked: 'editable:drawing:clicked',
21-
onVertexNew: 'editable:vertex:new',
22-
onVertexClick: 'editable:vertex:click',
23-
onVertexClicked: 'editable:vertex:clicked',
24-
onVertexRawclick: 'editable:vertex:rawclick',
25-
onVertexDeleted: 'editable:vertex:deleted',
26-
onVertexCtrlclick: 'editable:vertex:ctrlclick',
27-
onVertexShiftclick: 'editable:vertex:shiftclick',
28-
onVertexMetakeyclick: 'editable:vertex:metakeyclick',
29-
onVertexAltclick: 'editable:vertex:altclick',
30-
onVertexContextmenu: 'editable:vertex:contextmenu',
31-
onVertexMousedown: 'editable:vertex:mousedown',
32-
onVertexDrag: 'editable:vertex:drag',
33-
onVertexDragstart: 'editable:vertex:dragstart',
34-
onVertexDragend: 'editable:vertex:dragend',
35-
onMiddlemarkerMousedown: 'editable:middlemarker:mousedown',
36-
onShapeNew: 'editable:shape:new',
37-
onShapeDelete: 'editable:shape:delete',
38-
onShapeDeleted: 'editable:shape:deleted',
6+
onCreated: "editable:created",
7+
onEnable: "editable:enable",
8+
onDisable: "editable:disable",
9+
onEditing: "editable:editing",
10+
onDragStart: "editable:dragstart",
11+
onDrag: "editable:drag",
12+
onDragEnd: "editable:dragend",
13+
onDrawingStart: "editable:drawing:start",
14+
onDrawingEnd: "editable:drawing:end",
15+
onDrawingCancel: "editable:drawing:cancel",
16+
onDrawingCommit: "editable:drawing:commit",
17+
onDrawingMousedown: "editable:drawing:mousedown",
18+
onDrawingMouseup: "editable:drawing:mouseup",
19+
onDrawingClick: "editable:drawing:click",
20+
onDrawingMove: "editable:drawing:move",
21+
onDrawingClicked: "editable:drawing:clicked",
22+
onVertexNew: "editable:vertex:new",
23+
onVertexClick: "editable:vertex:click",
24+
onVertexClicked: "editable:vertex:clicked",
25+
onVertexRawclick: "editable:vertex:rawclick",
26+
onVertexDeleted: "editable:vertex:deleted",
27+
onVertexCtrlclick: "editable:vertex:ctrlclick",
28+
onVertexShiftclick: "editable:vertex:shiftclick",
29+
onVertexMetakeyclick: "editable:vertex:metakeyclick",
30+
onVertexAltclick: "editable:vertex:altclick",
31+
onVertexContextmenu: "editable:vertex:contextmenu",
32+
onVertexMousedown: "editable:vertex:mousedown",
33+
onVertexDrag: "editable:vertex:drag",
34+
onVertexDragstart: "editable:vertex:dragstart",
35+
onVertexDragend: "editable:vertex:dragend",
36+
onMiddlemarkerMousedown: "editable:middlemarker:mousedown",
37+
onShapeNew: "editable:shape:new",
38+
onShapeDelete: "editable:shape:delete",
39+
onShapeDeleted: "editable:shape:deleted",
3940
});
4041

4142
function useLeafletEditable({ events }) {
4243
const map = useMap();
4344

44-
React.useEffect(() => {
45-
Object.keys(eventHandlers).forEach((key) => {
46-
if (events[key]) {
47-
map.on(eventHandlers[key], events[key]);
45+
useEffect(() => {
46+
const keys = Object.keys(eventHandlers);
47+
keys.forEach((key) => {
48+
const handler = events[key];
49+
if (handler) {
50+
map.on(eventHandlers[key], handler);
4851
}
4952
});
53+
5054
return () => {
51-
Object.keys(eventHandlers).forEach((key) => {
52-
if (events[key]) {
53-
map.off(eventHandlers[key], events[key]);
55+
keys.forEach((key) => {
56+
const handler = events[key];
57+
if (handler) {
58+
map.off(eventHandlers[key], handler);
5459
}
5560
});
5661
};
5762
}, [map, events]);
5863

59-
const drawing = React.useMemo(() => {
60-
return map.editTools.drawing();
61-
}, [map]);
64+
const drawing = useCallback(() => map.editTools.drawing(), [map]);
6265

63-
const stopDrawing = React.useCallback(() => {
64-
map.editTools.stopDrawing();
65-
}, [map]);
66+
const stopDrawing = useCallback(() => map.editTools.stopDrawing(), [map]);
6667

67-
const commitDrawing = React.useCallback(() => {
68-
map.editTools.commitDrawing();
69-
}, [map]);
68+
const commitDrawing = useCallback(
69+
(event) => map.editTools.commitDrawing(event),
70+
[map],
71+
);
7072

71-
const startPolyline = React.useCallback(
72-
(latlng, options) => {
73-
return map.editTools.startPolyline(latlng, options);
74-
},
75-
[map]
73+
const startPolyline = useCallback(
74+
(latLng, options) => map.editTools.startPolyline(latLng, options),
75+
[map],
7676
);
7777

78-
const startPolygon = React.useCallback(
79-
(latlng, options) => {
80-
return map.editTools.startPolygon(latlng, options);
81-
},
82-
[map]
78+
const startPolygon = useCallback(
79+
(latLng, options) => map.editTools.startPolygon(latLng, options),
80+
[map],
8381
);
8482

85-
const startMarker = React.useCallback(
86-
(latlng, options) => {
87-
return map.editTools.startMarker(latlng, options);
88-
},
89-
[map]
83+
const startMarker = useCallback(
84+
(latLng, options) => map.editTools.startMarker(latLng, options),
85+
[map],
9086
);
9187

92-
const startRectangle = React.useCallback(
93-
(latlng, options) => {
94-
return map.editTools.startRectangle(latlng, options);
95-
},
96-
[map]
88+
const startRectangle = useCallback(
89+
(latLng, options) => map.editTools.startRectangle(latLng, options),
90+
[map],
9791
);
9892

99-
const startCircle = React.useCallback(
100-
(latlng, options) => {
101-
return map.editTools.startCircle(latlng, options);
93+
const startCircle = useCallback(
94+
(latLng, options) => map.editTools.startCircle(latLng, options),
95+
[map],
96+
);
97+
98+
const clearAll = useCallback(() => map.editTools.clearLayers(), [map]);
99+
100+
// BaseEditor related methods
101+
const enableEdit = useCallback(
102+
(feature) => {
103+
if (
104+
feature instanceof Marker ||
105+
feature instanceof Polyline ||
106+
feature instanceof Polygon ||
107+
feature instanceof Rectangle ||
108+
feature instanceof Circle
109+
) {
110+
feature.enableEdit();
111+
} else {
112+
console.error("Feature is not editable", feature);
113+
}
102114
},
103-
[map]
115+
[map],
104116
);
105117

106-
const clearAll = React.useCallback(() => {
107-
return map.editTools.clearLayers();
108-
}, [map]);
118+
const disableEdit = useCallback(
119+
(feature) => {
120+
if (
121+
feature instanceof Marker ||
122+
feature instanceof Polyline ||
123+
feature instanceof Polygon ||
124+
feature instanceof Rectangle ||
125+
feature instanceof Circle
126+
) {
127+
feature.disableEdit();
128+
} else {
129+
console.error("Feature is not editable", feature);
130+
}
131+
},
132+
[map],
133+
);
109134

110135
return {
111136
drawing,
@@ -117,6 +142,8 @@ function useLeafletEditable({ events }) {
117142
startRectangle,
118143
startCircle,
119144
clearAll,
145+
enableEdit,
146+
disableEdit,
120147
};
121148
}
122149

0 commit comments

Comments
 (0)