@deck.gl-community/editable-layers 9.1.1 → 9.2.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/edit-modes/draw-line-string-mode.d.ts +3 -1
- package/dist/edit-modes/draw-line-string-mode.d.ts.map +1 -1
- package/dist/edit-modes/draw-line-string-mode.js +19 -21
- package/dist/edit-modes/draw-line-string-mode.js.map +1 -1
- package/dist/edit-modes/draw-polygon-mode.d.ts +3 -1
- package/dist/edit-modes/draw-polygon-mode.d.ts.map +1 -1
- package/dist/edit-modes/draw-polygon-mode.js +19 -22
- package/dist/edit-modes/draw-polygon-mode.js.map +1 -1
- package/dist/edit-modes/edit-mode.d.ts +2 -1
- package/dist/edit-modes/edit-mode.d.ts.map +1 -1
- package/dist/edit-modes/geojson-edit-mode.d.ts +1 -0
- package/dist/edit-modes/geojson-edit-mode.d.ts.map +1 -1
- package/dist/edit-modes/geojson-edit-mode.js +1 -0
- package/dist/edit-modes/geojson-edit-mode.js.map +1 -1
- package/dist/edit-modes/measure-distance-mode.d.ts.map +1 -1
- package/dist/edit-modes/rotate-mode.d.ts.map +1 -1
- package/dist/edit-modes/scale-mode.d.ts.map +1 -1
- package/dist/edit-modes/types.d.ts +1 -0
- package/dist/edit-modes/types.d.ts.map +1 -1
- package/dist/editable-layers/editable-geojson-layer.d.ts +2 -1
- package/dist/editable-layers/editable-geojson-layer.d.ts.map +1 -1
- package/dist/editable-layers/editable-geojson-layer.js +5 -0
- package/dist/editable-layers/editable-geojson-layer.js.map +1 -1
- package/dist/editable-layers/editable-layer.d.ts +3 -1
- package/dist/editable-layers/editable-layer.d.ts.map +1 -1
- package/dist/editable-layers/editable-layer.js +7 -1
- package/dist/editable-layers/editable-layer.js.map +1 -1
- package/dist/index.cjs +847 -79
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/layers/segments-layer.d.ts +1 -1
- package/dist/lib/layers/segments-layer.d.ts.map +1 -1
- package/dist/lib/layers/segments-layer.js +1 -1
- package/dist/lib/layers/segments-layer.js.map +1 -1
- package/dist/lib/nebula-core.d.ts.map +1 -1
- package/dist/utils/memoize.d.ts.map +1 -1
- package/dist/widgets/edit-mode-tray-widget.d.ts +71 -0
- package/dist/widgets/edit-mode-tray-widget.d.ts.map +1 -0
- package/dist/widgets/edit-mode-tray-widget.js +217 -0
- package/dist/widgets/edit-mode-tray-widget.js.map +1 -0
- package/package.json +12 -11
- package/src/edit-modes/draw-line-string-mode.ts +23 -24
- package/src/edit-modes/draw-polygon-mode.ts +24 -27
- package/src/edit-modes/edit-mode.ts +4 -1
- package/src/edit-modes/geojson-edit-mode.ts +2 -0
- package/src/edit-modes/types.ts +3 -0
- package/src/editable-layers/editable-geojson-layer.ts +8 -1
- package/src/editable-layers/editable-layer.ts +10 -2
- package/src/index.ts +8 -0
- package/src/lib/layers/segments-layer.ts +1 -1
- package/src/widgets/edit-mode-tray-widget.tsx +342 -0
package/src/edit-modes/types.ts
CHANGED
|
@@ -44,6 +44,9 @@ export type BasePointerEvent = {
|
|
|
44
44
|
// Represents a click event
|
|
45
45
|
export type ClickEvent = BasePointerEvent;
|
|
46
46
|
|
|
47
|
+
// Represents a double click event
|
|
48
|
+
export type DoubleClickEvent = BasePointerEvent;
|
|
49
|
+
|
|
47
50
|
// Represents an event that occurs when the pointer goes down and the cursor starts moving
|
|
48
51
|
export type StartDraggingEvent = BasePointerEvent & {
|
|
49
52
|
pointerDownPicks?: Pick[] | null;
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
StartDraggingEvent,
|
|
13
13
|
StopDraggingEvent,
|
|
14
14
|
DraggingEvent,
|
|
15
|
-
PointerMoveEvent
|
|
15
|
+
PointerMoveEvent,
|
|
16
|
+
DoubleClickEvent
|
|
16
17
|
} from '../edit-modes/types';
|
|
17
18
|
|
|
18
19
|
import {ViewMode} from '../edit-modes/view-mode';
|
|
@@ -567,6 +568,12 @@ export class EditableGeoJsonLayer extends EditableLayer<
|
|
|
567
568
|
this.getActiveMode().handleClick(event, this.getModeProps(this.props) as any);
|
|
568
569
|
}
|
|
569
570
|
|
|
571
|
+
onLayerDoubleClick(event: DoubleClickEvent): void {
|
|
572
|
+
if (this.getActiveMode().handleDoubleClick) {
|
|
573
|
+
this.getActiveMode().handleDoubleClick(event, this.getModeProps(this.props) as any);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
570
577
|
onLayerKeyUp(event: KeyboardEvent): void {
|
|
571
578
|
this.getActiveMode().handleKeyUp(event, this.getModeProps(this.props) as any);
|
|
572
579
|
}
|
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
ClickEvent,
|
|
12
12
|
StartDraggingEvent,
|
|
13
13
|
StopDraggingEvent,
|
|
14
|
-
PointerMoveEvent
|
|
14
|
+
PointerMoveEvent,
|
|
15
|
+
DoubleClickEvent
|
|
15
16
|
} from '../edit-modes/types';
|
|
16
17
|
import {Position} from '../utils/geojson-types';
|
|
17
18
|
|
|
18
|
-
const EVENT_TYPES = ['click', 'pointermove', 'panstart', 'panmove', 'panend', 'keyup'];
|
|
19
|
+
const EVENT_TYPES = ['click', 'pointermove', 'panstart', 'panmove', 'panend', 'keyup', 'dblclick'];
|
|
19
20
|
|
|
20
21
|
// TODO(v9): remove generic layer
|
|
21
22
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -37,6 +38,9 @@ export abstract class EditableLayer<
|
|
|
37
38
|
onLayerClick(event: ClickEvent): void {
|
|
38
39
|
// default implementation - do nothing
|
|
39
40
|
}
|
|
41
|
+
onLayerDoubleClick(event: DoubleClickEvent): void {
|
|
42
|
+
// default implementation - do nothing
|
|
43
|
+
}
|
|
40
44
|
|
|
41
45
|
onStartDragging(event: StartDraggingEvent): void {
|
|
42
46
|
// default implementation - do nothing
|
|
@@ -133,6 +137,10 @@ export abstract class EditableLayer<
|
|
|
133
137
|
});
|
|
134
138
|
}
|
|
135
139
|
|
|
140
|
+
_ondblclick({srcEvent}: any) {
|
|
141
|
+
this.onLayerDoubleClick(srcEvent);
|
|
142
|
+
}
|
|
143
|
+
|
|
136
144
|
_onkeyup({srcEvent}: {srcEvent: KeyboardEvent}) {
|
|
137
145
|
this.onLayerKeyUp(srcEvent);
|
|
138
146
|
}
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,14 @@ export {EditableH3ClusterLayer} from './editable-layers/editable-h3-cluster-laye
|
|
|
29
29
|
export {SelectionLayer} from './editable-layers/selection-layer';
|
|
30
30
|
export {ElevatedEditHandleLayer} from './editable-layers/elevated-edit-handle-layer';
|
|
31
31
|
|
|
32
|
+
// Widgets
|
|
33
|
+
export {EditModeTrayWidget} from './widgets/edit-mode-tray-widget';
|
|
34
|
+
export type {
|
|
35
|
+
EditModeTrayWidgetProps,
|
|
36
|
+
EditModeTrayWidgetModeOption,
|
|
37
|
+
EditModeTrayWidgetSelectEvent
|
|
38
|
+
} from './widgets/edit-mode-tray-widget';
|
|
39
|
+
|
|
32
40
|
// Layers move to deck.gl-community/layers?
|
|
33
41
|
export {JunctionScatterplotLayer} from './editable-layers/junction-scatterplot-layer';
|
|
34
42
|
|
|
@@ -6,7 +6,7 @@ import {ArrowStyles, DEFAULT_STYLE, MAX_ARROWS} from '../style';
|
|
|
6
6
|
import {NebulaLayer} from '../nebula-layer';
|
|
7
7
|
import {toDeckColor} from '../../utils/utils';
|
|
8
8
|
import {DeckCache} from '../deck-renderer/deck-cache';
|
|
9
|
-
import {PathMarkerLayer} from '
|
|
9
|
+
import {PathMarkerLayer} from '../../../../layers/src/path-marker-layer/path-marker-layer';
|
|
10
10
|
|
|
11
11
|
const NEBULA_TO_DECK_DIRECTIONS = {
|
|
12
12
|
[ArrowStyles.NONE]: {forward: false, backward: false},
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
// deck.gl-community
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {render} from 'preact';
|
|
6
|
+
import type {ComponentChild, JSX} from 'preact';
|
|
7
|
+
import {
|
|
8
|
+
Widget,
|
|
9
|
+
type WidgetProps,
|
|
10
|
+
type WidgetPlacement,
|
|
11
|
+
type Deck
|
|
12
|
+
} from '@deck.gl/core';
|
|
13
|
+
import type {
|
|
14
|
+
GeoJsonEditModeConstructor,
|
|
15
|
+
GeoJsonEditModeType
|
|
16
|
+
} from '../edit-modes/geojson-edit-mode';
|
|
17
|
+
|
|
18
|
+
export type EditModeTrayWidgetModeOption = {
|
|
19
|
+
/**
|
|
20
|
+
* Optional identifier for the mode button.
|
|
21
|
+
* If not provided, one will be inferred from the supplied mode.
|
|
22
|
+
*/
|
|
23
|
+
id?: string;
|
|
24
|
+
/** Edit mode constructor or instance that the button should activate. */
|
|
25
|
+
mode: GeoJsonEditModeConstructor | GeoJsonEditModeType;
|
|
26
|
+
/**
|
|
27
|
+
* The icon or element rendered inside the button.
|
|
28
|
+
* A simple string can also be supplied for text labels.
|
|
29
|
+
*/
|
|
30
|
+
icon?: ComponentChild;
|
|
31
|
+
/** Optional text label rendered below the icon when provided. */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** Optional tooltip text applied to the button element. */
|
|
34
|
+
title?: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type EditModeTrayWidgetSelectEvent = {
|
|
38
|
+
id: string;
|
|
39
|
+
mode: GeoJsonEditModeConstructor | GeoJsonEditModeType;
|
|
40
|
+
option: EditModeTrayWidgetModeOption;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type EditModeTrayWidgetProps = WidgetProps & {
|
|
44
|
+
/** Placement for the widget root element. */
|
|
45
|
+
placement?: WidgetPlacement;
|
|
46
|
+
/** Layout direction for mode buttons. */
|
|
47
|
+
layout?: 'vertical' | 'horizontal';
|
|
48
|
+
/** Collection of modes rendered in the tray. */
|
|
49
|
+
modes?: EditModeTrayWidgetModeOption[];
|
|
50
|
+
/** Identifier of the currently active mode. */
|
|
51
|
+
selectedModeId?: string | null;
|
|
52
|
+
/** Currently active mode instance/constructor. */
|
|
53
|
+
activeMode?: GeoJsonEditModeConstructor | GeoJsonEditModeType | null;
|
|
54
|
+
/** Callback fired when the user selects a mode. */
|
|
55
|
+
onSelectMode?: (event: EditModeTrayWidgetSelectEvent) => void;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const ROOT_STYLE: Partial<CSSStyleDeclaration> = {
|
|
59
|
+
position: 'absolute',
|
|
60
|
+
display: 'flex',
|
|
61
|
+
pointerEvents: 'auto',
|
|
62
|
+
userSelect: 'none',
|
|
63
|
+
zIndex: '99'
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const TRAY_BASE_STYLE: JSX.CSSProperties = {
|
|
67
|
+
display: 'flex',
|
|
68
|
+
gap: '6px',
|
|
69
|
+
background: 'rgba(36, 40, 41, 0.88)',
|
|
70
|
+
borderRadius: '999px',
|
|
71
|
+
padding: '6px',
|
|
72
|
+
alignItems: 'center',
|
|
73
|
+
justifyContent: 'center',
|
|
74
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.25)'
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const BUTTON_BASE_STYLE: JSX.CSSProperties = {
|
|
78
|
+
appearance: 'none',
|
|
79
|
+
background: 'transparent',
|
|
80
|
+
border: 'none',
|
|
81
|
+
color: '#f0f0f0',
|
|
82
|
+
width: '34px',
|
|
83
|
+
height: '34px',
|
|
84
|
+
display: 'flex',
|
|
85
|
+
flexDirection: 'column',
|
|
86
|
+
alignItems: 'center',
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
borderRadius: '50%',
|
|
89
|
+
cursor: 'pointer',
|
|
90
|
+
padding: '0',
|
|
91
|
+
transition: 'background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease'
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const BUTTON_ACTIVE_STYLE: JSX.CSSProperties = {
|
|
95
|
+
background: '#0071e3',
|
|
96
|
+
color: '#ffffff',
|
|
97
|
+
boxShadow: '0 0 0 2px rgba(255, 255, 255, 0.35)'
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const BUTTON_LABEL_STYLE: JSX.CSSProperties = {
|
|
101
|
+
fontSize: '10px',
|
|
102
|
+
marginTop: '2px',
|
|
103
|
+
lineHeight: '12px'
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export class EditModeTrayWidget extends Widget<EditModeTrayWidgetProps> {
|
|
107
|
+
static override defaultProps = {
|
|
108
|
+
id: 'edit-mode-tray',
|
|
109
|
+
placement: 'top-left',
|
|
110
|
+
layout: 'vertical',
|
|
111
|
+
modes: [],
|
|
112
|
+
style: {},
|
|
113
|
+
className: ''
|
|
114
|
+
} satisfies Required<WidgetProps> &
|
|
115
|
+
Required<Pick<EditModeTrayWidgetProps, 'placement' | 'layout'>> &
|
|
116
|
+
EditModeTrayWidgetProps;
|
|
117
|
+
|
|
118
|
+
placement: WidgetPlacement = 'top-left';
|
|
119
|
+
className = 'deck-widget-edit-mode-tray';
|
|
120
|
+
layout: 'vertical' | 'horizontal' = 'vertical';
|
|
121
|
+
selectedModeId: string | null = null;
|
|
122
|
+
deck?: Deck | null = null;
|
|
123
|
+
private appliedCustomClassName: string | null = null;
|
|
124
|
+
|
|
125
|
+
constructor(props: EditModeTrayWidgetProps = {}) {
|
|
126
|
+
super({...EditModeTrayWidget.defaultProps, ...props});
|
|
127
|
+
this.placement = props.placement ?? EditModeTrayWidget.defaultProps.placement;
|
|
128
|
+
this.layout = props.layout ?? EditModeTrayWidget.defaultProps.layout;
|
|
129
|
+
this.selectedModeId = this.resolveSelectedModeId(props.modes ?? [], props);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
override setProps(props: Partial<EditModeTrayWidgetProps>): void {
|
|
133
|
+
if (props.placement !== undefined) {
|
|
134
|
+
this.placement = props.placement;
|
|
135
|
+
}
|
|
136
|
+
if (props.layout !== undefined) {
|
|
137
|
+
this.layout = props.layout;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const modes = props.modes ?? this.props.modes ?? [];
|
|
141
|
+
this.selectedModeId = this.resolveSelectedModeId(modes, props);
|
|
142
|
+
|
|
143
|
+
super.setProps(props);
|
|
144
|
+
this.renderTray();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
override onAdd({deck}: {deck: Deck}): void {
|
|
148
|
+
this.deck = deck;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
override onRemove(): void {
|
|
152
|
+
this.deck = null;
|
|
153
|
+
const root = this.rootElement;
|
|
154
|
+
if (root) {
|
|
155
|
+
render(null, root);
|
|
156
|
+
}
|
|
157
|
+
this.rootElement = null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
override onRenderHTML(rootElement: HTMLElement): void {
|
|
161
|
+
const style = {...ROOT_STYLE, ...this.props.style};
|
|
162
|
+
Object.assign(rootElement.style, style);
|
|
163
|
+
if (this.appliedCustomClassName && this.appliedCustomClassName !== this.props.className) {
|
|
164
|
+
rootElement.classList.remove(this.appliedCustomClassName);
|
|
165
|
+
this.appliedCustomClassName = null;
|
|
166
|
+
}
|
|
167
|
+
if (this.props.className) {
|
|
168
|
+
rootElement.classList.add(this.props.className);
|
|
169
|
+
this.appliedCustomClassName = this.props.className;
|
|
170
|
+
}
|
|
171
|
+
rootElement.classList.add(this.className);
|
|
172
|
+
|
|
173
|
+
this.renderTray();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private renderTray() {
|
|
177
|
+
const root = this.rootElement;
|
|
178
|
+
if (!root) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const modes = this.props.modes ?? [];
|
|
183
|
+
const selectedId = this.selectedModeId;
|
|
184
|
+
const direction = this.layout === 'horizontal' ? 'row' : 'column';
|
|
185
|
+
|
|
186
|
+
const trayStyle: JSX.CSSProperties = {
|
|
187
|
+
...TRAY_BASE_STYLE,
|
|
188
|
+
flexDirection: direction
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const stopEvent = (event: Event) => {
|
|
192
|
+
event.stopPropagation();
|
|
193
|
+
if (typeof (event as any).stopImmediatePropagation === 'function') {
|
|
194
|
+
(event as any).stopImmediatePropagation();
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const ui = (
|
|
199
|
+
<div
|
|
200
|
+
style={trayStyle}
|
|
201
|
+
onPointerDown={stopEvent}
|
|
202
|
+
onPointerMove={stopEvent}
|
|
203
|
+
onPointerUp={stopEvent}
|
|
204
|
+
onMouseDown={stopEvent}
|
|
205
|
+
onMouseMove={stopEvent}
|
|
206
|
+
onMouseUp={stopEvent}
|
|
207
|
+
onTouchStart={stopEvent}
|
|
208
|
+
onTouchMove={stopEvent}
|
|
209
|
+
onTouchEnd={stopEvent}
|
|
210
|
+
>
|
|
211
|
+
{modes.map((option, index) => {
|
|
212
|
+
const id = this.getModeId(option, index);
|
|
213
|
+
const active = id === selectedId;
|
|
214
|
+
const label = option.label ?? '';
|
|
215
|
+
const title = option.title ?? label;
|
|
216
|
+
|
|
217
|
+
const buttonStyle: JSX.CSSProperties = {
|
|
218
|
+
...BUTTON_BASE_STYLE,
|
|
219
|
+
...(active ? BUTTON_ACTIVE_STYLE : {})
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<button
|
|
224
|
+
key={id}
|
|
225
|
+
type="button"
|
|
226
|
+
title={title || undefined}
|
|
227
|
+
aria-pressed={active}
|
|
228
|
+
style={buttonStyle}
|
|
229
|
+
onClick={(event) => {
|
|
230
|
+
stopEvent(event);
|
|
231
|
+
this.handleSelect(option, id);
|
|
232
|
+
}}
|
|
233
|
+
>
|
|
234
|
+
{option.icon}
|
|
235
|
+
{label ? <span style={BUTTON_LABEL_STYLE}>{label}</span> : null}
|
|
236
|
+
</button>
|
|
237
|
+
);
|
|
238
|
+
})}
|
|
239
|
+
</div>
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
render(ui, root);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private handleSelect(option: EditModeTrayWidgetModeOption, id: string) {
|
|
246
|
+
if (this.selectedModeId !== id) {
|
|
247
|
+
this.selectedModeId = id;
|
|
248
|
+
this.renderTray();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
this.props.onSelectMode?.({
|
|
252
|
+
id,
|
|
253
|
+
mode: option.mode,
|
|
254
|
+
option
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private resolveSelectedModeId(
|
|
259
|
+
modes: EditModeTrayWidgetModeOption[],
|
|
260
|
+
props: Partial<EditModeTrayWidgetProps>
|
|
261
|
+
): string | null {
|
|
262
|
+
if (props.selectedModeId !== undefined) {
|
|
263
|
+
return props.selectedModeId;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const activeMode = props.activeMode ?? this.props?.activeMode ?? null;
|
|
267
|
+
if (activeMode) {
|
|
268
|
+
const match = this.findOptionByMode(modes, activeMode);
|
|
269
|
+
if (match) {
|
|
270
|
+
return this.getModeId(match.option, match.index);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (this.selectedModeId) {
|
|
275
|
+
const existing = this.findOptionById(modes, this.selectedModeId);
|
|
276
|
+
if (existing) {
|
|
277
|
+
return this.selectedModeId;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const first = modes[0];
|
|
282
|
+
return first ? this.getModeId(first, 0) : null;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private findOptionByMode(
|
|
286
|
+
modes: EditModeTrayWidgetModeOption[],
|
|
287
|
+
activeMode: GeoJsonEditModeConstructor | GeoJsonEditModeType
|
|
288
|
+
): {option: EditModeTrayWidgetModeOption; index: number} | null {
|
|
289
|
+
for (let index = 0; index < modes.length; index++) {
|
|
290
|
+
const option = modes[index];
|
|
291
|
+
if (option.mode === activeMode) {
|
|
292
|
+
return {option, index};
|
|
293
|
+
}
|
|
294
|
+
if (this.isSameMode(option.mode, activeMode)) {
|
|
295
|
+
return {option, index};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private findOptionById(
|
|
302
|
+
modes: EditModeTrayWidgetModeOption[],
|
|
303
|
+
id: string
|
|
304
|
+
): {option: EditModeTrayWidgetModeOption; index: number} | null {
|
|
305
|
+
for (let index = 0; index < modes.length; index++) {
|
|
306
|
+
if (this.getModeId(modes[index], index) === id) {
|
|
307
|
+
return {option: modes[index], index};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private getModeId(option: EditModeTrayWidgetModeOption, index: number): string {
|
|
314
|
+
if (option.id) {
|
|
315
|
+
return option.id;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const mode = option.mode as any;
|
|
319
|
+
if (mode) {
|
|
320
|
+
if (typeof mode === 'function' && mode.name) {
|
|
321
|
+
return mode.name;
|
|
322
|
+
}
|
|
323
|
+
if (mode && mode.constructor && mode.constructor.name) {
|
|
324
|
+
return mode.constructor.name;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return `mode-${index}`;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private isSameMode(
|
|
332
|
+
modeA: GeoJsonEditModeConstructor | GeoJsonEditModeType,
|
|
333
|
+
modeB: GeoJsonEditModeConstructor | GeoJsonEditModeType
|
|
334
|
+
): boolean {
|
|
335
|
+
if (modeA === modeB) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
const constructorA = (modeA as GeoJsonEditModeType)?.constructor;
|
|
339
|
+
const constructorB = (modeB as GeoJsonEditModeType)?.constructor;
|
|
340
|
+
return Boolean(constructorA && constructorB && constructorA === constructorB);
|
|
341
|
+
}
|
|
342
|
+
}
|