ogm-viewer 0.3.0 → 0.4.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 (197) hide show
  1. package/dist/cjs/{index-CVTUnaNg.js → index-mu9UK_Fb.js} +66 -3
  2. package/dist/cjs/{lerc-TQEssgMv.js → lerc-CT61sKYw.js} +7 -7
  3. package/dist/cjs/loader.cjs.js +2 -2
  4. package/dist/cjs/{ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-settings.ogm-sidebar.ogm-viewer-ifPxRNEo.js → ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-DKxSOrMP.js} +13640 -7139
  5. package/dist/cjs/ogm-attributes_9.cjs.entry.js +16 -0
  6. package/dist/cjs/ogm-viewer.cjs.js +2 -2
  7. package/dist/collection/assets/webawesome/styles/color/palettes/base.css +44 -0
  8. package/dist/collection/assets/webawesome/styles/color/palettes/bright.css +145 -0
  9. package/dist/collection/assets/webawesome/styles/color/palettes/default.css +146 -0
  10. package/dist/collection/assets/webawesome/styles/color/palettes/shoelace.css +146 -0
  11. package/dist/collection/assets/webawesome/styles/color/variants/brand.css +162 -0
  12. package/dist/collection/assets/webawesome/styles/color/variants/danger.css +162 -0
  13. package/dist/collection/assets/webawesome/styles/color/variants/neutral.css +162 -0
  14. package/dist/collection/assets/webawesome/styles/color/variants/success.css +162 -0
  15. package/dist/collection/assets/webawesome/styles/color/variants/warning.css +162 -0
  16. package/dist/collection/assets/webawesome/styles/color/variants.css +5 -0
  17. package/dist/collection/assets/webawesome/styles/component/form-control.styles.d.ts +2 -0
  18. package/dist/collection/assets/webawesome/styles/component/form-control.styles.ts +43 -0
  19. package/dist/collection/assets/webawesome/styles/component/host.styles.d.ts +2 -0
  20. package/dist/collection/assets/webawesome/styles/component/host.styles.ts +18 -0
  21. package/dist/collection/assets/webawesome/styles/component/segmented-field.styles.d.ts +19 -0
  22. package/dist/collection/assets/webawesome/styles/component/segmented-field.styles.ts +92 -0
  23. package/dist/collection/assets/webawesome/styles/component/size.styles.d.ts +2 -0
  24. package/dist/collection/assets/webawesome/styles/component/size.styles.ts +26 -0
  25. package/dist/collection/assets/webawesome/styles/component/variants.styles.d.ts +2 -0
  26. package/dist/collection/assets/webawesome/styles/component/variants.styles.ts +69 -0
  27. package/dist/collection/assets/webawesome/styles/component/visually-hidden.styles.d.ts +2 -0
  28. package/dist/collection/assets/webawesome/styles/component/visually-hidden.styles.ts +19 -0
  29. package/dist/collection/assets/webawesome/styles/layers.css +21 -0
  30. package/dist/collection/assets/webawesome/styles/native.css +1439 -0
  31. package/dist/collection/assets/webawesome/styles/themes/awesome.css +614 -0
  32. package/dist/collection/assets/webawesome/styles/themes/default.css +373 -0
  33. package/dist/collection/assets/webawesome/styles/themes/shoelace.css +648 -0
  34. package/dist/collection/assets/webawesome/styles/utilities/align-items.css +44 -0
  35. package/dist/collection/assets/webawesome/styles/utilities/border-radius.css +20 -0
  36. package/dist/collection/assets/webawesome/styles/utilities/flex-wrap.css +16 -0
  37. package/dist/collection/assets/webawesome/styles/utilities/fouce.css +17 -0
  38. package/dist/collection/assets/webawesome/styles/utilities/gap.css +56 -0
  39. package/dist/collection/assets/webawesome/styles/utilities/justify-content.css +32 -0
  40. package/dist/collection/assets/webawesome/styles/utilities/layout.css +159 -0
  41. package/dist/collection/assets/webawesome/styles/utilities/placeholder.css +9 -0
  42. package/dist/collection/assets/webawesome/styles/utilities/prose.css +161 -0
  43. package/dist/collection/assets/webawesome/styles/utilities/scroll-lock.css +20 -0
  44. package/dist/collection/assets/webawesome/styles/utilities/size.css +21 -0
  45. package/dist/collection/assets/webawesome/styles/utilities/text.css +262 -0
  46. package/dist/collection/assets/webawesome/styles/utilities/variants.css +62 -0
  47. package/dist/collection/assets/webawesome/styles/utilities/visually-hidden.css +17 -0
  48. package/dist/collection/assets/webawesome/styles/utilities.css +17 -0
  49. package/dist/collection/assets/webawesome/styles/webawesome.css +11 -0
  50. package/dist/collection/collection-manifest.json +2 -0
  51. package/dist/collection/components/ogm-attributes/ogm-attributes.css +68 -0
  52. package/dist/collection/components/ogm-attributes/ogm-attributes.js +112 -0
  53. package/dist/collection/components/ogm-image/ogm-image.css +1 -1
  54. package/dist/collection/components/ogm-image/ogm-image.js +16 -18
  55. package/dist/collection/components/ogm-map/ogm-map.css +10 -5
  56. package/dist/collection/components/ogm-map/ogm-map.js +170 -86
  57. package/dist/collection/components/ogm-menubar/ogm-menubar.css +16 -14
  58. package/dist/collection/components/ogm-menubar/ogm-menubar.js +3 -5
  59. package/dist/collection/components/ogm-menubar/ogm-menubar.test.js +7 -3
  60. package/dist/collection/components/ogm-metadata/ogm-metadata.css +6 -492
  61. package/dist/collection/components/ogm-metadata/ogm-metadata.js +3 -5
  62. package/dist/collection/components/ogm-metadata/ogm-metadata.test.js +1 -1
  63. package/dist/collection/components/ogm-previews/ogm-previews.css +44 -0
  64. package/dist/collection/components/ogm-previews/ogm-previews.js +172 -0
  65. package/dist/collection/components/ogm-settings/ogm-settings.js +7 -9
  66. package/dist/collection/components/ogm-sidebar/ogm-sidebar.css +50 -503
  67. package/dist/collection/components/ogm-sidebar/ogm-sidebar.js +8 -12
  68. package/dist/collection/components/ogm-viewer/ogm-viewer.css +4 -974
  69. package/dist/collection/components/ogm-viewer/ogm-viewer.js +41 -25
  70. package/dist/collection/lib/previewers/cog-deck.js +14 -9
  71. package/dist/collection/lib/previewers/cog.js +3 -3
  72. package/dist/collection/lib/previewers/geojson.js +3 -2
  73. package/dist/collection/lib/previewers/maplibre.js +9 -15
  74. package/dist/collection/lib/previewers/pmtiles-raster.js +1 -1
  75. package/dist/collection/lib/previewers/pmtiles-vector.js +7 -1
  76. package/dist/collection/lib/previewers/raster.js +1 -1
  77. package/dist/collection/lib/previewers/vector.js +65 -30
  78. package/dist/collection/lib/previewers/wms.js +1 -1
  79. package/dist/collection/lib/record.js +1 -1
  80. package/dist/collection/lib/record.test.js +1 -1
  81. package/dist/collection/lib/references.js +0 -65
  82. package/dist/collection/lib/references.test.js +0 -150
  83. package/dist/collection/lib/sources/cog.js +5 -2
  84. package/dist/collection/lib/sources/geojson.js +7 -1
  85. package/dist/collection/lib/sources/iiif-manifest.js +55 -0
  86. package/dist/collection/lib/sources/iiif-manifest.test.js +110 -0
  87. package/dist/collection/lib/sources/iiif.js +11 -0
  88. package/dist/collection/lib/sources/maplibre.js +8 -0
  89. package/dist/collection/lib/sources/openindexmap.js +3 -0
  90. package/dist/collection/lib/sources/pmtiles.js +10 -4
  91. package/dist/collection/lib/sources/raster.js +3 -3
  92. package/dist/collection/lib/sources/source.js +26 -7
  93. package/dist/collection/lib/sources/tilejson.js +7 -1
  94. package/dist/collection/lib/sources/tms.js +3 -0
  95. package/dist/collection/lib/sources/vector.js +3 -3
  96. package/dist/collection/lib/sources/wms.js +6 -11
  97. package/dist/collection/lib/sources/xyz.js +3 -0
  98. package/dist/collection/lib/themes/maplibre.js +46 -0
  99. package/dist/collection/lib/themes/theme.js +23 -0
  100. package/dist/esm/{index-BdFT_kJa.js → index-DTLAlWKQ.js} +66 -3
  101. package/dist/esm/{lerc-DFDScDrO.js → lerc-Bz409klg.js} +2 -2
  102. package/dist/esm/loader.js +3 -3
  103. package/dist/esm/{ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-settings.ogm-sidebar.ogm-viewer-r5w_49n3.js → ogm-attributes.ogm-image.ogm-map.ogm-menubar.ogm-metadata.ogm-previews.ogm-settings.ogm-sidebar.ogm-viewer-C9zV3wMe.js} +13639 -7140
  104. package/dist/esm/ogm-attributes_9.entry.js +2 -0
  105. package/dist/esm/ogm-viewer.js +3 -3
  106. package/dist/ogm-viewer/assets/webawesome/styles/color/palettes/base.css +44 -0
  107. package/dist/ogm-viewer/assets/webawesome/styles/color/palettes/bright.css +145 -0
  108. package/dist/ogm-viewer/assets/webawesome/styles/color/palettes/default.css +146 -0
  109. package/dist/ogm-viewer/assets/webawesome/styles/color/palettes/shoelace.css +146 -0
  110. package/dist/ogm-viewer/assets/webawesome/styles/color/variants/brand.css +162 -0
  111. package/dist/ogm-viewer/assets/webawesome/styles/color/variants/danger.css +162 -0
  112. package/dist/ogm-viewer/assets/webawesome/styles/color/variants/neutral.css +162 -0
  113. package/dist/ogm-viewer/assets/webawesome/styles/color/variants/success.css +162 -0
  114. package/dist/ogm-viewer/assets/webawesome/styles/color/variants/warning.css +162 -0
  115. package/dist/ogm-viewer/assets/webawesome/styles/color/variants.css +5 -0
  116. package/dist/ogm-viewer/assets/webawesome/styles/component/form-control.styles.d.ts +2 -0
  117. package/dist/ogm-viewer/assets/webawesome/styles/component/form-control.styles.ts +43 -0
  118. package/dist/ogm-viewer/assets/webawesome/styles/component/host.styles.d.ts +2 -0
  119. package/dist/ogm-viewer/assets/webawesome/styles/component/host.styles.ts +18 -0
  120. package/dist/ogm-viewer/assets/webawesome/styles/component/segmented-field.styles.d.ts +19 -0
  121. package/dist/ogm-viewer/assets/webawesome/styles/component/segmented-field.styles.ts +92 -0
  122. package/dist/ogm-viewer/assets/webawesome/styles/component/size.styles.d.ts +2 -0
  123. package/dist/ogm-viewer/assets/webawesome/styles/component/size.styles.ts +26 -0
  124. package/dist/ogm-viewer/assets/webawesome/styles/component/variants.styles.d.ts +2 -0
  125. package/dist/ogm-viewer/assets/webawesome/styles/component/variants.styles.ts +69 -0
  126. package/dist/ogm-viewer/assets/webawesome/styles/component/visually-hidden.styles.d.ts +2 -0
  127. package/dist/ogm-viewer/assets/webawesome/styles/component/visually-hidden.styles.ts +19 -0
  128. package/dist/ogm-viewer/assets/webawesome/styles/layers.css +21 -0
  129. package/dist/ogm-viewer/assets/webawesome/styles/native.css +1439 -0
  130. package/dist/ogm-viewer/assets/webawesome/styles/themes/awesome.css +614 -0
  131. package/dist/ogm-viewer/assets/webawesome/styles/themes/default.css +373 -0
  132. package/dist/ogm-viewer/assets/webawesome/styles/themes/shoelace.css +648 -0
  133. package/dist/ogm-viewer/assets/webawesome/styles/utilities/align-items.css +44 -0
  134. package/dist/ogm-viewer/assets/webawesome/styles/utilities/border-radius.css +20 -0
  135. package/dist/ogm-viewer/assets/webawesome/styles/utilities/flex-wrap.css +16 -0
  136. package/dist/ogm-viewer/assets/webawesome/styles/utilities/fouce.css +17 -0
  137. package/dist/ogm-viewer/assets/webawesome/styles/utilities/gap.css +56 -0
  138. package/dist/ogm-viewer/assets/webawesome/styles/utilities/justify-content.css +32 -0
  139. package/dist/ogm-viewer/assets/webawesome/styles/utilities/layout.css +159 -0
  140. package/dist/ogm-viewer/assets/webawesome/styles/utilities/placeholder.css +9 -0
  141. package/dist/ogm-viewer/assets/webawesome/styles/utilities/prose.css +161 -0
  142. package/dist/ogm-viewer/assets/webawesome/styles/utilities/scroll-lock.css +20 -0
  143. package/dist/ogm-viewer/assets/webawesome/styles/utilities/size.css +21 -0
  144. package/dist/ogm-viewer/assets/webawesome/styles/utilities/text.css +262 -0
  145. package/dist/ogm-viewer/assets/webawesome/styles/utilities/variants.css +62 -0
  146. package/dist/ogm-viewer/assets/webawesome/styles/utilities/visually-hidden.css +17 -0
  147. package/dist/ogm-viewer/assets/webawesome/styles/utilities.css +17 -0
  148. package/dist/ogm-viewer/assets/webawesome/styles/webawesome.css +11 -0
  149. package/dist/ogm-viewer/ogm-viewer.esm.js +1 -1
  150. package/dist/ogm-viewer/p-86b8fafc.entry.js +1 -0
  151. package/dist/ogm-viewer/{p-BeA3REDA.js → p-BrovdLv6.js} +1 -1
  152. package/dist/ogm-viewer/p-CpCT3zlD.js +2750 -0
  153. package/dist/ogm-viewer/p-DTLAlWKQ.js +2 -0
  154. package/dist/types/components/ogm-attributes/ogm-attributes.d.ts +10 -0
  155. package/dist/types/components/ogm-image/ogm-image.d.ts +3 -3
  156. package/dist/types/components/ogm-map/ogm-map.d.ts +32 -14
  157. package/dist/types/components/ogm-menubar/ogm-menubar.d.ts +1 -1
  158. package/dist/types/components/ogm-metadata/ogm-metadata.d.ts +1 -1
  159. package/dist/types/components/ogm-previews/ogm-previews.d.ts +16 -0
  160. package/dist/types/components/ogm-settings/ogm-settings.d.ts +2 -2
  161. package/dist/types/components/ogm-sidebar/ogm-sidebar.d.ts +1 -1
  162. package/dist/types/components/ogm-viewer/ogm-viewer.d.ts +10 -12
  163. package/dist/types/components.d.ts +70 -18
  164. package/dist/types/lib/previewers/cog-deck.d.ts +7 -3
  165. package/dist/types/lib/previewers/cog.d.ts +2 -2
  166. package/dist/types/lib/previewers/maplibre.d.ts +7 -9
  167. package/dist/types/lib/previewers/pmtiles-vector.d.ts +1 -0
  168. package/dist/types/lib/previewers/vector.d.ts +3 -15
  169. package/dist/types/lib/record.d.ts +1 -1
  170. package/dist/types/lib/references.d.ts +0 -8
  171. package/dist/types/lib/sources/cog.d.ts +3 -2
  172. package/dist/types/lib/sources/geojson.d.ts +3 -2
  173. package/dist/types/lib/sources/iiif-manifest.d.ts +12 -0
  174. package/dist/types/lib/sources/iiif-manifest.test.d.ts +1 -0
  175. package/dist/types/lib/sources/iiif.d.ts +5 -0
  176. package/dist/types/lib/sources/maplibre.d.ts +7 -0
  177. package/dist/types/lib/sources/openindexmap.d.ts +1 -0
  178. package/dist/types/lib/sources/pmtiles.d.ts +6 -4
  179. package/dist/types/lib/sources/raster.d.ts +3 -3
  180. package/dist/types/lib/sources/source.d.ts +6 -6
  181. package/dist/types/lib/sources/tilejson.d.ts +3 -2
  182. package/dist/types/lib/sources/tms.d.ts +1 -0
  183. package/dist/types/lib/sources/vector.d.ts +4 -5
  184. package/dist/types/lib/sources/wms.d.ts +4 -3
  185. package/dist/types/lib/sources/xyz.d.ts +1 -0
  186. package/dist/types/lib/themes/maplibre.d.ts +27 -0
  187. package/dist/types/lib/themes/theme.d.ts +7 -0
  188. package/package.json +3 -2
  189. package/dist/cjs/ogm-image_7.cjs.entry.js +0 -14
  190. package/dist/collection/lib/previewers/index.js +0 -36
  191. package/dist/collection/lib/sources/index.js +0 -29
  192. package/dist/esm/ogm-image_7.entry.js +0 -2
  193. package/dist/ogm-viewer/p-0b81e024.entry.js +0 -1
  194. package/dist/ogm-viewer/p-33R3d9fV.js +0 -1950
  195. package/dist/ogm-viewer/p-BdFT_kJa.js +0 -2
  196. package/dist/types/lib/previewers/index.d.ts +0 -3
  197. package/dist/types/lib/sources/index.d.ts +0 -3
