@versatiles/svelte 2.0.1 → 2.1.0

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.
Files changed (83) hide show
  1. package/dist/components/BBoxMap/BBoxMap.svelte +23 -12
  2. package/dist/components/BBoxMap/lib/bbox.d.ts +1 -1
  3. package/dist/components/BBoxMap/lib/bbox.js +19 -17
  4. package/dist/components/BasicMap/BasicMap.svelte +22 -9
  5. package/dist/components/BasicMap/BasicMap.svelte.d.ts +2 -1
  6. package/dist/components/MapEditor/MapEditor.svelte +51 -20
  7. package/dist/components/MapEditor/components/Dialog.svelte +92 -0
  8. package/dist/components/MapEditor/components/Dialog.svelte.d.ts +17 -0
  9. package/dist/components/MapEditor/components/DialogFile.svelte +112 -0
  10. package/dist/components/MapEditor/components/DialogFile.svelte.d.ts +6 -0
  11. package/dist/components/MapEditor/components/DialogShare.svelte +216 -0
  12. package/dist/components/MapEditor/components/DialogShare.svelte.d.ts +10 -0
  13. package/dist/components/MapEditor/components/Editor.svelte +6 -14
  14. package/dist/components/MapEditor/components/EditorFill.svelte +3 -3
  15. package/dist/components/MapEditor/components/EditorStroke.svelte +3 -3
  16. package/dist/components/MapEditor/components/EditorSymbol.svelte +9 -9
  17. package/dist/components/MapEditor/components/InputRow.svelte +2 -3
  18. package/dist/components/MapEditor/components/PanelFile.svelte +73 -0
  19. package/dist/components/MapEditor/components/PanelFile.svelte.d.ts +7 -0
  20. package/dist/components/MapEditor/components/PanelSymbolSelector.svelte +82 -0
  21. package/dist/components/MapEditor/components/PanelSymbolSelector.svelte.d.ts +8 -0
  22. package/dist/components/MapEditor/components/Sidebar.svelte +51 -98
  23. package/dist/components/MapEditor/components/Sidebar.svelte.d.ts +3 -3
  24. package/dist/components/MapEditor/components/SidebarPanel.svelte +13 -5
  25. package/dist/components/MapEditor/lib/element/abstract.d.ts +8 -4
  26. package/dist/components/MapEditor/lib/element/abstract.js +10 -1
  27. package/dist/components/MapEditor/lib/element/abstract_path.d.ts +3 -2
  28. package/dist/components/MapEditor/lib/element/abstract_path.js +6 -3
  29. package/dist/components/MapEditor/lib/element/circle.d.ts +25 -0
  30. package/dist/components/MapEditor/lib/element/circle.js +118 -0
  31. package/dist/components/MapEditor/lib/element/line.d.ts +2 -2
  32. package/dist/components/MapEditor/lib/element/line.js +1 -1
  33. package/dist/components/MapEditor/lib/element/marker.d.ts +4 -3
  34. package/dist/components/MapEditor/lib/element/marker.js +2 -2
  35. package/dist/components/MapEditor/lib/element/polygon.d.ts +2 -2
  36. package/dist/components/MapEditor/lib/element/polygon.js +2 -2
  37. package/dist/components/MapEditor/lib/element/types.d.ts +2 -3
  38. package/dist/components/MapEditor/lib/geometry_manager.d.ts +12 -29
  39. package/dist/components/MapEditor/lib/geometry_manager.js +44 -160
  40. package/dist/components/MapEditor/lib/geometry_manager_interactive.d.ts +33 -0
  41. package/dist/components/MapEditor/lib/geometry_manager_interactive.js +102 -0
  42. package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +2 -1
  43. package/dist/components/MapEditor/lib/map_layer/abstract.js +25 -22
  44. package/dist/components/MapEditor/lib/map_layer/fill.js +2 -4
  45. package/dist/components/MapEditor/lib/map_layer/line.js +1 -1
  46. package/dist/components/MapEditor/lib/map_layer/symbol.js +1 -1
  47. package/dist/components/MapEditor/lib/selection.d.ts +11 -0
  48. package/dist/components/MapEditor/lib/selection.js +70 -0
  49. package/dist/components/MapEditor/lib/state/constants.js +5 -6
  50. package/dist/components/MapEditor/lib/state/history.d.ts +14 -0
  51. package/dist/components/MapEditor/lib/state/history.js +53 -0
  52. package/dist/components/MapEditor/lib/state/manager.d.ts +7 -10
  53. package/dist/components/MapEditor/lib/state/manager.js +19 -54
  54. package/dist/components/MapEditor/lib/state/reader.d.ts +6 -4
  55. package/dist/components/MapEditor/lib/state/reader.js +70 -18
  56. package/dist/components/MapEditor/lib/state/types.d.ts +19 -2
  57. package/dist/components/MapEditor/lib/state/utils.d.ts +2 -0
  58. package/dist/components/MapEditor/lib/state/utils.js +12 -0
  59. package/dist/components/MapEditor/lib/state/writer.d.ts +6 -4
  60. package/dist/components/MapEditor/lib/state/writer.js +59 -19
  61. package/dist/components/MapEditor/lib/symbols.d.ts +1 -1
  62. package/dist/components/MapEditor/lib/symbols.js +47 -28
  63. package/dist/components/MapEditor/lib/utils/event_handler.d.ts +10 -0
  64. package/dist/components/MapEditor/lib/utils/event_handler.js +39 -0
  65. package/dist/components/MapEditor/lib/utils/geometry.d.ts +12 -0
  66. package/dist/components/MapEditor/lib/utils/geometry.js +87 -0
  67. package/dist/components/MapEditor/lib/utils/types.d.ts +2 -0
  68. package/dist/components/MapEditor/lib/utils/types.js +1 -0
  69. package/dist/components/MapEditor/style/button.scss +115 -0
  70. package/dist/components/MapEditor/style/index.scss +3 -0
  71. package/dist/components/MapEditor/style/layout.scss +20 -0
  72. package/dist/components/MapEditor/style/other.scss +10 -0
  73. package/dist/utils/location.d.ts +1 -0
  74. package/dist/utils/location.js +181 -0
  75. package/dist/utils/map_style.d.ts +2 -2
  76. package/dist/utils/map_style.js +2 -2
  77. package/package.json +29 -29
  78. package/dist/components/MapEditor/components/SymbolSelector.svelte +0 -110
  79. package/dist/components/MapEditor/components/SymbolSelector.svelte.d.ts +0 -8
  80. package/dist/components/MapEditor/lib/utils.d.ts +0 -6
  81. package/dist/components/MapEditor/lib/utils.js +0 -23
  82. /package/dist/components/MapEditor/lib/{geocoder.d.ts → utils/geocoder.d.ts} +0 -0
  83. /package/dist/components/MapEditor/lib/{geocoder.js → utils/geocoder.js} +0 -0
