@versatiles/svelte 1.1.2 → 2.0.1

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 (41) hide show
  1. package/dist/components/BasicMap/BasicMap.svelte +4 -4
  2. package/dist/components/BasicMap/BasicMap.svelte.d.ts +2 -2
  3. package/dist/components/MapEditor/MapEditor.svelte +16 -3
  4. package/dist/components/MapEditor/components/Editor.svelte +56 -40
  5. package/dist/components/MapEditor/components/Editor.svelte.d.ts +1 -1
  6. package/dist/components/MapEditor/components/EditorFill.svelte +42 -12
  7. package/dist/components/MapEditor/components/EditorStroke.svelte +43 -13
  8. package/dist/components/MapEditor/components/EditorSymbol.svelte +105 -34
  9. package/dist/components/MapEditor/components/InputRow.svelte +34 -0
  10. package/dist/components/MapEditor/components/InputRow.svelte.d.ts +9 -0
  11. package/dist/components/MapEditor/components/Sidebar.svelte +119 -109
  12. package/dist/components/MapEditor/components/SidebarPanel.svelte +101 -0
  13. package/dist/components/MapEditor/components/SidebarPanel.svelte.d.ts +10 -0
  14. package/dist/components/MapEditor/components/SymbolSelector.svelte +7 -15
  15. package/dist/components/MapEditor/lib/element/abstract.d.ts +4 -4
  16. package/dist/components/MapEditor/lib/element/abstract.js +2 -2
  17. package/dist/components/MapEditor/lib/element/line.d.ts +3 -4
  18. package/dist/components/MapEditor/lib/element/line.js +0 -1
  19. package/dist/components/MapEditor/lib/element/marker.d.ts +4 -4
  20. package/dist/components/MapEditor/lib/element/polygon.d.ts +3 -3
  21. package/dist/components/MapEditor/lib/geometry_manager.d.ts +20 -10
  22. package/dist/components/MapEditor/lib/geometry_manager.js +42 -52
  23. package/dist/components/MapEditor/lib/map_layer/abstract.d.ts +2 -2
  24. package/dist/components/MapEditor/lib/map_layer/fill.d.ts +4 -3
  25. package/dist/components/MapEditor/lib/map_layer/fill.js +9 -17
  26. package/dist/components/MapEditor/lib/map_layer/line.d.ts +4 -3
  27. package/dist/components/MapEditor/lib/map_layer/line.js +15 -26
  28. package/dist/components/MapEditor/lib/map_layer/symbol.d.ts +5 -4
  29. package/dist/components/MapEditor/lib/map_layer/symbol.js +28 -46
  30. package/dist/components/MapEditor/lib/state/constants.d.ts +4 -0
  31. package/dist/components/MapEditor/lib/state/constants.js +22 -0
  32. package/dist/components/MapEditor/lib/state/manager.d.ts +17 -0
  33. package/dist/components/MapEditor/lib/state/manager.js +87 -0
  34. package/dist/components/MapEditor/lib/state/reader.d.ts +21 -14
  35. package/dist/components/MapEditor/lib/state/reader.js +259 -142
  36. package/dist/components/MapEditor/lib/state/types.d.ts +27 -12
  37. package/dist/components/MapEditor/lib/state/writer.d.ts +18 -14
  38. package/dist/components/MapEditor/lib/state/writer.js +182 -169
  39. package/dist/components/MapEditor/lib/utils.d.ts +2 -5
  40. package/dist/components/MapEditor/lib/utils.js +0 -19
  41. package/package.json +19 -19
@@ -17,8 +17,8 @@
17
17
  styleOptions?: Parameters<typeof getMapStyle>[1];
18
18
  mapOptions?: Partial<MapOptions>;
19
19
  map?: maplibre.Map;
20
- onMapInit?: (map: maplibre.Map) => void;
21
- onMapLoad?: (map: maplibre.Map) => void;
20
+ onMapInit?: (map: maplibre.Map, maplibre: typeof import('maplibre-gl')) => void;
21
+ onMapLoad?: (map: maplibre.Map, maplibre: typeof import('maplibre-gl')) => void;
22
22
  } = $props();
23
23
 
24
24
  let container: HTMLDivElement;
@@ -48,10 +48,10 @@
48
48
  ...mapOptions
49
49
  });
50
50
 