@@ -6,14 +6,18 @@
6
6
  position: relative;
7
7
  }
8
8
 
9
- /* inspection cursor
10
- canvas {
11
- cursor: crosshair;
9
+ /* Inspection popups. Vertical scrolling (when content is too tall) is handled by the
10
+ <wa-scroller> inside ogm-attributes, not here - that's what gives it the fading shadow cue. */
11
+ .maplibregl-popup-content {
12
+ max-width: 400px;
13
+ overflow: hidden;
14
+ padding: 0;
15
+ box-shadow: var(--wa-shadow-l);
16
+ border: var(--wa-panel-border-width) solid var(--wa-color-surface-border);
12
17
  }
13
- */
14
18
 
15
19
  /* Dark mode map adjustments */
16
- .sl-theme-dark {
20
+ .wa-dark {
17
21
  .tile-border {
18
22
  stroke: white;
19
23
  }
@@ -47,6 +51,7 @@ canvas {
47
51
 
48
52
  div.maplibregl-popup-content {
49
53
  background-color: black;
54
+ color: #ccc;
50
55
  }
51
56
 
52
57
  div.maplibregl-popup-anchor-right div.maplibregl-popup-tip {
@@ -1,33 +1,49 @@
1
1
  import { h } from "@stencil/core";
2
- import { Protocol as PMTilesProtocol } from "pmtiles";
3
2
  import maplibregl from "maplibre-gl";
3
+ import { Protocol as PMTilesProtocol } from "pmtiles";
4
+ import CogSource from "../../lib/sources/cog";
5
+ import GeoJSONSource from "../../lib/sources/geojson";
6
+ import OpenIndexMapSource from "../../lib/sources/openindexmap";
7
+ import PMTilesSource from "../../lib/sources/pmtiles";
8
+ import RasterSource from "../../lib/sources/raster";
9
+ import WmsSource from "../../lib/sources/wms";
4
10
  import { getElement } from "../../lib/elements";
5
- import { getSources } from "../../lib/sources";
6
- import { getMapPreviewers } from "../../lib/previewers";
11
+ import CogPreviewer from "../../lib/previewers/cog";
12
+ import GeoJSONPreviewer from "../../lib/previewers/geojson";
13
+ import OpenIndexMapPreviewer from "../../lib/previewers/openindexmap";
14
+ import PMTilesRasterPreviewer from "../../lib/previewers/pmtiles-raster";
15
+ import PMTilesVectorPreviewer from "../../lib/previewers/pmtiles-vector";
16
+ import RasterPreviewer from "../../lib/previewers/raster";
17
+ import WmsPreviewer from "../../lib/previewers/wms";
18
+ import MapLibreTheme from "../../lib/themes/maplibre";
7
19
  // Register PMTiles protocol
8
20
  const protocol = new PMTilesProtocol();
9
21
  maplibregl.addProtocol('pmtiles', protocol.tile);
10
22
  export class OgmMap {
11
23
  el;
12
- record;
24
+ source;
13
25
  theme;
14
- previewOpacity = 100;
15
26
  padding = 0;
16
27
  mapIdle;
17
28
  mapLoading;
18
- // MapLibre map instance
29
+ // MapLibre map instance and popup instance for feature info display
19
30
  map;
31
+ mapTheme;
32
+ popup = undefined;
33
+ attributesEl;
34
+ hoveredFeature = undefined;
20
35
  // Container element reference for fullscreen
21
36
  containerEl;
22
- // Previewers for the currently previewed sources
23
- previewers = [];
37
+ // Previewer for the currently previewed source
38
+ previewer = undefined;
24
39
  // Set up the mapLibre map and event bindings on load
25
40
  componentDidLoad() {
41
+ this.mapTheme = new MapLibreTheme(this.el);
26
42
  this.map = new maplibregl.Map({
27
43
  container: getElement(this.el, '#map'),
28
44
  attributionControl: false,
29
45
  cooperativeGestures: true,
30
- style: this.baseMapStyle,
46
+ style: this.mapTheme.getBaseMapStyle(),
31
47
  center: [0, 0],
32
48
  zoom: 2,
33
49
  minZoom: 2,
@@ -35,26 +51,30 @@ export class OgmMap {
35
51
  this.getContainer();
36
52
  this.addControls();
37
53
  this.map.on('idle', () => this.mapIdle.emit());
38
- this.map.on('load', () => this.previewRecord(this.record));
54
+ this.map.on('load', () => this.previewSource(this.source));
55
+ this.map.on('mousemove', this.handleHover.bind(this));
56
+ this.map.on('click', this.handleClick.bind(this));
39
57
  // View as a globe with atmosphere effects
40
58
  this.map.on('style.load', () => {
41
- this.map.setProjection({
42
- type: 'globe',
43
- });
44
- this.map.setSky({
45
- 'sky-color': '#199EF3',
46
- 'sky-horizon-blend': 0.5,
47
- 'horizon-color': '#ffffff',
48
- 'horizon-fog-blend': 0.5,
49
- 'fog-color': '#0000ff',
50
- 'fog-ground-blend': 0.5,
51
- 'atmosphere-blend': ['interpolate', ['linear'], ['zoom'], 0, 1, 10, 1, 12, 0],
52
- });
59
+ this.map.setProjection({ type: 'globe' });
60
+ this.map.setSky(this.mapTheme.getSkyStyle());
53
61
  });
62
+ // Keep attributes outside Stencil render pipeline so that MapLibre can
63
+ // use the HTML directly for the popup content
64
+ this.attributesEl = document.createElement('ogm-attributes');
65
+ this.attributesEl.features = [];
66
+ }
67
+ // Clean up the map to prevent warnings/errors when removed from the DOM
68
+ disconnectedCallback() {
69
+ if (this.map)
70
+ this.map.remove();
54
71
  }
55
72
  // Find the container element for the map (used for fullscreen control)
56
73
  getContainer() {
57
- const containerEl = this.el.parentElement?.parentElement;
74
+ const viewerEl = document.querySelector('ogm-viewer');
75
+ if (!viewerEl)
76
+ throw new Error('Could not find ogm-viewer element');
77
+ const containerEl = getElement(viewerEl, '.container');
58
78
  if (!containerEl)
59
79
  throw new Error('Could not find map container element');
60
80
  this.containerEl = containerEl;
@@ -74,33 +94,57 @@ export class OgmMap {
74
94
  },
75
95
  }));
76
96
  }
77
- async previewRecord(record) {
78
- if (!record)
97
+ // Get the appropriate previewer for our source
98
+ async getMapPreviewer(map) {
99
+ const style = this.mapTheme.getStyle();
100
+ if (this.source instanceof OpenIndexMapSource)
101
+ return new OpenIndexMapPreviewer(this.source, map, style);
102
+ else if (this.source instanceof GeoJSONSource)
103
+ return new GeoJSONPreviewer(this.source, map, style);
104
+ else if (this.source instanceof PMTilesSource) {
105
+ if (await this.source.isVector())
106
+ return new PMTilesVectorPreviewer(this.source, map, style);
107
+ else
108
+ return new PMTilesRasterPreviewer(this.source, map, style);
109
+ }
110
+ else if (this.source instanceof WmsSource)
111
+ return new WmsPreviewer(this.source, map, style);
112
+ else if (this.source instanceof CogSource)
113
+ return new CogPreviewer(this.source, map, style);
114
+ else if (this.source instanceof RasterSource)
115
+ return new RasterPreviewer(this.source, map, style);
116
+ }
117
+ async previewSource(source) {
118
+ // Do nothing if we didn't get passed a source
119
+ if (!source)
79
120
  return;
121
+ // Indicate loading state so we can show the spinner
80
122
  this.mapLoading.emit();
81
- // Clear any existing preview layers and sources
82
- await Promise.all(this.previewers.map(previewer => previewer.clearPreview()));
83
- this.previewers = [];
84
- // Create sources and previewers using references
85
- const sources = getSources(record);
86
- const previewOptions = { fillColor: this.fillColor, lineColor: this.lineColor, opacity: this.previewOpacity / 100 };
87
- const previewers = await getMapPreviewers(sources, this.map, previewOptions);
88
- // Preview each source
89
- for (const previewer of previewers) {
90
- this.previewers.push(previewer);
91
- await previewer.preview();
123
+ // Close popup if one is open
124
+ this.clearFeatureSelection();
125
+ this.destroyPopup();
126
+ // Clear existing preview
127
+ if (this.previewer) {
128
+ await this.previewer.clearPreview();
129
+ this.previewer = undefined;
92
130
  }
131
+ // Get the appropriate previewer for our source and preview it
132
+ this.previewer = await this.getMapPreviewer(this.map);
133
+ if (!this.previewer)
134
+ throw new Error(`No previewer found for source: ${source.constructor.name}`);
135
+ await this.previewer.preview();
93
136
  // Fit to bounds from the record
94
- const bounds = record.getBounds();
137
+ const bounds = await this.source.getBounds();
95
138
  if (bounds)
96
139
  await this.fitMapBounds(bounds);
140
+ // Emit map idle event to signal that the map is ready
97
141
  this.mapIdle.emit();
98
142
  }
99
- // Fit the map to the provided bounds
143
+ // Fit the map to the given bounds; return when moving is finished
100
144
  async fitMapBounds(bounds) {
101
145
  return new Promise(resolve => {
102
146
  this.map.once('moveend', () => resolve());
103
- this.map.fitBounds(bounds, { padding: this.padding });
147
+ this.map.fitBounds(bounds);
104
148
  });
105
149
  }
106
150
  // When padding is changed, move the map over to make room for the sidebar
@@ -111,20 +155,79 @@ export class OgmMap {
111
155
  async easeMapTo(options) {
112
156
  return await this.map.easeTo(options);
113
157
  }
114
- // Base map style based on the theme
115
- get baseMapStyle() {
116
- return this.theme === 'dark' ? 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json' : 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json';
158
+ // Use the crosshair cursor if there's something to inspect
159
+ handleHover(event) {
160
+ const features = this.map.queryRenderedFeatures(event.point, { layers: this.previewLayers });
161
+ if (features.length > 0) {
162
+ this.map.getCanvas().style.cursor = 'crosshair';
163
+ this.hoverFeature(features[0]);
164
+ }
165
+ else {
166
+ this.map.getCanvas().style.cursor = '';
167
+ this.clearHoveredFeature();
168
+ }
169
+ }
170
+ // Show the attributes popup on click
171
+ handleClick(event) {
172
+ // Clear any existing popup and feature selection
173
+ this.clearFeatureSelection();
174
+ this.destroyPopup();
175
+ // Check if we have feature(s) to inspect at the clicked point
176
+ const features = this.map.queryRenderedFeatures(event.point, { layers: this.previewLayers });
177
+ if (features.length === 0)
178
+ return;
179
+ // Create and populate the attributes popup and select the first feature if multiple
180
+ this.attributesEl.features = features;
181
+ this.createPopup(event.lngLat);
182
+ this.selectFeature(features[0]);
183
+ }
184
+ // Listen to selection events from the popup and highlight the selected feature
185
+ handleFeatureSelected(event) {
186
+ this.clearFeatureSelection();
187
+ const feature = event.detail;
188
+ this.selectFeature(feature);
117
189
  }
118
- // Fill colors for vector data based on the theme
119
- get fillColor() {
120
- return window.getComputedStyle(this.el).getPropertyValue('--sl-color-primary-500');
190
+ // Reset styling of all features to unselected state
191
+ clearFeatureSelection() {
192
+ this.attributesEl.features.forEach(feature => {
193
+ this.map.setFeatureState({ source: feature.source, id: feature.id, sourceLayer: feature.sourceLayer }, { selected: false });
194
+ });
195
+ this.attributesEl.features = [];
196
+ }
197
+ // Set styling of a single feature to selected state
198
+ selectFeature(feature) {
199
+ this.map.setFeatureState({ source: feature.source, id: feature.id, sourceLayer: feature.sourceLayer }, { selected: true });
200
+ }
201
+ // Set styling of a single feature to hovered state
202
+ hoverFeature(feature) {
203
+ this.clearHoveredFeature();
204
+ this.hoveredFeature = feature;
205
+ this.map.setFeatureState({ source: feature.source, id: feature.id, sourceLayer: feature.sourceLayer }, { hover: true });
206
+ }
207
+ // Clear the hovered feature state
208
+ clearHoveredFeature() {
209
+ if (this.hoveredFeature) {
210
+ this.map.setFeatureState({ source: this.hoveredFeature.source, id: this.hoveredFeature.id, sourceLayer: this.hoveredFeature.sourceLayer }, { hover: false });
211
+ this.hoveredFeature = undefined;
212
+ }
121
213
  }
122
- // Line/stroke color for vector data based on the theme
123
- get lineColor() {
124
- return window.getComputedStyle(this.el).getPropertyValue('--sl-color-neutral-900');
214
+ // Create a new popup and set its content and location
215
+ createPopup(location) {
216
+ this.popup = new maplibregl.Popup({ maxWidth: 'none', closeButton: false }).setDOMContent(this.attributesEl).setLngLat(location).addTo(this.map);
217
+ }
218
+ // Remove popup from the map and clear the reference
219
+ destroyPopup() {
220
+ if (this.popup) {
221
+ this.popup.remove();
222
+ this.popup = undefined;
223
+ }
224
+ }
225
+ // Get the IDs of all layers in the previewers
226
+ get previewLayers() {
227
+ return this.previewer?.layerIds || [];
125
228
  }
126
229
  render() {
127
- return h("div", { key: 'f56397cdabf7610e7bf796920e34c8ae6b9943a9', id: "map", class: `sl-theme-${this.theme}` });
230
+ return h("div", { key: '1c38c0508638813aee913dce29f533845393023b', id: "map", class: `wa-${this.theme}` });
128
231
  }
129
232
  static get is() { return "ogm-map"; }
130
233
  static get encapsulation() { return "shadow"; }
@@ -140,18 +243,16 @@ export class OgmMap {
140
243
  }
141
244
  static get properties() {
142
245
  return {
143
- "record": {
246
+ "source": {
144
247
  "type": "unknown",
145
248
  "mutable": false,
146
249
  "complexType": {
147
- "original": "OgmRecord",
148
- "resolved": "OgmRecord",
250
+ "original": "Source",
251
+ "resolved": "Source",
149
252
  "references": {
150
- "OgmRecord": {
151
- "location": "import",
152
- "path": "../../lib/record",
153
- "id": "src/lib/record.ts::OgmRecord",
154
- "referenceLocation": "OgmRecord"
253
+ "Source": {
254
+ "location": "global",
255
+ "id": "global::Source"
155
256
  }
156
257
  }
157
258
  },
@@ -183,26 +284,6 @@ export class OgmMap {
183
284
  "reflect": false,
184
285
  "attribute": "theme"
185
286
  },
186
- "previewOpacity": {
187
- "type": "number",
188
- "mutable": false,
189
- "complexType": {
190
- "original": "number",
191
- "resolved": "number",
192
- "references": {}
193
- },
194
- "required": false,
195
- "optional": false,
196
- "docs": {
197
- "tags": [],
198
- "text": ""
199
- },
200
- "getter": false,
201
- "setter": false,
202
- "reflect": false,
203
- "attribute": "preview-opacity",
204
- "defaultValue": "100"
205
- },
206
287
  "padding": {
207
288
  "type": "number",
208
289
  "mutable": false,
@@ -262,7 +343,7 @@ export class OgmMap {
262
343
  return {
263
344
  "easeMapTo": {
264
345
  "complexType": {
265
- "signature": "(options: EaseToOptions) => Promise<maplibregl.Map>",
346
+ "signature": "(options: maplibregl.EaseToOptions) => Promise<maplibregl.Map>",
266
347
  "parameters": [{
267
348
  "name": "options",
268
349
  "type": "AnimationOptions & CenterZoomBearing & { pitch?: number; roll?: number; elevation?: number; } & { delayEndEvents?: number; padding?: number | PaddingOptions; around?: LngLatLike; easeId?: string; noMoveStart?: boolean; }",
@@ -276,12 +357,6 @@ export class OgmMap {
276
357
  "maplibregl": {
277
358
  "location": "global",
278
359
  "id": "global::maplibregl"
279
- },
280
- "EaseToOptions": {
281
- "location": "import",
282
- "path": "maplibre-gl",
283
- "id": "node_modules::EaseToOptions",
284
- "referenceLocation": "EaseToOptions"
285
360
  }
286
361
  },
287
362
  "return": "Promise<Map$1>"
@@ -296,11 +371,20 @@ export class OgmMap {
296
371
  static get elementRef() { return "el"; }
297
372
  static get watchers() {
298
373
  return [{
299
- "propName": "record",
300
- "methodName": "previewRecord"
374
+ "propName": "source",
375
+ "methodName": "previewSource"
301
376
  }, {
302
377
  "propName": "padding",
303
378
  "methodName": "onPaddingChange"
304
379
  }];
305
380
  }
381
+ static get listeners() {
382
+ return [{
383
+ "name": "featureSelected",
384
+ "method": "handleFeatureSelected",
385
+ "target": "body",
386
+ "capture": false,
387
+ "passive": false
388
+ }];
389
+ }
306
390
  }
@@ -1,38 +1,40 @@
1
1
  .menubar {
2
2
  display: flex;
3
3
  align-items: center;
4
- gap: var(--sl-spacing-small);
5
- padding: var(--sl-spacing-x-small);
6
- background-color: var(--sl-panel-background-color);
7
- border-top: calc(var(--sl-panel-border-width) * 2) solid var(--accent-color);
8
- border-bottom: var(--sl-panel-border-width) solid var(--sl-panel-border-color);
4
+ gap: var(--wa-space-s);
5
+ padding: var(--wa-space-xs);
6
+ background-color: var(--wa-color-surface-raised);
7
+ border-top: calc(var(--wa-panel-border-width) * 2) solid var(--accent-color);
8
+ border-bottom: var(--wa-panel-border-width) solid var(--wa-color-surface-border);
9
9
 
10
10
  /* shadow above map and sidebar */
11
11
  position: relative;
12
12
  z-index: 701;
13
- box-shadow: 0 2px 6px 0px var(--sl-overlay-background-color);
13
+ box-shadow: 0 2px 6px 0px var(--wa-color-shadow);
14
14
  }
15
15
 
16
16
  /* Truncate long titles with an ellipsis */
17
17
  .title {
18
18
  flex: auto;
19
- font-size: var(--sl-font-size-large);
20
- color: var(--sl-color-neutral-800);
19
+ font-size: var(--wa-font-size-l);
20
+ color: var(--wa-color-text-normal);
21
21
  text-overflow: ellipsis;
22
22
  overflow: hidden;
23
23
  white-space: nowrap;
24
24
  }
25
25
 
26
- .menu-button {
27
- font-size: var(--sl-font-size-x-large);
26
+ /* Size the icon glyph directly rather than the button's own font-size, which would inflate
27
+ the button's whole clickable box (wa-button scales its control height off font-size) */
28
+ .menu-button wa-icon {
29
+ font-size: var(--wa-font-size-xl);
28
30
  }
29
31
 
30
32
  .restricted-icon {
31
- color: var(--sl-color-danger-600);
32
- font-size: var(--sl-font-size-large);
33
+ color: var(--wa-color-danger-on-normal);
34
+ font-size: var(--wa-font-size-l);
33
35
  }
34
36
 
35
37
  .loading-spinner {
36
- font-size: var(--sl-font-size-large);
37
- margin: 0 var(--sl-spacing-x-small);
38
+ font-size: var(--wa-font-size-l);
39
+ margin: 0 var(--wa-space-xs);
38
40
  }
@@ -5,7 +5,7 @@ export class OgmMenubar {
5
5
  sidebarToggled;
6
6
  loading = false;
7
7
  render() {
8
- return (h("div", { key: 'b9f3fa82a91afe42eacafa5c6f4e7041107f9317', class: `menubar ${this.theme && `sl-theme-${this.theme}`}` }, h("sl-icon-button", { key: '299008820e057cdadafa6be1c40cc51d99f1afb5', name: "list", label: "Open sidebar", class: "menu-button", onclick: this.sidebarToggled.emit }), this.record?.restricted && (h("sl-tooltip", { key: 'c676c4cf06c136d6ca055b567f4318f2678b323a', content: "Restricted access" }, h("sl-icon", { key: 'bbad7996a1e27d694309d8e5dd8146ba4cb053e0', name: "lock-fill", label: "Restricted access", class: "restricted-icon" }))), h("div", { key: 'ad8ba00f9b3a6b93fcf248d217ecc99f798645a8', class: "title" }, this.record?.title), this.loading && h("sl-spinner", { key: 'fa5b8f92939601e0afed5bfa85b99aad4db221f5', class: "loading-spinner" })));
8
+ return (h("div", { key: '437b8f1b6f44844f1db4460c6597c0a68479a8f7', class: `menubar ${this.theme && `wa-${this.theme}`}` }, h("wa-button", { key: 'baf0a0baa96fcf3f114fdf47b4446b90df862c6b', appearance: "plain", class: "menu-button", onclick: this.sidebarToggled.emit }, h("wa-icon", { key: 'b4e1c07bd7284dbd191997a4b270d12c1e1d5b63', name: "list", label: "Open sidebar", canvas: "auto" })), this.record?.restricted && (h(h.Fragment, null, h("wa-tooltip", { key: '4e8d318982e7bd8af99b320e4810b23d0c00b264', for: "restricted-icon" }, "Restricted access"), h("wa-icon", { key: '6da389ec7b55697d203dd2935af192ae64c0622b', id: "restricted-icon", name: "lock-fill", label: "Restricted access", class: "restricted-icon", canvas: "auto" }))), h("div", { key: 'd118cbb176a44ae761d82c7adff2b0fa31cbe87e', class: "title" }, this.record?.title), this.loading && h("wa-spinner", { key: '5bc6c254a1fa5b4b4bb82ec8fc1cc04ff1457a31', class: "loading-spinner" })));
9
9
  }
10
10
  static get is() { return "ogm-menubar"; }
11
11
  static get encapsulation() { return "shadow"; }
@@ -29,10 +29,8 @@ export class OgmMenubar {
29
29
  "resolved": "OgmRecord",
30
30
  "references": {
31
31
  "OgmRecord": {
32
- "location": "import",
33
- "path": "../../lib/record",
34
- "id": "src/lib/record.ts::OgmRecord",
35
- "referenceLocation": "OgmRecord"
32
+ "location": "global",
33
+ "id": "global::OgmRecord"
36
34
  }
37
35
  }
38
36
  },
@@ -1,5 +1,5 @@
1
1
  import { render, describe, it, expect, h } from "@stencil/vitest";
2
- import { OgmRecord } from "../../lib/record";
2
+ import OgmRecord from "../../lib/record";
3
3
  describe('ogm-menubar', () => {
4
4
  describe('with a record', () => {
5
5
  it('renders the record title', async () => {
@@ -17,7 +17,9 @@ describe('ogm-menubar', () => {
17
17
  <ogm-menubar class="hydrated">
18
18
  <mock:shadow-root>
19
19
  <div class="menubar undefined">
20
- <sl-icon-button name="list" label="Open sidebar" class="menu-button"></sl-icon-button>
20
+ <wa-button appearance="plain" class="menu-button">
21
+ <wa-icon name="list" label="Open sidebar" canvas="auto"></wa-icon>
22
+ </wa-button>
21
23
  <div class="title">
22
24
  Coho Salmon Watersheds: San Francisco Bay Area, California, 2011
23
25
  </div>
@@ -34,7 +36,9 @@ describe('ogm-menubar', () => {
34
36
  <ogm-menubar class="hydrated">
35
37
  <mock:shadow-root>
36
38
  <div class="menubar undefined">
37
- <sl-icon-button name="list" label="Open sidebar" class="menu-button"></sl-icon-button>
39
+ <wa-button appearance="plain" class="menu-button">
40
+ <wa-icon name="list" label="Open sidebar" canvas="auto"></wa-icon>
41
+ </wa-button>
38
42
  <div class="title"></div>
39
43
  </div>
40
44
  </mock:shadow-root>