@@ -1,38 +1,21 @@
1
- import { type Writable } from 'svelte/store';
2
1
  import type { AbstractElement } from './element/abstract.js';
3
- import { MarkerElement } from './element/marker.js';
4
- import { LineElement } from './element/line.js';
5
- import { PolygonElement } from './element/polygon.js';
6
- import { Cursor } from './cursor.js';
7
- import { SymbolLibrary } from './symbols.js';
8
- import { StateManager } from './state/manager.js';
2
+ import type { GeometryManagerInteractive } from './geometry_manager_interactive.js';
3
+ import type { SelectionHandler } from './selection.js';
4
+ import type { StateManager } from './state/manager.js';
9
5
  import type { StateRoot } from './state/types.js';
10
- export type ExtendedGeoJSON = GeoJSON.FeatureCollection & {
11
- map?: {
12
- center: [number, number];
13
- zoom: number;
14
- };
15
- };
6
+ import { type Writable } from 'svelte/store';
16
7
  export declare class GeometryManager {
17
8
  readonly elements: Writable<AbstractElement[]>;
18
9
  readonly map: maplibregl.Map;
19
- readonly selectedElement: Writable<AbstractElement | undefined>;
20
10
  readonly canvas: HTMLElement;
21
- readonly cursor: Cursor;
22
- readonly symbolLibrary: SymbolLibrary;
23
- readonly state: StateManager;
24
- private readonly selectionNodes;
11
+ readonly state: StateManager | null;
12
+ readonly selection: SelectionHandler | null;
25
13
  constructor(map: maplibregl.Map);
26
- selectElement(element: AbstractElement | undefined): void;
27
- drawSelectionNodes(): void;
28
- getState(): StateRoot;
29
- setState(state: StateRoot): void;
30
- getElement(index: number): AbstractElement;
31
- addNewMarker(): MarkerElement;
32
- addNewLine(): LineElement;
33
- addNewPolygon(): PolygonElement;
34
- private appendElement;
14
+ isInteractive(): this is GeometryManagerInteractive;
15
+ clear(): void;
16
+ protected appendElement(element: AbstractElement): void;
35
17
  removeElement(element: AbstractElement): void;
36
- getGeoJSON(): GeoJSON.FeatureCollection;
37
- addGeoJSON(geojson: ExtendedGeoJSON): void;
18
+ loadState(state: StateRoot): Promise<void>;
19
+ setState(state: StateRoot): Promise<void>;
20
+ getElement(index: number): AbstractElement;
38
21
  }