51
- if (onMapInit) onMapInit(map);
51
+ if (onMapInit) onMapInit(map, maplibre);
52
52
 
53
53
  map.on('load', () => {
54
- if (onMapLoad) onMapLoad(map!);
54
+ if (onMapLoad) onMapLoad(map!, maplibre);
55
55
  });
56
56
  }
57
57
  </script>
@@ -7,8 +7,8 @@ type $$ComponentProps = {
7
7
  styleOptions?: Parameters<typeof getMapStyle>[1];
8
8
  mapOptions?: Partial<MapOptions>;
9
9
  map?: maplibre.Map;
10
- onMapInit?: (map: maplibre.Map) => void;
11
- onMapLoad?: (map: maplibre.Map) => void;
10
+ onMapInit?: (map: maplibre.Map, maplibre: typeof import('maplibre-gl')) => void;
11
+ onMapLoad?: (map: maplibre.Map, maplibre: typeof import('maplibre-gl')) => void;
12
12
  };
13
13
  declare const BasicMap: import("svelte").Component<$$ComponentProps, {}, "map">;
14
14
  type BasicMap = ReturnType<typeof BasicMap>;
@@ -15,25 +15,34 @@
15
15
  let map: MaplibreMapType | undefined = $state();
16
16
  let geometryManager: GeometryManager | undefined = $state();
17
17
 
