@versatiles/svelte 1.1.1 → 1.1.2

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 (25) hide show
  1. package/dist/components/BBoxMap/AutoComplete.svelte +0 -1
  2. package/dist/components/BBoxMap/BBoxMap.svelte +1 -2
  3. package/dist/{utils/draw → components/BBoxMap/lib}/bbox.d.ts +1 -2
  4. package/dist/components/BasicMap/BasicMap.svelte +5 -7
  5. package/dist/components/BasicMap/BasicMap.svelte.d.ts +5 -4
  6. package/dist/components/LocatorMap/LocatorMap.svelte +0 -2
  7. package/dist/components/MapEditor/components/Editor.svelte +1 -0
  8. package/dist/components/MapEditor/components/EditorSymbol.svelte +11 -1
  9. package/dist/components/MapEditor/components/Sidebar.svelte +8 -10
  10. package/dist/components/MapEditor/lib/geometry_manager.js +2 -0
  11. package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +1 -1
  12. package/dist/components/MapEditor/lib/map_layer/abstract.js +27 -12
  13. package/dist/components/MapEditor/lib/map_layer/symbol.d.ts +17 -7
  14. package/dist/components/MapEditor/lib/map_layer/symbol.js +73 -14
  15. package/dist/components/MapEditor/lib/state/reader.js +4 -1
  16. package/dist/components/MapEditor/lib/state/types.d.ts +1 -0
  17. package/dist/components/MapEditor/lib/state/writer.js +15 -1
  18. package/package.json +13 -12
  19. package/dist/components/MapEditor/lib/__mocks__/cursor.d.ts +0 -5
  20. package/dist/components/MapEditor/lib/__mocks__/cursor.js +0 -6
  21. package/dist/components/MapEditor/lib/__mocks__/geometry_manager.d.ts +0 -22
  22. package/dist/components/MapEditor/lib/__mocks__/geometry_manager.js +0 -21
  23. package/dist/components/MapEditor/lib/__mocks__/map.d.ts +0 -36
  24. package/dist/components/MapEditor/lib/__mocks__/map.js +0 -26
  25. /package/dist/{utils/draw → components/BBoxMap/lib}/bbox.js +0 -0
@@ -1,4 +1,3 @@
1
- <!-- AutoComplete.svelte -->
2
1
  <script lang="ts" generics="T">
3
2
  import { isDarkMode } from '../../utils/map_style.js';
4
3
  /* eslint svelte/no-at-html-tags: off */
@@ -1,4 +1,3 @@
1
- <!-- BBoxMap.svelte -->
2
1
  <script lang="ts">
3
2
  import type { CameraOptions, Map as MaplibreMapType } from 'maplibre-gl';
4
3
  import AutoComplete from './AutoComplete.svelte';
@@ -7,7 +6,7 @@
7
6
  import { isDarkMode } from '../../utils/map_style.js';
8
7
  import type { BBox } from 'geojson';
9
8
  import { loadBBoxes } from './BBoxMap.js';
10
- import { BBoxDrawer } from '../../utils/draw/bbox.js';
9
+ import { BBoxDrawer } from './lib/bbox.js';
11
10
 
12
11
  let { selectedBBox = $bindable() }: { selectedBBox?: BBox } = $props();
13
12
  const startTime = Date.now();
@@ -1,7 +1,7 @@
1
1
  import type geojson from 'geojson';
2
2
  import { type Writable } from 'svelte/store';
3
3
  import maplibregl from 'maplibre-gl';