@@ -1,31 +1,26 @@
1
1
  import { get, writable } from 'svelte/store';
2
- import { MarkerElement } from './element/marker.js';
2
+ import { getMapStyle } from '../../../utils/map_style.js';
3
+ import { CircleElement } from './element/circle.js';
3
4
  import { LineElement } from './element/line.js';
5
+ import { MarkerElement } from './element/marker.js';
4
6
  import { PolygonElement } from './element/polygon.js';
5
- import { Cursor } from './cursor.js';
6
- import { SymbolLibrary } from './symbols.js';
7
- import { StateManager } from './state/manager.js';
8
7
  export class GeometryManager {
9
8
  elements;
10
9
  map;
11
- selectedElement = writable(undefined);
12
10
  canvas;
13
- cursor;
14
- symbolLibrary;
15
- state;
16
- selectionNodes;
11
+ state = null;
12
+ selection = null;
17
13
  constructor(map) {
18
14
  this.elements = writable([]);
19
15
  this.map = map;
20
16
  this.canvas = this.map.getCanvasContainer();
21
- this.cursor = new Cursor(this.canvas);
22
- this.symbolLibrary = new SymbolLibrary(map);
23
- map.addSource('selection_nodes', {
17
+ const style = getMapStyle({ darkMode: false });
18
+ style.transition = { duration: 0, delay: 0 };
19
+ style.sources.selection_nodes = {
24
20
  type: 'geojson',
25
21
  data: { type: 'FeatureCollection', features: [] }
26
- });
27
- this.selectionNodes = map.getSource('selection_nodes');
28
- map.addLayer({
22
+ };
23
+ style.layers.push({
29
24
  id: 'selection_nodes',
30
25
  source: 'selection_nodes',
31
26
  type: 'circle',
@@ -39,91 +34,46 @@ export class GeometryManager {
39
34
  'circle-stroke-width': 1
40
35
  }
41
36
  });
42
- map.on('mousedown', 'selection_nodes', (e) => {
43
- const element = get(this.selectedElement);
44
- if (element == undefined)
45
- return;
46
- const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
47
- const selectedNode = element.getSelectionNodeUpdater(feature.properties);
48
- if (selectedNode == undefined)
49
- return;
50
- // @ts-expect-error ensure that the event is ignored by other layers
51
- e.ignore = true;
52
- e.preventDefault();
53
- if (e.originalEvent.shiftKey) {
54
- selectedNode.delete();
55
- this.drawSelectionNodes();
56
- }
57
- else {
58
- const onMove = (e) => {
59
- e.preventDefault();
60
- selectedNode.update(e.lngLat.lng, e.lngLat.lat);
61
- this.drawSelectionNodes();
62
- };
63
- map.on('mousemove', onMove);
64
- map.once('mouseup', () => {
65
- map.off('mousemove', onMove);
66
- this.state.log();
67
- });
68
- }
69
- });
70
- map.on('mouseenter', 'selection_nodes', () => {
71
- this.cursor.togglePrecise('selection_nodes');
72
- });
73
- map.on('mouseleave', 'selection_nodes', () => {
74
- this.cursor.togglePrecise('selection_nodes', false);
75
- });
76
- map.on('click', (e) => {
77
- if (!e.originalEvent.shiftKey)
78
- this.selectElement(undefined);
79
- e.preventDefault();
80
- });
81
- this.state = new StateManager(this);
37
+ map.setStyle(style);
82
38
  }
83
- selectElement(element) {
84
- if (element == get(this.selectedElement))
85
- return;
86
- const elements = get(this.elements);
87
- elements.forEach((e) => e.select(e == element));
88
- this.selectedElement.set(element);
89
- this.drawSelectionNodes();
39
+ isInteractive() {
40
+ return false;
90
41
  }
91
- drawSelectionNodes() {
92
- const nodes = get(this.selectedElement)?.getSelectionNodes() ?? [];
93
- this.selectionNodes.setData({
94
- type: 'FeatureCollection',
95
- features: nodes.map((n) => ({
96
- type: 'Feature',
97
- properties: { index: n.index, opacity: n.transparent ? 0.3 : 1 },
98
- geometry: { type: 'Point', coordinates: n.coordinates }
99
- }))
42
+ clear() {
43
+ this.elements.update((elements) => {
44
+ elements.forEach((e) => e.destroy());
45
+ return [];
100
46
  });
101
47
  }
102
- getState() {
103
- const center = this.map.getCenter();
104
- return {
105
- map: {
106
- center: [center.lng, center.lat],
107
- zoom: this.map.getZoom()
108
- },
109
- elements: get(this.elements).map((element) => element.getState())
110
- };
48
+ appendElement(element) {
49
+ this.elements.update((elements) => [...elements, element]);
50
+ }
51
+ removeElement(element) {
52
+ this.elements.update((elements) => elements.filter((e) => e !== element));
111
53
  }
112
- setState(state) {
54
+ async loadState(state) {
113
55
  if (!state)
114
56
  return;
115
- this.selectElement(undefined);
116
- this.elements.update((elements) => {
117
- elements.forEach((e) => e.destroy());
118
- return [];
119
- });
57
+ this.clear();
58
+ this.setState(state);
59
+ this.state?.history.reset(state);
60
+ }
61
+ async setState(state) {
62
+ if (!state)
63
+ return;
64
+ this.clear();
120
65
  if (state.map) {
121
- if (state.map.zoom)
122
- this.map.setZoom(state.map.zoom);
123
- if (state.map.center) {
124
- const [lng, lat] = state.map.center;
125
- this.map.setCenter({ lng, lat });
126
- }
66
+ const { center, radius } = state.map;
67
+ const dy = (radius * 360) / 40074000;
68
+ const dx = dy / Math.cos((center[1] * Math.PI) / 180);
69
+ const bounds = [
70
+ [center[0] - dx, center[1] - dy],
71
+ [center[0] + dx, center[1] + dy]
72
+ ];
73
+ this.map.fitBounds(bounds, { animate: false });
74
+ }
75
+ if (!this.map.isStyleLoaded()) {
76
+ await new Promise((r) => this.map.once('styledata', r));
127
77
  }
128
78
  if (state.elements) {
129
79
  const elements = state.elements.map((element) => {
@@ -134,6 +84,8 @@ export class GeometryManager {
134
84
  return LineElement.fromState(this, element);
135
85
  case 'polygon':
136
86
  return PolygonElement.fromState(this, element);
87
+ case 'circle':
88
+ return CircleElement.fromState(this, element);
137
89
  default:
138
90
  throw new Error('Unknown element type');
139
91
  }
@@ -144,72 +96,4 @@ export class GeometryManager {
144
96
  getElement(index) {
145
97
  return get(this.elements)[index];
146
98
  }
147
- addNewMarker() {
148
- const element = new MarkerElement(this);
149
- this.appendElement(element);
150
- this.selectElement(element);
151
- return element;
152
- }
153
- addNewLine() {
154
- const element = new LineElement(this);
155
- this.appendElement(element);
156
- this.selectElement(element);
157
- return element;
158
- }
159
- addNewPolygon() {
160
- const element = new PolygonElement(this);
161
- this.appendElement(element);
162
- this.selectElement(element);
163
- return element;
164
- }
165
- appendElement(element) {
166
- this.elements.update((elements) => [...elements, element]);
167
- }
168
- removeElement(element) {
169
- if (get(this.selectedElement) === element)
170
- this.selectElement(undefined);
171
- this.elements.update((elements) => elements.filter((e) => e !== element));
172
- }
173
- getGeoJSON() {
174
- const center = this.map.getCenter();
175
- return {
176
- type: 'FeatureCollection',
177
- map: {
178
- center: [center.lng, center.lat],
179
- zoom: this.map.getZoom()
180
- },
181
- features: get(this.elements).map((element) => element.getFeature(true))
182
- };
183
- }
184
- addGeoJSON(geojson) {
185
- if ('map' in geojson && geojson.map) {
186
- const { map } = geojson;
187
- if (typeof map.zoom === 'number') {
188
- this.map.setZoom(map.zoom);
189
- }
190
- if (Array.isArray(map.center)) {
191
- const [lng, lat] = map.center;
192
- if (typeof lng === 'number' && typeof lat === 'number') {
193
- this.map.setCenter({ lng, lat });
194
- }
195
- }
196
- }
197
- for (const feature of geojson.features) {
198
- let element;
199
- switch (feature.geometry.type) {
200
- case 'Point':
201
- element = MarkerElement.fromGeoJSON(this, feature);
202
- break;
203
- case 'LineString':
204
- element = LineElement.fromGeoJSON(this, feature);
205
- break;
206
- case 'Polygon':
207
- element = PolygonElement.fromGeoJSON(this, feature);
208
- break;
209
- default:
210
- throw new Error(`Unknown geometry type "${feature.geometry.type}"`);
211
- }
212
- this.appendElement(element);
213
- }
214
- }
215
99
  }
@@ -0,0 +1,33 @@
1
+ import type { AbstractElement } from './element/abstract.js';
2
+ import { CircleElement } from './element/circle.js';
3
+ import { LineElement } from './element/line.js';
4
+ import { MarkerElement } from './element/marker.js';
5
+ import { PolygonElement } from './element/polygon.js';
6
+ import { GeometryManager } from './geometry_manager.js';
7
+ import { SelectionHandler } from './selection.js';
8
+ import { Cursor } from './cursor.js';
9
+ import { StateManager } from './state/manager.js';
10
+ import type { StateRoot } from './state/types.js';
11
+ export type ExtendedGeoJSON = GeoJSON.FeatureCollection & {
12
+ map?: {
13
+ center: [number, number];
14
+ zoom: number;
15
+ };
16
+ };
17
+ export declare class GeometryManagerInteractive extends GeometryManager {
18
+ readonly selection: SelectionHandler;
19
+ readonly cursor: Cursor;
20
+ readonly state: StateManager;
21
+ constructor(map: maplibregl.Map);
22
+ clear(): void;
23
+ isInteractive(): this is GeometryManagerInteractive;
24
+ removeElement(element: AbstractElement): void;
25
+ addNewElement(type: 'marker'): MarkerElement;
26
+ addNewElement(type: 'line'): LineElement;
27
+ addNewElement(type: 'polygon'): PolygonElement;
28
+ addNewElement(type: 'circle'): CircleElement;
29
+ addNewElement(type: 'marker' | 'line' | 'polygon' | 'circle'): AbstractElement;
30
+ getGeoJSON(): GeoJSON.FeatureCollection;
31
+ getState(): StateRoot;
32
+ addGeoJSON(geojson: ExtendedGeoJSON): void;
33
+ }
@@ -0,0 +1,102 @@
1
+ import { get } from 'svelte/store';
2
+ import { CircleElement } from './element/circle.js';
3
+ import { LineElement } from './element/line.js';
4
+ import { MarkerElement } from './element/marker.js';
5
+ import { PolygonElement } from './element/polygon.js';
6
+ import { GeometryManager } from './geometry_manager.js';
7
+ import { SelectionHandler } from './selection.js';
8
+ import { flatten } from './utils/geometry.js';
9
+ import { Cursor } from './cursor.js';
10
+ import { StateManager } from './state/manager.js';
11
+ export class GeometryManagerInteractive extends GeometryManager {
12
+ selection;
13
+ cursor;
14
+ state;
15
+ constructor(map) {
16
+ super(map);
17
+ this.cursor = new Cursor(map.getCanvasContainer());
18
+ this.selection = new SelectionHandler(this);
19
+ this.state = new StateManager(this);
20
+ }
21
+ clear() {
22
+ this.selection.selectElement();
23
+ super.clear();
24
+ }
25
+ isInteractive() {
26
+ return true;
27
+ }
28
+ removeElement(element) {
29
+ this.selection.selectElement();
30
+ super.removeElement(element);
31
+ }
32
+ addNewElement(type) {
33
+ const AbstractClass = {
34
+ marker: MarkerElement,
35
+ line: LineElement,
36
+ polygon: PolygonElement,
37
+ circle: CircleElement
38
+ }[type];
39
+ const element = new AbstractClass(this);
40
+ this.appendElement(element);
41
+ this.selection.selectElement(element);
42
+ return element;
43
+ }
44
+ getGeoJSON() {
45
+ const center = this.map.getCenter();
46
+ return {
47
+ type: 'FeatureCollection',
48
+ map: {
49
+ center: [center.lng, center.lat],
50
+ zoom: this.map.getZoom()
51
+ },
52
+ features: get(this.elements).map((element) => element.getGeoJSON())
53
+ };
54
+ }
55
+ getState() {
56
+ const center = this.map.getCenter();
57
+ const bounds = this.map.getBounds();
58
+ const radiusDegrees = Math.min(bounds.getNorth() - bounds.getSouth(), (bounds.getEast() - bounds.getWest()) * Math.cos((center.lat * Math.PI) / 180)) / 2;
59
+ const radius = 40074000 * (radiusDegrees / 360);
60
+ return {
61
+ map: {
62
+ center: [center.lng, center.lat],
63
+ radius
64
+ },
65
+ elements: get(this.elements).map((element) => element.getState())
66
+ };
67
+ }
68
+ addGeoJSON(geojson) {
69
+ if ('map' in geojson && geojson.map) {
70
+ const { map } = geojson;
71
+ if (typeof map.zoom === 'number') {
72
+ this.map.setZoom(map.zoom);
73
+ }
74
+ if (Array.isArray(map.center)) {
75
+ const [lng, lat] = map.center;
76
+ if (typeof lng === 'number' && typeof lat === 'number') {
77
+ this.map.setCenter({ lng, lat });
78
+ }
79
+ }
80
+ }
81
+ for (const feature of flatten(geojson.features)) {
82
+ let element;
83
+ const p = feature.properties;
84
+ switch (feature.geometry.type) {
85
+ case 'Point':
86
+ if (p && p.subType == 'Circle' && p.radius != null) {
87
+ element = CircleElement.fromGeoJSON(this, feature);
88
+ break;
89
+ }
90
+ element = MarkerElement.fromGeoJSON(this, feature);
91
+ break;
92
+ case 'LineString':
93
+ element = LineElement.fromGeoJSON(this, feature);
94
+ break;
95
+ case 'Polygon':
96
+ element = PolygonElement.fromGeoJSON(this, feature);
97
+ break;
98
+ }
99
+ this.appendElement(element);
100
+ }
101
+ }
102
+ }
@@ -1,6 +1,7 @@
1
1
  import type { LayerFill, LayerLine, LayerSymbol } from './types.js';
2
2
  import type { GeometryManager } from '../geometry_manager.js';
3
3
  import type { StateStyle } from '../state/types.js';
4
+ import type { GeometryManagerInteractive } from '../geometry_manager_interactive.js';
4
5
  type LayerSpec = LayerFill | LayerLine | LayerSymbol;
5
6
  type Events = 'click' | 'mousedown' | 'mousemove' | 'mouseup';
6
7
  type MouseEventHandler = (event: maplibregl.MapMouseEvent) => void;
@@ -8,7 +9,7 @@ export declare abstract class MapLayer<T extends LayerSpec> {
8
9
  private layout;
9
10
  private paint;
10
11
  protected readonly id: string;
11
- readonly manager: GeometryManager;
12
+ readonly manager: GeometryManager | GeometryManagerInteractive;
12
13
  protected readonly map: maplibregl.Map;
13
14
  eventHandlers: Map<Events, MouseEventHandler[]>;
14
15
  isSelected: boolean;
@@ -45,28 +45,31 @@ export class MapLayer {
45
45
  handlers.forEach((handler) => handler(e));
46
46
  }
47
47
  addEvents() {
48
- this.map.on('mouseenter', this.id, () => {
49
- if (this.isSelected)
50
- this.manager.cursor.toggleGrab(this.id);
51
- this.manager.cursor.toggleHover(this.id);
52
- });
53
- this.map.on('mouseleave', this.id, () => {
54
- if (this.isSelected)
55
- this.manager.cursor.toggleGrab(this.id, false);
56
- this.manager.cursor.toggleHover(this.id, false);
57
- });
58
- this.map.on('click', this.id, (e) => {
59
- this.dispatchEvent('click', e);
60
- if (this.isSelected)
61
- this.manager.cursor.toggleGrab(this.id);
62
- this.manager.cursor.toggleHover(this.id);
63
- e.preventDefault();
64
- });
65
- this.map.on('mousedown', this.id, (e) => {
66
- if (this.manager.cursor.isPrecise())
67
- return;
68
- this.dispatchEvent('mousedown', e);
69
- });
48
+ const manager = this.manager;
49
+ if (manager.isInteractive()) {
50
+ this.map.on('mouseenter', this.id, () => {
51
+ if (this.isSelected)
52
+ manager.cursor.toggleGrab(this.id);
53
+ manager.cursor.toggleHover(this.id);
54
+ });
55
+ this.map.on('mouseleave', this.id, () => {
56
+ if (this.isSelected)
57
+ manager.cursor.toggleGrab(this.id, false);
58
+ manager.cursor.toggleHover(this.id, false);
59
+ });
60
+ this.map.on('click', this.id, (e) => {
61
+ this.dispatchEvent('click', e);
62
+ if (this.isSelected)
63
+ manager.cursor.toggleGrab(this.id);
64
+ manager.cursor.toggleHover(this.id);
65
+ e.preventDefault();
66
+ });
67
+ this.map.on('mousedown', this.id, (e) => {
68
+ if (manager.cursor.isPrecise())
69
+ return;
70
+ this.dispatchEvent('mousedown', e);
71
+ });
72
+ }
70
73
  this.map.on('mouseup', this.id, (e) => this.dispatchEvent('mouseup', e));
71
74
  this.map.on('mousemove', this.id, (e) => this.dispatchEvent('mousemove', e));
72
75
  }
@@ -1,7 +1,7 @@
1
1
  import { get, writable } from 'svelte/store';
2
2
  import { MapLayer } from './abstract.js';
3
3
  import { Color } from '@versatiles/style';
4
- import { removeDefaultFields } from '../utils.js';
4
+ import { removeDefaultFields } from '../state/utils.js';
5
5
  const size = 32;
6
6
  export const fillPatterns = new Map([
7
7
  [0, { name: 'solid', fill: undefined }],
@@ -86,9 +86,7 @@ export class MapLayerFill extends MapLayer {
86
86
  if (properties['fill-opacity'])
87
87
  this.opacity.set(properties['fill-opacity']);
88
88
  if (properties['fill-pattern']) {
89
- const pattern = fillPatterns
90
- .entries()
91
- .find(([, { name }]) => name === properties['fill-pattern']);
89
+ const pattern = fillPatterns.entries().find(([, { name }]) => name === properties['fill-pattern']);
92
90
  if (pattern)
93
91
  this.pattern.set(pattern[0]);
94
92
  }
@@ -1,7 +1,7 @@
1
1
  import { derived, get, writable } from 'svelte/store';
2
2
  import { MapLayer } from './abstract.js';
3
3
  import { Color } from '@versatiles/style';
4
- import { removeDefaultFields } from '../utils.js';
4
+ import { removeDefaultFields } from '../state/utils.js';
5
5
  export const dashArrays = new Map([
6
6
  [0, { name: 'solid', array: [100] }],
7
7
  [1, { name: 'dashed', array: [2, 4] }],
@@ -2,7 +2,7 @@ import { derived, get, writable } from 'svelte/store';
2
2
  import { MapLayer } from './abstract.js';
3
3
  import { Color } from '@versatiles/style';
4
4
  import { getSymbol, getSymbolIndexByName } from '../symbols.js';
5
- import { removeDefaultFields } from '../utils.js';
5
+ import { removeDefaultFields } from '../state/utils.js';
6
6
  export const labelPositions = [
7
7
  { index: 0, name: 'auto' },
8
8
  { index: 1, name: 'right', anchor: 'left' },
@@ -0,0 +1,11 @@
1
+ import { type Writable } from 'svelte/store';
2
+ import type { AbstractElement } from './element/abstract.js';
3
+ import type { GeometryManagerInteractive } from './geometry_manager_interactive.js';
4
+ export declare class SelectionHandler {
5
+ readonly selectedElement: Writable<AbstractElement | undefined>;
6
+ private selectionNodes;
7
+ private manager;
8
+ constructor(manager: GeometryManagerInteractive);
9
+ selectElement(element?: AbstractElement): void;
10
+ updateSelectionNodes(): void;
11
+ }
@@ -0,0 +1,70 @@
1
+ import { get, writable } from 'svelte/store';
2
+ export class SelectionHandler {
3
+ selectedElement = writable(undefined);
4
+ selectionNodes;
5
+ manager;
6
+ constructor(manager) {
7
+ this.manager = manager;
8
+ const map = this.manager.map;
9
+ map.on('mousedown', 'selection_nodes', (e) => {
10
+ const element = get(this.selectedElement);
11
+ if (element == null)
12
+ return;
13
+ const feature = map.queryRenderedFeatures(e.point, { layers: ['selection_nodes'] })[0];
14
+ const selectedNode = element.getSelectionNodeUpdater(feature.properties);
15
+ if (selectedNode == null)
16
+ return;
17
+ // @ts-expect-error ensure that the event is ignored by other layers
18
+ e.ignore = true;
19
+ e.preventDefault();
20
+ if (e.originalEvent.shiftKey) {
21
+ selectedNode.delete();
22
+ this.updateSelectionNodes();
23
+ }
24
+ else {
25
+ const onMove = (e) => {
26
+ e.preventDefault();
27
+ selectedNode.update(e.lngLat.lng, e.lngLat.lat);
28
+ this.updateSelectionNodes();
29
+ };
30
+ map.on('mousemove', onMove);
31
+ map.once('mouseup', () => {
32
+ map.off('mousemove', onMove);
33
+ this.manager.state.log();
34
+ });
35
+ }
36
+ });
37
+ map.on('mouseenter', 'selection_nodes', () => {
38
+ this.manager.cursor.togglePrecise('selection_nodes');
39
+ });
40
+ map.on('mouseleave', 'selection_nodes', () => {
41
+ this.manager.cursor.togglePrecise('selection_nodes', false);
42
+ });
43
+ map.on('click', (e) => {
44
+ if (!e.originalEvent.shiftKey)
45
+ this.selectElement();
46
+ e.preventDefault();
47
+ });
48
+ }
49
+ selectElement(element) {
50
+ if (element == get(this.selectedElement))
51
+ return;
52
+ const elements = get(this.manager.elements);
53
+ elements.forEach((e) => e.select(e == element));
54
+ this.selectedElement.set(element);
55
+ this.updateSelectionNodes();
56
+ }
57
+ updateSelectionNodes() {
58
+ const nodes = get(this.selectedElement)?.getSelectionNodes() ?? [];
59
+ if (!this.selectionNodes)
60
+ this.selectionNodes = this.manager.map.getSource('selection_nodes');
61
+ this.selectionNodes?.setData({
62
+ type: 'FeatureCollection',
63
+ features: nodes.map((n) => ({
64
+ type: 'Feature',
65
+ properties: { index: n.index, opacity: n.transparent ? 0.3 : 1 },
66
+ geometry: { type: 'Point', coordinates: n.coordinates }
67
+ }))
68
+ });
69
+ }
70
+ }
@@ -11,12 +11,11 @@ for (let i = 0; i < BASE64_CHARS.length; i++) {
11
11
  ];
12
12
  }
13
13
  export const CHAR_VALUE2CODE = [
14
- 32, 101, 116, 97, 110, 105, 111, 115, 114, 108, 100, 104, 99, 117, 109, 112, 102, 103, 46, 121,
15
- 98, 119, 44, 118, 48, 107, 49, 83, 84, 67, 50, 56, 53, 65, 57, 120, 51, 73, 45, 54, 52, 55, 77,
16
- 66, 34, 39, 80, 69, 78, 70, 82, 68, 85, 113, 76, 71, 74, 72, 79, 87, 106, 122, 47, 60, 62, 75, 41,
17
- 40, 86, 89, 58, 81, 90, 88, 59, 63, 94, 38, 43, 91, 93, 36, 33, 42, 61, 126, 95, 123, 64, 0, 1, 2,
18
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
19
- 29, 30, 31, 35, 37, 92, 96, 124, 125, 127
14
+ 32, 101, 116, 97, 110, 105, 111, 115, 114, 108, 100, 104, 99, 117, 109, 112, 102, 103, 46, 121, 98, 119, 44, 118, 48,
15
+ 107, 49, 83, 84, 67, 50, 56, 53, 65, 57, 120, 51, 73, 45, 54, 52, 55, 77, 66, 34, 39, 80, 69, 78, 70, 82, 68, 85, 113,
16
+ 76, 71, 74, 72, 79, 87, 106, 122, 47, 60, 62, 75, 41, 40, 86, 89, 58, 81, 90, 88, 59, 63, 94, 38, 43, 91, 93, 36, 33,
17
+ 42, 61, 126, 95, 123, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
18
+ 25, 26, 27, 28, 29, 30, 31, 35, 37, 92, 96, 124, 125, 127
20
19
  ];
21
20
  export const CHAR_CODE2VALUE = [];
22
21
  CHAR_VALUE2CODE.forEach((c, v) => (CHAR_CODE2VALUE[c] = v));