18
- function onMapInit(_map: MaplibreMapType) {
18
+ function onMapInit(_map: MaplibreMapType, maplibre: typeof import('maplibre-gl')) {
19
19
  map = _map;
20
+ map.addControl(new maplibre.AttributionControl({ compact: true }), 'bottom-left');
21
+
20
22
  map.on('load', async () => {
21
23
  const { GeometryManager } = await import('./lib/geometry_manager.js');
22
24
  geometryManager = new GeometryManager(map!);
25
+ const hash = location.hash.slice(1);
26
+ if (hash) geometryManager.state.setHash(hash);
27
+ addEventListener('hashchange', () => geometryManager!.state.setHash(location.hash.slice(1)));
23
28
  });
24
29
  }
25
30
  </script>
26
31
 
27
32
  <div class="page">
28
33
  <div class="container">
29
- <BasicMap {onMapInit} styleOptions={{ disableDarkMode: true }}></BasicMap>
34
+ <BasicMap
35
+ {onMapInit}
36
+ styleOptions={{ disableDarkMode: true }}
37
+ mapOptions={{ attributionControl: false }}
38
+ ></BasicMap>
30
39
  </div>
31
40
  {#if showSidebar && geometryManager}
32
41
  <Sidebar {geometryManager} width={200} />
33
42
 
34
43
  <style>
35
44
  .page .container {
36
- width: calc(100% - 200px);
45
+ width: 100%;
37
46
  position: absolute;
38
47
  top: 0;
39
48
  left: 0;
@@ -50,4 +59,8 @@
50
59
  position: relative;
51
60
  min-height: 6em;
52
61
  }
62
+ :global(.maplibregl-ctrl-attrib) {
63
+ display: flex;
64
+ align-items: center;
65
+ }
53
66
  </style>
@@ -6,49 +6,65 @@
6
6
  import { LineElement } from '../lib/element/line.js';
7
7
  import { MarkerElement } from '../lib/element/marker.js';
8
8
  import { PolygonElement } from '../lib/element/polygon.js';
9
+ import InputRow from './InputRow.svelte';
10
+ import SidebarPanel from './SidebarPanel.svelte';
11
+ import { writable } from 'svelte/store';
9
12
 
10
- const { element }: { element: AbstractElement } = $props();
13
+ const { element }: { element: AbstractElement | undefined } = $props();
11
14
 
12
- let strokeVisible = $state(false);
13
-
14
- if (element instanceof PolygonElement) {
15
- element.strokeLayer.visible.subscribe((value) => (strokeVisible = value));
16
- }
15
+ const noElement = $derived(!element);
16
+ const strokeVisible = $derived.by(() => {
17
+ if (element instanceof PolygonElement) return element.strokeLayer.visible;
18
+ return writable(false);
19
+ });
17
20
  </script>
18
21
 
19
- {#if element instanceof MarkerElement}
20
- <h2>Marker</h2>
21
- <EditorSymbol layer={element.layer} />
22
- {/if}
23
- {#if element instanceof LineElement}
24
- <h2>Line Stroke</h2>
25
- <EditorStroke layer={element.layer} />
26
- {/if}
27
- {#if element instanceof PolygonElement}
28
- <h2>Polygon Fill</h2>
29
- <EditorFill layer={element.fillLayer} />
30
- <h2>Polygon Stroke</h2>
22
+ {#key element}
23
+ <SidebarPanel title="Style" disabled={noElement}>
24
+ <div class="style-editor">
25
+ {#if element instanceof MarkerElement}
26
+ <EditorSymbol layer={element.layer} />
27
+ {/if}
28
+ {#if element instanceof LineElement}
29
+ <EditorStroke layer={element.layer} />
30
+ {/if}
31
+ {#if element instanceof PolygonElement}
32
+ <EditorFill layer={element.fillLayer} />
33
+ <hr />
31
34
 
32
- <div class="row-input">
33
- <label for="showStroke">Outline:</label>
34
- <input
35
- id="showStroke"
36
- type="checkbox"
37
- bind:checked={
38
- () => strokeVisible, (v) => (element as PolygonElement).strokeLayer.visible.set(v)
39
- }
40
- />
41
- </div>
35
+ <InputRow id="showStroke" label="Draw Outline">
36
+ <input
37
+ id="showStroke"
38
+ type="checkbox"
39
+ bind:checked={
40
+ () => $strokeVisible,
41
+ (visible) => {
42
+ $strokeVisible = visible;
43
+ element.manager.state.log();
44
+ }
45
+ }
46
+ />
47
+ </InputRow>
42
48
 
43
- {#if strokeVisible}
44
- <EditorStroke layer={element.strokeLayer} />
45
- {/if}
46
- {/if}
47
- {#if element instanceof PolygonElement || element instanceof LineElement}
48
- <h2>Shape</h2>
49
- <p>
50
- Drag points to move.<br />Drag a midpoint to add.<br />Shift-click to delete a point.
51
- </p>
52
- {/if}
53
- <h2>Actions</h2>
54
- <input type="button" value="Delete" onclick={() => element!.delete()} />
49
+ {#if $strokeVisible}
50
+ <EditorStroke layer={element.strokeLayer} />
51
+ {/if}
52
+ {/if}
53
+ {#if element instanceof PolygonElement || element instanceof LineElement}
54
+ <hr />
55
+ <p>
56
+ Drag points to move.<br />Drag a midpoint to add.<br />Shift-click to delete a point.
57
+ </p>
58
+ {/if}
59
+ </div>
60
+ </SidebarPanel>
61
+ {/key}
62
+
63
+ <style>
64
+ .style-editor {
65
+ :global(p) {
66
+ opacity: 0.5;
67
+ margin: 0.5em 0 1em;
68
+ }
69
+ }
70
+ </style>
@@ -1,6 +1,6 @@
1
1
  import type { AbstractElement } from '../lib/element/abstract.js';
2
2
  type $$ComponentProps = {
3
- element: AbstractElement;
3
+ element: AbstractElement | undefined;
4
4
  };
5
5
  declare const Editor: import("svelte").Component<$$ComponentProps, {}, "">;
6
6
  type Editor = ReturnType<typeof Editor>;
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { fillPatterns, type MapLayerFill } from '../lib/map_layer/fill.js';
3
+ import InputRow from './InputRow.svelte';
3
4
 
4
5
  const { layer }: { layer: MapLayerFill } = $props();
5
6
 
@@ -8,21 +9,50 @@
8
9
  let opacity = $state(layer.opacity);
9
10
  </script>
10
11
 
11
- <div class="row-input">
12
- <label for="color">Color:</label>
13
- <input id="color" type="color" bind:value={$color} />
14
- </div>
12
+ <InputRow label="Color" id="color">
13
+ <input
14
+ id="color"
15
+ type="color"
16
+ bind:value={
17
+ () => $color,
18
+ (v) => {
19
+ $color = v;
20
+ layer.manager.state.log();
21
+ }
22
+ }
23
+ />
24
+ </InputRow>
15
25
 
16
- <div class="row-input">
17
- <label for="pattern">Pattern:</label>
18
- <select id="pattern" bind:value={$pattern}>
26
+ <InputRow label="Pattern" id="pattern">
27
+ <select
28
+ id="pattern"
29
+ bind:value={
30
+ () => $pattern,
31
+ (v) => {
32
+ $pattern = v;
33
+ layer.manager.state.log();
34
+ }
35
+ }
36
+ >
19
37
  {#each fillPatterns as [index, fill] (index)}
20
38
  <option value={index}>{fill.name}</option>
21
39
  {/each}
22
40
  </select>
23
- </div>
41
+ </InputRow>
24
42
 
25
- <div class="row-input">
26
- <label for="opacity">Opacity:</label>
27
- <input id="opacity" type="range" min="0" max="1" step="0.02" bind:value={$opacity} />
28
- </div>
43
+ <InputRow label="Opacity" id="opacity">
44
+ <input
45
+ id="opacity"
46
+ type="range"
47
+ min="0"
48
+ max="1"
49
+ step="0.02"
50
+ bind:value={
51
+ () => $opacity,
52
+ (v) => {
53
+ $opacity = v;
54
+ layer.manager.state.log();
55
+ }
56
+ }
57
+ />
58
+ </InputRow>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { dashArrays, MapLayerLine } from '../lib/map_layer/line.js';
3
+ import InputRow from './InputRow.svelte';
3
4
 
4
5
  const { layer }: { layer: MapLayerLine } = $props();
5
6
 
@@ -8,21 +9,50 @@
8
9
  let dashed = $state(layer.dashed);
9
10
  </script>
10
11
 
11
- <div class="row-input">
12
- <label for="dashed">Dashed:</label>
13
- <select id="dashed" bind:value={$dashed}>
12
+ <InputRow id="color" label="Color">
13
+ <input
14
+ id="color"
15
+ type="color"
16
+ bind:value={
17
+ () => $color,
18
+ (v) => {
19
+ $color = v;
20
+ layer.manager.state.log();
21
+ }
22
+ }
23
+ />
24
+ </InputRow>
25
+
26
+ <InputRow id="dashed" label="Dashed">
27
+ <select
28
+ id="dashed"
29
+ bind:value={
30
+ () => $dashed,
31
+ (v) => {
32
+ $dashed = v;
33
+ layer.manager.state.log();
34
+ }
35
+ }
36
+ >
14
37
  {#each dashArrays as [index, dash] (index)}
15
38
  <option value={index}>{dash.name}</option>
16
39
  {/each}
17
40
  </select>
18
- </div>
19
-
20
- <div class="row-input">
21
- <label for="color">Color:</label>
22
- <input id="color" type="color" bind:value={$color} />
23
- </div>
41
+ </InputRow>
24
42
 
25
- <div class="row-input">
26
- <label for="width">Width:</label>
27
- <input id="width" type="range" min="0.5" max="5" step="0.5" bind:value={$width} />
28
- </div>
43
+ <InputRow id="width" label="Width">
44
+ <input
45
+ id="width"
46
+ type="range"
47
+ min="0.5"
48
+ max="5"
49
+ step="0.5"
50
+ bind:value={
51
+ () => $width,
52
+ (v) => {
53
+ $width = v;
54
+ layer.manager.state.log();
55
+ }
56
+ }
57
+ />
58
+ </InputRow>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { labelPositions, MapLayerSymbol } from '../lib/map_layer/symbol.js';
3
+ import InputRow from './InputRow.svelte';
3
4
  import SymbolSelector from './SymbolSelector.svelte';
4
5
 
5
6
  const { layer }: { layer: MapLayerSymbol } = $props();
@@ -13,41 +14,111 @@
13
14
  let size = $state(layer.size);
14
15
  </script>
15
16
 
16
- <div class="row-input">
17
- <div class="label">Symbol:</div>
18
- <SymbolSelector bind:symbolIndex={$symbolIndex} symbolLibrary={layer.manager.symbolLibrary} />
19
- </div>
20
-
21
- <div class="row-input">
22
- <label for="color">Color:</label>
23
- <input id="color" type="color" bind:value={$color} />
24
- </div>
25
-
26
- <div class="row-input">
27
- <label for="size">Size:</label>
28
- <input id="size" type="range" min="0.5" max="3" step="0.1" bind:value={$size} />
29
- </div>
30
-
31
- <div class="row-input">
32
- <label for="rotate">Rotation:</label>
33
- <input id="rotate" type="range" min="-180" max="180" step="15" bind:value={$rotate} />
34
- </div>
35
-
36
- <div class="row-input">
37
- <label for="halo">Halo:</label>
38
- <input id="halo" type="range" min="0" max="3" step="0.5" bind:value={$halo} />
39
- </div>
40
-
41
- <div class="row-input">
42
- <label for="label">Label:</label>
43
- <input id="label" type="label" bind:value={$label} />
44
- </div>
45
-
46
- <div class="row-input">
47
- <label for="labelAlign">Align Label:</label>
48
- <select id="labelAlign" bind:value={$labelAlign}>
17
+ <InputRow id="label" label="Symbol">
18
+ <SymbolSelector
19
+ bind:symbolIndex={
20
+ () => $symbolIndex,
21
+ (v) => {
22
+ $symbolIndex = v;
23
+ layer.manager.state.log();
24
+ }
25
+ }
26
+ symbolLibrary={layer.manager.symbolLibrary}
27
+ />
28
+ </InputRow>
29
+
30
+ <InputRow id="color" label="Color">
31
+ <input
32
+ id="color"
33
+ type="color"
34
+ bind:value={
35
+ () => $color,
36
+ (v) => {
37
+ $color = v;
38
+ layer.manager.state.log();
39
+ }
40
+ }
41
+ />
42
+ </InputRow>
43
+
44
+ <InputRow id="size" label="Size">
45
+ <input
46
+ id="size"
47
+ type="range"
48
+ min="0.5"
49
+ max="3"
50
+ step="0.1"
51
+ bind:value={
52
+ () => $size,
53
+ (v) => {
54
+ $size = v;
55
+ layer.manager.state.log();
56
+ }
57
+ }
58
+ />
59
+ </InputRow>
60
+
61
+ <InputRow id="rotate" label="Rotation">
62
+ <input
63
+ id="rotate"
64
+ type="range"
65
+ min="-180"
66
+ max="180"
67
+ step="15"
68
+ bind:value={
69
+ () => $rotate,
70
+ (v) => {
71
+ $rotate = v;
72
+ layer.manager.state.log();
73
+ }
74
+ }
75
+ />
76
+ </InputRow>
77
+
78
+ <InputRow id="halo" label="Halo">
79
+ <input
80
+ id="halo"
81
+ type="range"
82
+ min="0"
83
+ max="3"
84
+ step="0.5"
85
+ bind:value={
86
+ () => $halo,
87
+ (v) => {
88
+ $halo = v;
89
+ layer.manager.state.log();
90
+ }
91
+ }
92
+ />
93
+ </InputRow>
94
+
95
+ <InputRow id="label" label="Label">
96
+ <input
97
+ id="label"
98
+ type="label"
99
+ bind:value={
100
+ () => $label,
101
+ (v) => {
102
+ $label = v;
103
+ layer.manager.state.log();
104
+ }
105
+ }
106
+ />
107
+ </InputRow>
108
+
109
+ <InputRow id="labelAlign" label="Align Label">
110
+ <select
111
+ id="labelAlign"
112
+ bind:value={
113
+ () => $labelAlign,
114
+ (v) => {
115
+ $labelAlign = v;
116
+ layer.manager.state.log();
117
+ }
118
+ }
119
+ >
49
120
  {#each labelPositions as { index, name } (index)}
50
121
  <option value={index}>{name}</option>
51
122
  {/each}
52
123
  </select>
53
- </div>
124
+ </InputRow>
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ const { children, label, id }: { children: Snippet; label: string; id: string } = $props();
5
+ </script>
6
+
7
+ <div class="row">
8
+ <label for={id}>{label}</label>
9
+ {@render children()}
10
+ </div>
11
+
12
+ <style>
13
+ .row {
14
+ margin: var(--gap) 0 var(--gap);
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ color: var(--fg-color);
19
+ & > :global(label) {
20
+ flex-grow: 0;
21
+ opacity: 0.5;
22
+ }
23
+ & > :global(button),
24
+ & > :global(input),
25
+ & > :global(select) {
26
+ box-sizing: border-box;
27
+ width: 60%;
28
+ flex-grow: 0;
29
+ }
30
+ & > :global(input[type='checkbox']) {
31
+ width: auto;
32
+ }
33
+ }
34
+ </style>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ children: Snippet;
4
+ label: string;
5
+ id: string;
6
+ };
7
+ declare const InputRow: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type InputRow = ReturnType<typeof InputRow>;
9
+ export default InputRow;