4
- type DragPoint = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | false;
4
+ export type DragPoint = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw' | false;
5
5
  export declare const DragPointMap: Map<DragPoint, {
6
6
  cursor: string;
7
7
  flipH: DragPoint;
@@ -27,4 +27,3 @@ export declare class BBoxDrawer {
27
27
  private getCursor;
28
28
  private doDrag;
29
29
  }
30
- export {};
@@ -1,10 +1,8 @@
1
- <!-- BasicMap.svelte -->
2
1
  <script lang="ts">
3
- import type { Map as MaplibreMapType, MapOptions } from 'maplibre-gl';
4
2
  import 'maplibre-gl/dist/maplibre-gl.css';
5
3
  import { getMapStyle, isDarkMode } from '../../utils/map_style.js';
6
4
  import maplibre from 'maplibre-gl';
7
- const { Map } = maplibre;
5
+ import type { MapOptions } from 'maplibre-gl';
8
6
 
9
7
  // Props
10
8
  let {
@@ -18,9 +16,9 @@
18
16
  style?: string;
19
17
  styleOptions?: Parameters<typeof getMapStyle>[1];
20
18
  mapOptions?: Partial<MapOptions>;
21
- map?: MaplibreMapType;
22
- onMapInit?: (map: MaplibreMapType) => void;
23
- onMapLoad?: (map: MaplibreMapType) => void;
19
+ map?: maplibre.Map;
20
+ onMapInit?: (map: maplibre.Map) => void;
21
+ onMapLoad?: (map: maplibre.Map) => void;
24
22
  } = $props();
25
23
 
26
24
  let container: HTMLDivElement;
@@ -40,7 +38,7 @@
40
38
 
41
39
  const style = getMapStyle(darkMode, styleOptions);
42
40
  style.transition = { duration: 0, delay: 0 };
43
- map = new Map({
41
+ map = new maplibre.Map({
44
42
  container,
45
43
  style,
46
44
  renderWorldCopies: false,
@@ -1,13 +1,14 @@
1
- import type { Map as MaplibreMapType, MapOptions } from 'maplibre-gl';
2
1
  import 'maplibre-gl/dist/maplibre-gl.css';
3
2
  import { getMapStyle } from '../../utils/map_style.js';
3
+ import maplibre from 'maplibre-gl';
4
+ import type { MapOptions } from 'maplibre-gl';
4
5
  type $$ComponentProps = {
5
6
  style?: string;
6
7
  styleOptions?: Parameters<typeof getMapStyle>[1];
7
8
  mapOptions?: Partial<MapOptions>;
8
- map?: MaplibreMapType;
9
- onMapInit?: (map: MaplibreMapType) => void;
10
- onMapLoad?: (map: MaplibreMapType) => void;
9
+ map?: maplibre.Map;
10
+ onMapInit?: (map: maplibre.Map) => void;
11
+ onMapLoad?: (map: maplibre.Map) => void;
11
12
  };
12
13
  declare const BasicMap: import("svelte").Component<$$ComponentProps, {}, "map">;
13
14
  type BasicMap = ReturnType<typeof BasicMap>;
@@ -1,4 +1,3 @@
1
- <!-- LocatorMap.svelte -->
2
1
  <script lang="ts">
3
2
  import type { Map as MaplibreMapType, GeoJSONSource } from 'maplibre-gl';
4
3
  import BasicMap from '../BasicMap/BasicMap.svelte';
@@ -10,7 +9,6 @@
10
9
  let coordinates: [number, number] = [0, 0];
11
10
  const initialHash = parseHash();
12
11
  if (initialHash) {
13
- console.log('initialHash', initialHash);
14
12
  coordinates = [initialHash[1], initialHash[2]];
15
13
  map.setZoom(initialHash[0]);
16
14
  map.setCenter(coordinates);
@@ -8,6 +8,7 @@
8
8
  import { PolygonElement } from '../lib/element/polygon.js';
9
9
 
10
10
  const { element }: { element: AbstractElement } = $props();
11
+
11
12
  let strokeVisible = $state(false);
12
13
 
13
14
  if (element instanceof PolygonElement) {
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { MapLayerSymbol } from '../lib/map_layer/symbol.js';
2
+ import { labelPositions, MapLayerSymbol } from '../lib/map_layer/symbol.js';
3
3
  import SymbolSelector from './SymbolSelector.svelte';
4
4
 
5
5
  const { layer }: { layer: MapLayerSymbol } = $props();
@@ -9,6 +9,7 @@
9
9
  let rotate = $state(layer.rotate);
10
10
  let halo = $state(layer.halo);
11
11
  let label = $state(layer.label);
12
+ let labelAlign = $state(layer.labelAlign);
12
13
  let size = $state(layer.size);
13
14
  </script>
14
15
 
@@ -41,3 +42,12 @@
41
42
  <label for="label">Label:</label>
42
43
  <input id="label" type="label" bind:value={$label} />
43
44
  </div>
45
+
46
+ <div class="row-input">
47
+ <label for="labelAlign">Align Label:</label>
48
+ <select id="labelAlign" bind:value={$labelAlign}>
49
+ {#each labelPositions as { index, name } (index)}
50
+ <option value={index}>{name}</option>
51
+ {/each}
52
+ </select>
53
+ </div>
@@ -1,14 +1,10 @@
1
1
  <script lang="ts">
2
- import type { AbstractElement } from '../lib/element/abstract.js';
3
2
  import Editor from './Editor.svelte';
4
3
  import type { GeometryManager } from '../lib/geometry_manager.js';
5
4
 
6
5
  const { geometryManager, width }: { geometryManager: GeometryManager; width: number } = $props();
7
6
 
8
- let activeElement: AbstractElement | undefined = $state(undefined);
9
- $effect(() => geometryManager.selectElement(activeElement));
10
-
11
- geometryManager.selectedElement.subscribe((value) => (activeElement = value));
7
+ let activeElement = geometryManager.selectedElement;
12
8
 
13
9
  function importGeoJSON() {
14
10
  const input = document.createElement('input');
@@ -60,22 +56,24 @@
60
56
  <input
61
57
  type="button"
62
58
  value="Marker"
63
- onclick={() => (activeElement = geometryManager.addNewMarker())}
59
+ onclick={() => activeElement.set(geometryManager.addNewMarker())}
64
60
  />
65
61
  <input
66
62
  type="button"
67
63
  value="Line"
68
- onclick={() => (activeElement = geometryManager.addNewLine())}
64
+ onclick={() => activeElement.set(geometryManager.addNewLine())}
69
65
  />
70
66
  <input
71
67
  type="button"
72
68
  value="Polygon"
73
- onclick={() => (activeElement = geometryManager.addNewPolygon())}
69
+ onclick={() => activeElement.set(geometryManager.addNewPolygon())}
74
70
  />
75
71
  </div>
76
- {#if activeElement != null}
72
+ {#if $activeElement != null}
77
73
  <hr />
78
- <Editor element={activeElement} />
74
+ {#key $activeElement}
75
+ <Editor element={$activeElement} />
76
+ {/key}
79
77
  {/if}
80
78
  </div>
81
79
  <div class="footer">
@@ -85,6 +85,8 @@ export class GeometryManager {
85
85
  this.loadState(hash);
86
86
  }
87
87
  selectElement(element) {
88
+ if (element == get(this.selectedElement))
89
+ return;
88
90
  const elements = get(this.elements);
89
91
  elements.forEach((e) => e.select(e == element));
90
92
  this.selectedElement.set(element);
@@ -20,7 +20,7 @@ export declare abstract class MapLayer<T extends LayerSpec> {
20
20
  private addEvents;
21
21
  setPaint(paint: T['paint']): void;
22
22
  updatePaint<K extends keyof T['paint'], V extends T['paint'][K]>(key: K, value: V): void;
23
- setLayout(layout: T['layout']): void;
23
+ updateLayout(obj: T['layout']): void;
24
24
  updateLayout<K extends keyof T['layout'], V extends T['layout'][K]>(key: K, value: V): void;
25
25
  destroy(): void;
26
26
  abstract getState(): StateObject | undefined;
@@ -13,10 +13,20 @@ export class MapLayer {
13
13
  this.id = id;
14
14
  }
15
15
  addLayer(source, type, layout, paint) {
16
+ layout = cloneClean(layout);
17
+ paint = cloneClean(paint);
16
18
  this.layout = layout;
17
19
  this.paint = paint;
18
20
  this.map.addLayer({ id: this.id, source, type, layout, paint }, 'selection_nodes');
19
21
  this.addEvents();
22
+ function cloneClean(obj) {
23
+ const clone = { ...obj };
24
+ for (const key in clone) {
25
+ if (clone[key] == null)
26
+ delete clone[key];
27
+ }
28
+ return clone;
29
+ }
20
30
  }
21
31
  on(event, handler) {
22
32
  if (!this.eventHandlers.has(event))
@@ -75,18 +85,23 @@ export class MapLayer {
75
85
  this.map.setPaintProperty(this.id, key, value);
76
86
  this.paint[key] = value;
77
87
  }
78
- setLayout(layout) {
79
- if (layout === undefined)
80
- return;
81
- const keys = new Set(Object.keys(layout).concat(Object.keys(this.layout)));
82
- for (const key of keys.values())
83
- this.updateLayout(key, layout[key]);
84
- }
85
- updateLayout(key, value) {
86
- if (this.layout[key] == value)
87
- return;
88
- this.map.setLayoutProperty(this.id, key, value);
89
- this.layout[key] = value;
88
+ updateLayout(arg1, arg2) {
89
+ if (typeof arg1 === 'string') {
90
+ if (this.layout[arg1] == arg2)
91
+ return;
92
+ this.map.setLayoutProperty(this.id, arg1, arg2);
93
+ if (arg2 == null) {
94
+ delete this.layout[arg1];
95
+ }
96
+ else {
97
+ this.layout[arg1] = arg2;
98
+ }
99
+ }
100
+ else if (typeof arg1 === 'object') {
101
+ for (const [key, value] of Object.entries(arg1)) {
102
+ this.updateLayout(key, value);
103
+ }
104
+ }
90
105
  }
91
106
  destroy() {
92
107
  this.map.removeLayer(this.id);
@@ -1,19 +1,29 @@
1
+ import { type Writable } from 'svelte/store';
1
2
  import type { LayerSymbol } from './types.js';
2
3
  import { MapLayer } from './abstract.js';
3
4
  import type { GeometryManager } from '../geometry_manager.js';
4
5
  import type { StateObject } from '../state/types.js';
6
+ interface LabelAlign {
7
+ index: 0 | 1 | 2 | 3 | 4;
8
+ name: string;
9
+ anchor?: 'center' | 'left' | 'right' | 'bottom' | 'top';
10
+ }
11
+ export declare const labelPositions: LabelAlign[];
5
12
  export declare class MapLayerSymbol extends MapLayer<LayerSymbol> {
6
- color: import("svelte/store").Writable<string>;
7
- halo: import("svelte/store").Writable<number>;
8
- rotate: import("svelte/store").Writable<number>;
9
- size: import("svelte/store").Writable<number>;
10
- symbolIndex: import("svelte/store").Writable<number>;
11
- label: import("svelte/store").Writable<string>;
12
- haloWidth: import("svelte/store").Readable<number>;
13
+ color: Writable<string>;
14
+ halo: Writable<number>;
15
+ rotate: Writable<number>;
16
+ size: Writable<number>;
17
+ symbolIndex: Writable<number>;
18
+ label: Writable<string>;
19
+ labelAlign: Writable<0 | 2 | 1 | 4 | 3>;
13
20
  symbolInfo: import("svelte/store").Readable<import("../symbols.js").SymbolInfo>;
21
+ textAnchor: import("svelte/store").Readable<"center" | "top" | "bottom" | "right" | "left" | undefined>;
22
+ textVariableAnchor: import("svelte/store").Readable<("center" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "top" | "bottom" | "right" | "left")[] | undefined>;
14
23
  constructor(manager: GeometryManager, id: string, source: string);
15
24
  getState(): StateObject | undefined;
16
25
  setState(state: StateObject): void;
17
26
  getGeoJSONProperties(): GeoJSON.GeoJsonProperties;
18
27
  setGeoJSONProperties(properties: GeoJSON.GeoJsonProperties): void;
19
28
  }
29
+ export {};
@@ -3,13 +3,21 @@ import { MapLayer } from './abstract.js';
3
3
  import { Color } from '@versatiles/style';
4
4
  import { getSymbol, getSymbolIndexByName } from '../symbols.js';
5
5
  import { removeDefaultFields } from '../utils.js';
6
+ export const labelPositions = [
7
+ { index: 0, name: 'auto' },
8
+ { index: 1, name: 'right', anchor: 'left' },
9
+ { index: 2, name: 'left', anchor: 'right' },
10
+ { index: 3, name: 'top', anchor: 'bottom' },
11
+ { index: 4, name: 'bottom', anchor: 'top' }
12
+ ];
6
13
  const defaultStyle = {
7
14
  color: '#ff0000',
8
15
  rotate: 0,
9
16
  size: 1,
10
17
  halo: 1,
11
18
  pattern: 38,
12
- label: ''
19
+ label: '',
20
+ align: 0
13
21
  };
14
22
  export class MapLayerSymbol extends MapLayer {
15
23
  color = writable(defaultStyle.color);
@@ -18,22 +26,34 @@ export class MapLayerSymbol extends MapLayer {
18
26
  size = writable(defaultStyle.size);
19
27
  symbolIndex = writable(defaultStyle.pattern);
20
28
  label = writable(defaultStyle.label);
21
- haloWidth = derived([this.halo, this.size], ([halo, size]) => halo * size);
29
+ labelAlign = writable(defaultStyle.align);
22
30
  symbolInfo = derived(this.symbolIndex, (index) => getSymbol(index));
31
+ textAnchor = derived(this.labelAlign, (index) => {
32
+ return lookupLabelAlign(index).anchor;
33
+ });
34
+ textVariableAnchor = derived([this.labelAlign, this.symbolInfo], ([index, symbol]) => {
35
+ if (index !== 0)
36
+ return undefined;
37
+ if (symbol.image == null) {
38
+ return ['center', 'left', 'right', 'top', 'bottom'];
39
+ }
40
+ return ['left', 'right', 'top', 'bottom'];
41
+ });
23
42
  constructor(manager, id, source) {
24
43
  super(manager, id);
25
44
  this.addLayer(source, 'symbol', {
26
45
  'icon-image': get(this.symbolInfo).image,
27
46
  'icon-offset': get(this.symbolInfo).offset,
28
- 'icon-overlap': 'always',
47
+ 'icon-allow-overlap': true,
29
48
  'icon-rotate': defaultStyle.rotate,
30
49
  'icon-size': defaultStyle.size,
31
50
  'text-field': defaultStyle.label,
32
51
  'text-font': ['noto_sans_regular'],
33
52
  'text-justify': 'left',
34
- 'text-optional': true,
35
- 'text-offset': [0.7, 0.7],
36
- 'text-variable-anchor': ['right', 'left', 'top', 'bottom']
53
+ 'text-overlap': 'always',
54
+ 'text-radial-offset': 0.7,
55
+ 'text-variable-anchor': get(this.textVariableAnchor),
56
+ 'text-anchor': get(this.textAnchor)
37
57
  }, {
38
58
  'icon-color': defaultStyle.color,
39
59
  'icon-halo-blur': 0,
@@ -44,27 +64,45 @@ export class MapLayerSymbol extends MapLayer {
44
64
  'text-halo-color': '#FFFFFF',
45
65
  'text-halo-width': defaultStyle.halo
46
66
  });
47
- this.color.subscribe((v) => this.updatePaint('icon-color', Color.parse(v)));
48
- this.haloWidth.subscribe((v) => {
67
+ this.color.subscribe((v) => {
68
+ this.updatePaint('icon-color', Color.parse(v));
69
+ this.manager.saveState();
70
+ });
71
+ this.halo.subscribe((v) => {
49
72
  this.updatePaint('icon-halo-width', v);
50
73
  this.updatePaint('text-halo-width', v);
74
+ this.manager.saveState();
75
+ });
76
+ this.label.subscribe((v) => {
77
+ this.updateLayout('text-field', v);
78
+ this.manager.saveState();
79
+ });
80
+ this.textAnchor.subscribe((v) => {
81
+ this.updateLayout('text-anchor', v);
82
+ this.manager.saveState();
83
+ });
84
+ this.textVariableAnchor.subscribe((v) => {
85
+ this.updateLayout('text-variable-anchor', v);
86
+ this.manager.saveState();
87
+ });
88
+ this.rotate.subscribe((v) => {
89
+ this.updateLayout('icon-rotate', v);
90
+ this.manager.saveState();
51
91
  });
52
- this.label.subscribe((v) => this.updateLayout('text-field', v));
53
- this.rotate.subscribe((v) => this.updateLayout('icon-rotate', v));
54
92
  this.size.subscribe((v) => {
55
93
  this.updateLayout('icon-size', v);
56
94
  this.updateLayout('text-size', v * 16);
95
+ this.manager.saveState();
57
96
  });
58
97
  this.symbolInfo.subscribe((v) => {
59
98
  if (v.image == null) {
60
99
  this.updateLayout('icon-image', undefined);
61
- this.updateLayout('text-variable-anchor', ['center']);
62
100
  }
63
101
  else {
64
102
  this.updateLayout('icon-image', v.image);
65
- this.updateLayout('text-variable-anchor', ['right', 'left', 'top', 'bottom']);
66
103
  this.updateLayout('icon-offset', v.offset);
67
104
  }
105
+ this.manager.saveState();
68
106
  });
69
107
  }
70
108
  getState() {
@@ -74,7 +112,8 @@ export class MapLayerSymbol extends MapLayer {
74
112
  size: get(this.size),
75
113
  halo: get(this.halo),
76
114
  pattern: get(this.symbolIndex),
77
- label: get(this.label)
115
+ label: get(this.label),
116
+ align: get(this.labelAlign)
78
117
  }, defaultStyle);
79
118
  }
80
119
  setState(state) {
@@ -90,6 +129,8 @@ export class MapLayerSymbol extends MapLayer {
90
129
  this.symbolIndex.set(state.pattern);
91
130
  if (state.label)
92
131
  this.label.set(state.label);
132
+ if (state.align)
133
+ this.labelAlign.set(lookupLabelAlign(state.align).index);
93
134
  }
94
135
  getGeoJSONProperties() {
95
136
  return {
@@ -98,7 +139,8 @@ export class MapLayerSymbol extends MapLayer {
98
139
  'symbol-rotate': get(this.rotate),
99
140
  'symbol-size': get(this.size),
100
141
  'symbol-pattern': get(this.symbolInfo).name,
101
- 'symbol-label': get(this.label)
142
+ 'symbol-label': get(this.label),
143
+ 'symbol-label-align': lookupLabelAlign(this.labelAlign).name
102
144
  };
103
145
  }
104
146
  setGeoJSONProperties(properties) {
@@ -114,6 +156,8 @@ export class MapLayerSymbol extends MapLayer {
114
156
  this.size.set(properties['symbol-size']);
115
157
  if (properties['symbol-label'])
116
158
  this.label.set(properties['symbol-label']);
159
+ if (properties['symbol-label-align'])
160
+ this.labelAlign.set(lookupLabelAlign(properties['symbol-label-align']).index);
117
161
  if (properties['symbol-pattern']) {
118
162
  const index = getSymbolIndexByName(properties['symbol-pattern']);
119
163
  if (index != null)
@@ -121,3 +165,18 @@ export class MapLayerSymbol extends MapLayer {
121
165
  }
122
166
  }
123
167
  }
168
+ function lookupLabelAlign(index) {
169
+ let pos;
170
+ if (typeof index === 'object') {
171
+ index = get(index);
172
+ }
173
+ if (typeof index === 'number') {
174
+ pos = labelPositions.find((p) => p.index === index);
175
+ }
176
+ else if (typeof index === 'string') {
177
+ pos = labelPositions.find((p) => p.name === index);
178
+ }
179
+ if (pos == null)
180
+ return labelPositions[0];
181
+ return pos;
182
+ }
@@ -110,7 +110,7 @@ export class StateReader {
110
110
  state.pattern = this.readUnsignedInteger();
111
111
  break;
112
112
  case 73:
113
- state.rotate = this.readUnsignedInteger();
113
+ state.rotate = this.readSignedInteger();
114
114
  break;
115
115
  case 74:
116
116
  state.size = this.readUnsignedInteger() / 10;
@@ -121,6 +121,9 @@ export class StateReader {
121
121
  case 76:
122
122
  state.zoom = this.readUnsignedInteger() / 20;
123
123
  break;
124
+ case 77:
125
+ state.align = this.readUnsignedInteger();
126
+ break;
124
127
  case 90:
125
128
  state.visible = this.readBoolean();
126
129
  break;
@@ -16,5 +16,6 @@ export interface StateObject {
16
16
  size?: number;
17
17
  width?: number;
18
18
  zoom?: number;
19
+ align?: number;
19
20
  visible?: boolean;
20
21
  }
@@ -66,6 +66,8 @@ export class StateWriter {
66
66
  case 'elements':
67
67
  if (!Array.isArray(value))
68
68
  throw new Error(`Invalid elements: ${value}`);
69
+ if (value.length === 0)
70
+ return;
69
71
  this.writeByte(20);
70
72
  this.writeUnsignedInteger(value.length);
71
73
  value.forEach((element) => this.writeObject(element));
@@ -80,6 +82,8 @@ export class StateWriter {
80
82
  case 'points':
81
83
  if (!Array.isArray(value))
82
84
  throw new Error(`Invalid points: ${value}`);
85
+ if (value.length === 0)
86
+ return;
83
87
  this.writeByte(31);
84
88
  this.writeUnsignedInteger(value.length);
85
89
  this.writeDifferential(value.map((p) => Math.round(p[0] * 1e5)));
@@ -121,7 +125,7 @@ export class StateWriter {
121
125
  writeInteger(72, value);
122
126
  break;
123
127
  case 'rotate':
124
- writeInteger(73, value);
128
+ writeSignedInteger(73, value);
125
129
  break;
126
130
  case 'size':
127
131
  writeInteger(74, value, 10);
@@ -132,6 +136,9 @@ export class StateWriter {
132
136
  case 'zoom':
133
137
  writeInteger(76, value, 20);
134
138
  break;
139
+ case 'align':
140
+ writeInteger(77, value);
141
+ break;
135
142
  case 'visible':
136
143
  if (typeof value !== 'boolean')
137
144
  throw new Error(`Invalid boolean: ${value}`);
@@ -158,6 +165,13 @@ export class StateWriter {
158
165
  me.writeByte(id);
159
166
  me.writeUnsignedInteger(value * factor);
160
167
  }
168
+ function writeSignedInteger(id, obj, factor = 1) {
169
+ if (typeof obj !== 'number')
170
+ throw new Error(`Invalid number: ${obj}`);
171
+ const value = Math.round(obj);
172
+ me.writeByte(id);
173
+ me.writeSignedInteger(value * factor);
174
+ }
161
175
  }
162
176
  writeColor(color) {
163
177
  if (typeof color !== 'string')
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@versatiles/svelte",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "build": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && vite build && npm run package",
7
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
8
- "check": "npm run lint && npm run build && npm run test",
7
+ "check-watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
8
+ "check": "npm run format && npm run lint && npm run build && npm run test",
9
9
  "dev": "vite dev",
10
- "format": "prettier --write .",
10
+ "format": "prettier --write --log-level warn .",
11
11
  "lint": "prettier --check . && eslint --color .",
12
12
  "package": "svelte-kit sync && svelte-package && publint",
13
13
  "prepack": "npm run build",
14
14
  "prepublishOnly": "npm run package",
15
15
  "preview": "vite preview",
16
- "screenshots": "npm run build && npx tsx ./scripts/screenshots.ts && pngquant --nofs --force --ext .png screenshots/*.png && optipng -quiet screenshots/*.png",
16
+ "screenshots": "npx tsx ./scripts/screenshots.ts",
17
17
  "release": "vrt release-npm",
18
- "test:integration": "playwright test",
19
- "test:unit": "vitest run",
20
- "test:coverage": "vitest run --coverage",
21
- "test": "npm run test:unit && npm run test:integration",
18
+ "test-integration": "playwright test",
19
+ "test-unit": "vitest run",
20
+ "test-coverage": "vitest run --coverage",
21
+ "test": "npm run test-unit && npm run test-integration",
22
22
  "upgrade": "vrt deps-upgrade"
23
23
  },
24
24
  "exports": {
@@ -30,18 +30,19 @@
30
30
  "files": [
31
31
  "dist",
32
32
  "!dist/**/*.spec.*",
33
+ "!dist/**/__mocks__/*",
33
34
  "!dist/**/*.test.*",
34
35
  "!dist/BBoxMap/data/*",
35
36
  "!dist/BBoxMap/helpers/*"
36
37
  ],
37
38
  "peerDependencies": {
38
39
  "sass-embedded": "^1.86.0",
39
- "svelte": "^5.0.3"
40
+ "svelte": "^5.23.2"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@playwright/test": "^1.51.1",
43
44
  "@sveltejs/adapter-static": "^3.0.8",
44
- "@sveltejs/kit": "^2.20.0",
45
+ "@sveltejs/kit": "^2.20.1",
45
46
  "@sveltejs/package": "^2.3.10",
46
47
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
47
48
  "@turf/turf": "^7.2.0",
@@ -60,7 +61,7 @@
60
61
  "prettier-plugin-svelte": "^3.3.3",
61
62
  "publint": "^0.3.9",
62
63
  "sass": "^1.86.0",
63
- "svelte": "^5.23.1",
64
+ "svelte": "^5.23.2",
64
65
  "svelte-check": "^4.1.5",
65
66
  "svelte-preprocess": "^6.0.3",
66
67
  "tsx": "^4.19.3",
@@ -1,5 +0,0 @@
1
- export declare class MockCursor {
2
- grab: import("vitest").Mock<(...args: any[]) => any>;
3
- hover: import("vitest").Mock<(...args: any[]) => any>;
4
- precise: import("vitest").Mock<(...args: any[]) => any>;
5
- }
@@ -1,6 +0,0 @@
1
- import { vi } from 'vitest';
2
- export class MockCursor {
3
- grab = vi.fn();
4
- hover = vi.fn();
5
- precise = vi.fn();
6
- }
@@ -1,22 +0,0 @@
1
- import { type Writable } from 'svelte/store';
2
- import type { AbstractElement } from '../element/abstract.js';
3
- import type { StateObject } from '../state/types.js';
4
- import { MockMap } from './map.js';
5
- import { MockCursor } from './cursor.js';
6
- export declare class MockGeometryManager {
7
- readonly elements: Writable<AbstractElement[]>;
8
- readonly activeElement: Writable<AbstractElement | undefined>;
9
- readonly map: MockMap;
10
- readonly cursor: MockCursor;
11
- constructor();
12
- setActiveElement: import("vitest").Mock<(...args: any[]) => any>;
13
- getState: import("vitest").Mock<() => StateObject>;
14
- saveState: import("vitest").Mock<(...args: any[]) => any>;
15
- loadState: import("vitest").Mock<(...args: any[]) => any>;
16
- getElement: import("vitest").Mock<(index: number) => AbstractElement>;
17
- addNewMarker: import("vitest").Mock<() => AbstractElement>;
18
- addNewLine: import("vitest").Mock<() => AbstractElement>;
19
- addNewPolygon: import("vitest").Mock<() => AbstractElement>;
20
- deleteElement: import("vitest").Mock<(...args: any[]) => any>;
21
- drawSelectionNodes: import("vitest").Mock<(...args: any[]) => any>;
22
- }
@@ -1,21 +0,0 @@
1
- import { writable } from 'svelte/store';
2
- import { vi } from 'vitest';
3
- import { MockMap } from './map.js';
4
- import { MockCursor } from './cursor.js';
5
- export class MockGeometryManager {
6
- elements = writable([]);
7
- activeElement = writable(undefined);
8
- map = new MockMap();
9
- cursor = new MockCursor();
10
- constructor() { }
11
- setActiveElement = vi.fn();
12
- getState = vi.fn(() => ({ map: { point: [0, 0], zoom: 10 }, elements: [] }));
13
- saveState = vi.fn();
14
- loadState = vi.fn();
15
- getElement = vi.fn((index) => ({ index }));
16
- addNewMarker = vi.fn(() => ({}));
17
- addNewLine = vi.fn(() => ({}));
18
- addNewPolygon = vi.fn(() => ({}));
19
- deleteElement = vi.fn();
20
- drawSelectionNodes = vi.fn();
21
- }
@@ -1,36 +0,0 @@
1
- export declare class MockMap {
2
- getCanvasContainer: import("vitest").Mock<() => {
3
- style: {
4
- cursor: string;
5
- };
6
- }>;
7
- addSource: import("vitest").Mock<(...args: any[]) => any>;
8
- removeSource: import("vitest").Mock<(...args: any[]) => any>;
9
- getSource: import("vitest").Mock<() => {
10
- setData: import("vitest").Mock<(...args: any[]) => any>;
11
- }>;
12
- addLayer: import("vitest").Mock<(...args: any[]) => any>;
13
- on: import("vitest").Mock<(...args: any[]) => any>;
14
- setCenter: import("vitest").Mock<(...args: any[]) => any>;
15
- setZoom: import("vitest").Mock<(...args: any[]) => any>;
16
- getZoom: import("vitest").Mock<() => number>;
17
- getCenter: import("vitest").Mock<() => {
18
- lng: number;
19
- lat: number;
20
- }>;
21
- queryRenderedFeatures: import("vitest").Mock<() => {
22
- properties: {};
23
- }[]>;
24
- setPaintProperty: import("vitest").Mock<(...args: any[]) => any>;
25
- setLayoutProperty: import("vitest").Mock<(...args: any[]) => any>;
26
- removeLayer: import("vitest").Mock<(...args: any[]) => any>;
27
- hasImage: import("vitest").Mock<(...args: any[]) => any>;
28
- removeImage: import("vitest").Mock<(...args: any[]) => any>;
29
- addImage: import("vitest").Mock<(...args: any[]) => any>;
30
- getBounds: import("vitest").Mock<() => {
31
- getWest: () => -180;
32
- getEast: () => 180;
33
- getSouth: () => -90;
34
- getNorth: () => 90;
35
- }>;
36
- }
@@ -1,26 +0,0 @@
1
- import { vi } from 'vitest';
2
- export class MockMap {
3
- getCanvasContainer = vi.fn(() => ({ style: { cursor: 'default' } }));
4
- addSource = vi.fn();
5
- removeSource = vi.fn();
6
- getSource = vi.fn(() => ({ setData: vi.fn() }));
7
- addLayer = vi.fn();
8
- on = vi.fn();
9
- setCenter = vi.fn();
10
- setZoom = vi.fn();
11
- getZoom = vi.fn(() => 10);
12
- getCenter = vi.fn(() => ({ lng: 0, lat: 0 }));
13
- queryRenderedFeatures = vi.fn(() => [{ properties: {} }]);
14
- setPaintProperty = vi.fn();
15
- setLayoutProperty = vi.fn();
16
- removeLayer = vi.fn();
17
- hasImage = vi.fn();
18
- removeImage = vi.fn();
19
- addImage = vi.fn();
20
- getBounds = vi.fn(() => ({
21
- getWest: () => -180,
22
- getEast: () => 180,
23
- getSouth: () => -90,
24
- getNorth: () => 90
25
- }));
26
- }