@panoramax/web-viewer 4.0.3 → 4.1.0-develop-55fdf56c

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 (106) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/build/index.css +9 -9
  3. package/build/index.css.map +1 -1
  4. package/build/index.js +640 -456
  5. package/build/index.js.map +1 -1
  6. package/build/map.html +1 -1
  7. package/build/photo.html +1 -1
  8. package/build/viewer.html +3 -3
  9. package/build/widgets.html +1 -1
  10. package/config/jest/mocks.js +9 -1
  11. package/docs/03_URL_settings.md +21 -0
  12. package/docs/09_Develop.md +6 -0
  13. package/docs/images/comparative_3drender.jpg +0 -0
  14. package/docs/index.md +13 -0
  15. package/docs/reference/components/core/Editor.md +18 -0
  16. package/docs/reference/components/core/PhotoViewer.md +1 -0
  17. package/docs/reference/components/core/Viewer.md +1 -0
  18. package/docs/reference/components/menus/MapLegend.md +17 -0
  19. package/docs/reference/components/menus/MiniPictureLegend.md +15 -0
  20. package/docs/reference/components/menus/PictureLegend.md +17 -0
  21. package/docs/reference/components/ui/AnnotationsSwitch.md +15 -0
  22. package/docs/reference/components/ui/Button.md +1 -1
  23. package/docs/reference/components/ui/CopyButton.md +1 -1
  24. package/docs/reference/components/ui/LinkButton.md +1 -1
  25. package/docs/reference/components/ui/Map.md +18 -2
  26. package/docs/reference/components/ui/MapMore.md +6 -2
  27. package/docs/reference/components/ui/SemanticsEditor.md +87 -0
  28. package/docs/reference/components/ui/widgets/Legend.md +5 -4
  29. package/docs/reference/utils/URLHandler.md +7 -0
  30. package/docs/reference.md +3 -1
  31. package/docs/tutorials/aerial_imagery.md +13 -11
  32. package/mkdocs.yml +3 -1
  33. package/package.json +7 -7
  34. package/public/map.html +3 -3
  35. package/public/photo.html +1 -1
  36. package/public/viewer.html +3 -3
  37. package/public/widgets.html +32 -0
  38. package/src/components/core/Basic.css +2 -0
  39. package/src/components/core/Basic.js +3 -1
  40. package/src/components/core/CoverageMap.css +1 -0
  41. package/src/components/core/CoverageMap.js +6 -0
  42. package/src/components/core/Editor.css +2 -0
  43. package/src/components/core/Editor.js +56 -7
  44. package/src/components/core/PhotoViewer.css +10 -10
  45. package/src/components/core/PhotoViewer.js +56 -23
  46. package/src/components/core/Viewer.css +16 -4
  47. package/src/components/core/Viewer.js +62 -33
  48. package/src/components/layout/BottomDrawer.js +2 -1
  49. package/src/components/layout/Tabs.js +4 -0
  50. package/src/components/menus/AnnotationsList.js +13 -9
  51. package/src/components/menus/MapBackground.js +8 -3
  52. package/src/components/menus/MapFilters.js +11 -2
  53. package/src/components/menus/MapLayers.js +3 -2
  54. package/src/components/menus/MapLegend.js +35 -4
  55. package/src/components/menus/MiniPictureLegend.js +74 -0
  56. package/src/components/menus/PictureLegend.js +89 -33
  57. package/src/components/menus/PictureMetadata.js +49 -17
  58. package/src/components/menus/PlayerOptions.js +3 -3
  59. package/src/components/menus/Share.js +3 -3
  60. package/src/components/menus/index.js +5 -4
  61. package/src/components/styles.js +11 -0
  62. package/src/components/ui/AnnotationsSwitch.js +171 -0
  63. package/src/components/ui/Button.js +1 -1
  64. package/src/components/ui/CopyButton.js +1 -1
  65. package/src/components/ui/LinkButton.js +1 -1
  66. package/src/components/ui/Map.css +4 -0
  67. package/src/components/ui/Map.js +17 -5
  68. package/src/components/ui/MapMore.js +61 -25
  69. package/src/components/ui/Photo.css +11 -2
  70. package/src/components/ui/Photo.js +6 -3
  71. package/src/components/ui/SemanticsEditor.js +157 -0
  72. package/src/components/ui/index.js +2 -1
  73. package/src/components/ui/widgets/GeoSearch.js +3 -2
  74. package/src/components/ui/widgets/Legend.js +76 -15
  75. package/src/components/ui/widgets/MapFiltersButton.js +3 -3
  76. package/src/components/ui/widgets/MapLayersButton.js +3 -3
  77. package/src/components/ui/widgets/OSMEditors.js +2 -2
  78. package/src/components/ui/widgets/PictureLegendActions.js +24 -42
  79. package/src/components/ui/widgets/Player.js +3 -3
  80. package/src/components/ui/widgets/Zoom.js +4 -2
  81. package/src/translations/ar.json +1 -0
  82. package/src/translations/da.json +3 -2
  83. package/src/translations/de.json +64 -13
  84. package/src/translations/en.json +5 -1
  85. package/src/translations/eo.json +32 -2
  86. package/src/translations/fr.json +7 -1
  87. package/src/translations/it.json +33 -2
  88. package/src/translations/nl.json +53 -11
  89. package/src/translations/zh_Hant.json +29 -2
  90. package/src/utils/API.js +17 -1
  91. package/src/utils/InitParameters.js +46 -4
  92. package/src/utils/URLHandler.js +9 -1
  93. package/src/utils/map.js +24 -1
  94. package/src/utils/semantics.js +53 -1
  95. package/src/utils/services.js +16 -0
  96. package/src/utils/widgets.js +38 -0
  97. package/tests/components/core/Editor.test.js +1 -1
  98. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +18 -6
  99. package/tests/components/core/__snapshots__/Viewer.test.js.snap +15 -3
  100. package/tests/components/ui/Photo.test.js +1 -0
  101. package/tests/components/ui/__snapshots__/Map.test.js.snap +164 -0
  102. package/tests/utils/InitParameters.test.js +27 -0
  103. package/tests/utils/map.test.js +12 -0
  104. package/tests/utils/semantics.test.js +34 -5
  105. package/docs/reference/components/ui/HashTags.md +0 -15
  106. package/src/components/ui/HashTags.js +0 -98
@@ -1,3 +1,8 @@
1
+ pnx-viewer {
2
+ position: relative;
3
+ display: block;
4
+ }
5
+
1
6
  /* Maximized components */
2
7
  pnx-viewer .pnx-map.maplibregl-map,
3
8
  pnx-viewer .pnx-psv {
@@ -56,7 +61,6 @@ pnx-viewer pnx-mini {
56
61
  pnx-viewer pnx-mini {
57
62
  min-width: unset;
58
63
  min-height: unset;
59
- margin-bottom: 40px;
60
64
  }
61
65
  }
62
66
 
@@ -73,13 +77,13 @@ pnx-viewer:not(pnx-viewer[focus="pic"]) .pnx-only-psv {
73
77
 
74
78
  /* Override legend positioning */
75
79
  @media screen and (min-width: 576px) {
76
- pnx-viewer pnx-widget-legend {
80
+ pnx-viewer pnx-widget-legend:not([light="true"]) {
77
81
  position: absolute;
78
82
  left: 10px;
79
83
  top: 60px;
80
84
  }
81
85
 
82
- pnx-viewer[focus="pic"] pnx-widget-legend {
86
+ pnx-viewer[focus="pic"] pnx-widget-legend:not([light="true"]) {
83
87
  top: 10px;
84
88
  }
85
89
  }
@@ -95,4 +99,12 @@ pnx-viewer .pnx-map .maplibregl-ctrl-attrib {
95
99
  width: 250px;
96
100
  max-width: 40vw;
97
101
  }
98
- }
102
+ }
103
+
104
+ /* Hidden widgets on sequence play */
105
+ pnx-viewer.pnx-playing pnx-bottom-drawer,
106
+ pnx-viewer.pnx-playing pnx-mini,
107
+ pnx-viewer.pnx-playing pnx-widget-legend,
108
+ pnx-viewer.pnx-playing pnx-widget-zoom {
109
+ display: none;
110
+ }
@@ -2,11 +2,10 @@
2
2
 
3
3
  import "./Viewer.css";
4
4
  import { linkMapAndPhoto, saveMapParamsToLocalStorage, getMapParamsFromLocalStorage } from "../../utils/map";
5
- import PhotoViewer from "./PhotoViewer";
6
- import Basic from "./Basic";
5
+ import PhotoViewer, {KEYBOARD_SKIP_FOCUS_WIDGETS} from "./PhotoViewer";
7
6
  import MapMore from "../ui/MapMore";
8
7
  import { initMapKeyboardHandler } from "../../utils/map";
9
- import { isNullId } from "../../utils/utils";
8
+ import { isNullId, isInIframe } from "../../utils/utils";
10
9
  import { createWebComp } from "../../utils/widgets";
11
10
  import { fa } from "../../utils/widgets";
12
11
  import { faPanorama } from "@fortawesome/free-solid-svg-icons/faPanorama";
@@ -16,7 +15,6 @@ import { default as InitParameters, alterMapState, alterViewerState } from "../.
16
15
 
17
16
 
18
17
  export const PSV_ZOOM_DELTA = 20;
19
- const PSV_MOVE_DELTA = Math.PI / 6;
20
18
  const MAP_MOVE_DELTA = 100;
21
19
 
22
20
 
@@ -95,6 +93,7 @@ export default class Viewer extends PhotoViewer {
95
93
  * @property {object} [map] An object with [any map option available in Map or MapMore class](#Panoramax.components.ui.MapMore).<br />Example: `map="{'background': 'aerial', 'theme': 'age'}"`
96
94
  * @property {object} [psv] [Any option to pass to Photo component](#Panoramax.components.ui.Photo) as an object.<br />Example: `psv="{'transitionDuration': 500, 'picturesNavigation': 'pic'}"`
97
95
  * @property {string} [url-parameters=true] Should the component add and update URL query parameters to save viewer state ?
96
+ * @property {string} [keyboard-shortcuts=true] Should keyboard shortcuts be enabled ? Set to "false" to fully disable any keyboard shortcuts.
98
97
  * @property {string} [focus=pic] The component showing up as main component (pic, map)
99
98
  * @property {string} [geocoder=nominatim] The geocoder engine to use (nominatim, ban, or URL to a standard [GeocodeJSON-compliant](https://github.com/geocoders/geocodejson-spec/blob/master/draft/README.md) API)
100
99
  * @property {string} [widgets=true] Use default set of widgets ? Set to false to avoid any widget to show up, and use slots to populate as you like.
@@ -149,20 +148,25 @@ export default class Viewer extends PhotoViewer {
149
148
  _parent: this
150
149
  }));
151
150
 
152
- if(!this.isWidthSmall()) {
151
+ if(isInIframe()) {
153
152
  this.legend = createWebComp("pnx-widget-legend", {
154
- slot: this.isWidthSmall() ? "top" : "top-left",
153
+ slot: "bottom-right",
154
+ light: true,
155
155
  _parent: this,
156
156
  focus: this._initParams.getParentPostInit().focus,
157
157
  picture: this._initParams.getParentPostInit().picture,
158
158
  });
159
159
  this.grid.appendChild(this.legend);
160
-
161
- this.grid.appendChild(createWebComp("pnx-hashtags", {
162
- slot: "top-right",
160
+ }
161
+ else if(!this.isWidthSmall()) {
162
+ this.legend = createWebComp("pnx-widget-legend", {
163
+ slot: this.isWidthSmall() ? "top" : "top-left",
163
164
  _parent: this,
164
- class: "pnx-only-psv pnx-print-hidden",
165
- }));
165
+ focus: this._initParams.getParentPostInit().focus,
166
+ picture: this._initParams.getParentPostInit().picture,
167
+ });
168
+ this._miniPicLegend = createWebComp("pnx-mini-picture-legend", { _parent: this });
169
+ this.grid.appendChild(this.legend);
166
170
  }
167
171
  else {
168
172
  this.legend = createWebComp("pnx-picture-legend", { _parent: this });
@@ -179,30 +183,47 @@ export default class Viewer extends PhotoViewer {
179
183
  });
180
184
  }
181
185
 
182
- this.grid.appendChild(createWebComp("pnx-widget-player", {
183
- slot: "top",
184
- _parent: this,
185
- class: "pnx-only-psv pnx-print-hidden",
186
- size: this.isHeightSmall() ? "md": "xl",
187
- }));
186
+ if(!isInIframe()) {
187
+ this.grid.appendChild(createWebComp("pnx-widget-player", {
188
+ slot: "top",
189
+ _parent: this,
190
+ class: "pnx-only-psv pnx-print-hidden",
191
+ size: this.isHeightSmall() ? "md": "xl",
192
+ }));
193
+
194
+ this.grid.appendChild(createWebComp("pnx-annotations-switch", {
195
+ slot: "top",
196
+ _parent: this,
197
+ class: "pnx-only-psv pnx-print-hidden",
198
+ size: this.isHeightSmall() ? "md": "xl",
199
+ }));
188
200
 
189
- this.grid.appendChild(createWebComp("pnx-widget-geosearch", {
190
- slot: this.isWidthSmall() ? "top-right" : "top-left",
191
- _parent: this,
192
- class: "pnx-only-map pnx-print-hidden",
193
- geocoder: this._initParams.getParentPostInit().geocoder,
194
- }));
195
- this.grid.appendChild(createWebComp("pnx-widget-mapfilters", {
196
- slot: this.isWidthSmall() ? "top-right" : "top-left",
197
- _parent: this,
198
- "user-search": this.api._endpoints.user_search !== null && this.api._endpoints.user_tiles !== null,
199
- "quality-score": this.map?._hasQualityScore?.() || false,
200
- class: "pnx-only-map pnx-print-hidden",
201
- }));
202
- this.grid.appendChild(createWebComp("pnx-widget-maplayers", { slot: "top-right", _parent: this, class: "pnx-only-map pnx-print-hidden" }));
201
+ this.grid.appendChild(createWebComp("pnx-widget-geosearch", {
202
+ slot: this.isWidthSmall() ? "top-right" : "top-left",
203
+ _parent: this,
204
+ class: "pnx-only-map pnx-print-hidden",
205
+ geocoder: this._initParams.getParentPostInit().geocoder,
206
+ }));
207
+
208
+ this.grid.appendChild(createWebComp("pnx-widget-mapfilters", {
209
+ slot: this.isWidthSmall() ? "top-right" : "top-left",
210
+ _parent: this,
211
+ "user-search": this.api._endpoints.user_search !== null && this.api._endpoints.user_tiles !== null,
212
+ "quality-score": this.map?._hasQualityScore?.() || false,
213
+ class: "pnx-only-map pnx-print-hidden",
214
+ }));
215
+
216
+ this.grid.appendChild(createWebComp("pnx-widget-maplayers", { slot: "top-right", _parent: this, class: "pnx-only-map pnx-print-hidden" }));
217
+ }
203
218
  }
204
219
  }
205
220
 
221
+ /** @private */
222
+ disconnectedCallback() {
223
+ super.disconnectedCallback();
224
+ this.map?.destroy();
225
+ }
226
+
206
227
  getClassName() {
207
228
  return "Viewer";
208
229
  }
@@ -321,7 +342,10 @@ export default class Viewer extends PhotoViewer {
321
342
  this._moveChildToGrid();
322
343
 
323
344
  alterViewerState(this, myPostInitParams);
324
- this._handleKeyboardManagement();
345
+
346
+ if(myPostInitParams.keyboardShortcuts) {
347
+ this._handleKeyboardManagement();
348
+ }
325
349
 
326
350
  if(myPostInitParams.picture) {
327
351
  this.psv.addEventListener("picture-loaded", () => {
@@ -367,7 +391,10 @@ export default class Viewer extends PhotoViewer {
367
391
 
368
392
  // Widgets
369
393
  for(let cn of this.grid.childNodes) {
370
- if(cn.getAttribute("slot") !== "bg") {
394
+ if(
395
+ cn.getAttribute("slot") !== "bg"
396
+ && !KEYBOARD_SKIP_FOCUS_WIDGETS.includes(cn.tagName.toLowerCase())
397
+ ) {
371
398
  cn.addEventListener("focusin", () => keytonone());
372
399
  cn.addEventListener("focusout", () => {
373
400
  if(this.popup.getAttribute("visible") === null) {
@@ -471,6 +498,7 @@ export default class Viewer extends PhotoViewer {
471
498
  // Add PSV to mini
472
499
  this.mini.appendChild(this.psvContainer);
473
500
  this.mini.icon = fa(faPanorama);
501
+ if(this._miniPicLegend) { this.mini.appendChild(this._miniPicLegend); }
474
502
 
475
503
  // Hide mini icon if no picture selected
476
504
  if(isNullId(this.picture)) { this.mini.classList.add("pnx-hidden"); }
@@ -488,6 +516,7 @@ export default class Viewer extends PhotoViewer {
488
516
  // Remove PSV from mini
489
517
  if(this.psvContainer.parentNode == this.mini) {
490
518
  this.mini.removeChild(this.psvContainer);
519
+ if(this._miniPicLegend) { this.mini.removeChild(this._miniPicLegend); }
491
520
  }
492
521
 
493
522
  // Add PSV to grid
@@ -1,5 +1,6 @@
1
1
  import { LitElement, html, css } from "lit";
2
2
  import { classMap } from "lit/directives/class-map.js";
3
+ import { onceParentAvailable } from "../../utils/widgets";
3
4
 
4
5
  const OPENNESS_Y_PCT = { "opened": 0, "half-opened": 0.7, "closed": 1 };
5
6
 
@@ -104,7 +105,7 @@ export default class BottomDrawer extends LitElement {
104
105
  drawer.style.height = `${this._drawerHeight}px`;
105
106
  drawer.style.maxHeight = `${this._drawerHeight}px`;
106
107
 
107
- this._parent?.onceReady().then(() => {
108
+ onceParentAvailable(this).then(() => this._parent.onceReady()).then(() => {
108
109
  this._parent.map?.addEventListener("click", () => this.openness = "closed");
109
110
  this._parent.psv?.addEventListener("click", () => this.openness = "closed");
110
111
  });
@@ -33,6 +33,10 @@ export default class Tabs extends LitElement {
33
33
  align-items: stretch;
34
34
  overflow-x: auto;
35
35
  touch-action: pan-x;
36
+ position: sticky;
37
+ top: 0;
38
+ background: white;
39
+ z-index: 125;
36
40
  }
37
41
  nav ::slotted(*) {
38
42
  color: var(--grey-dark);
@@ -3,6 +3,7 @@ import { faSvg, iconify } from "../styles";
3
3
  import { fa, moreIcons } from "../../utils/widgets";
4
4
  import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight";
5
5
  import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
6
+ import { onceParentAvailable } from "../../utils/widgets";
6
7
  import "iconify-icon";
7
8
 
8
9
  /**
@@ -42,15 +43,18 @@ export default class AnnotationsList extends LitElement {
42
43
  super.connectedCallback();
43
44
 
44
45
  this._onPicChange();
45
- this._parent?.psv?.addEventListener("picture-loaded", this._onPicChange.bind(this));
46
-
47
- this._parent?.psv?.addEventListener("annotation-click", e => {
48
- const aPos = this._meta.properties?.annotations?.findIndex(a => a.id === e.detail.annotationId);
49
- if(aPos >= 0) { this._onListItemClick(Object.assign({nb: aPos+1}, this._meta.properties.annotations[aPos])); }
50
- });
51
-
52
- this._parent?.psv?.addEventListener("annotations-unfocused", () => {
53
- this._onListItemClick(null);
46
+
47
+ onceParentAvailable(this).then(() => {
48
+ this._parent.psv?.addEventListener("picture-loaded", this._onPicChange.bind(this));
49
+
50
+ this._parent.psv?.addEventListener("annotation-click", e => {
51
+ const aPos = this._meta.properties?.annotations?.findIndex(a => a.id === e.detail.annotationId);
52
+ if(aPos >= 0) { this._onListItemClick(Object.assign({nb: aPos+1}, this._meta.properties.annotations[aPos])); }
53
+ });
54
+
55
+ this._parent.psv?.addEventListener("annotations-unfocused", () => {
56
+ this._onListItemClick(null);
57
+ });
54
58
  });
55
59
  }
56
60
 
@@ -1,6 +1,8 @@
1
1
  import { LitElement, html, css } from "lit";
2
2
  import BackgroundAerial from "../../img/bg_aerial.jpg";
3
3
  import BackgroundStreets from "../../img/bg_streets.jpg";
4
+ import { onceParentAvailable } from "../../utils/widgets";
5
+
4
6
 
5
7
  /**
6
8
  * Map Background menu allows user to select background.
@@ -60,10 +62,13 @@ export default class MapBackground extends LitElement {
60
62
  /** @private */
61
63
  connectedCallback() {
62
64
  super.connectedCallback();
63
- this._parent?.map?.on("background-changed", e => {
64
- this.bg = e.background;
65
+
66
+ onceParentAvailable(this).then(() => {
67
+ this._parent.map?.on("background-changed", e => {
68
+ this.bg = e.background;
69
+ });
70
+ this.bg = this._parent.map?.getBackground();
65
71
  });
66
- this.bg = this._parent?.map?.getBackground();
67
72
  }
68
73
 
69
74
  /** @private */
@@ -8,6 +8,7 @@ import { faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight";
8
8
  import { faMedal } from "@fortawesome/free-solid-svg-icons/faMedal";
9
9
  import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
10
10
  import { faUser } from "@fortawesome/free-solid-svg-icons/faUser";
11
+ import { onceParentAvailable } from "../../utils/widgets";
11
12
 
12
13
  /**
13
14
  * Map Filters menu allows user to select map data they want displayed.
@@ -180,12 +181,20 @@ export default class MapFilters extends LitElement {
180
181
  }
181
182
 
182
183
  // Map zoom
183
- this._parent?.onceMapReady?.().then(() => {
184
+ onceParentAvailable(this).then(() => this._parent.onceMapReady?.().then(async () => {
184
185
  this._parent.map.on("zoomend", this._onMapZoom.bind(this));
185
186
  this._parent.map.on("filters-changed", this._onParentFilterChange.bind(this));
186
187
  this._onMapZoom();
187
188
  this._onParentFilterChange(this._parent.map._mapFilters);
188
- });
189
+
190
+ // Load default users filter
191
+ const vu = this._parent.map.getVisibleUsers();
192
+ if(vu?.length > 0 && vu[0] != "geovisio") {
193
+ this.user = vu[0];
194
+ const username = await this._parent.api.getUserName(vu[0]);
195
+ if(username) { this.user = username; }
196
+ }
197
+ }));
189
198
  }
190
199
 
191
200
  /**
@@ -5,6 +5,7 @@ import { COLORS } from "../../utils/utils";
5
5
  import { faEarthEurope } from "@fortawesome/free-solid-svg-icons/faEarthEurope";
6
6
  import { faPalette } from "@fortawesome/free-solid-svg-icons/faPalette";
7
7
  import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
8
+ import { onceParentAvailable } from "../../utils/widgets";
8
9
 
9
10
  /**
10
11
  * Map Layers menu allows user to select background and map theme.
@@ -56,10 +57,10 @@ export default class MapLayers extends LitElement {
56
57
  /** @private */
57
58
  connectedCallback() {
58
59
  super.connectedCallback();
59
- this._parent?.onceMapReady?.().then(() => {
60
+ onceParentAvailable(this).then(() => this._parent?.onceMapReady?.().then(() => {
60
61
  this.theme = this._parent.map._mapFilters.theme;
61
62
  this._parent.map.on("filters-changed", e => this.theme = e.theme);
62
- });
63
+ }));
63
64
  }
64
65
 
65
66
  /** @private */
@@ -1,4 +1,5 @@
1
1
  import {LitElement, html, nothing, css} from "lit";
2
+ import {onceParentAvailable} from "../../utils/widgets";
2
3
 
3
4
  /**
4
5
  * Map legend displays information about map sources.
@@ -14,20 +15,50 @@ export default class MapLegend extends LitElement {
14
15
  /** @private */
15
16
  static styles = css`
16
17
  :host {
17
- font-size: 0.9em;
18
+ font-size: 0.7em;
18
19
  }
19
20
  small {
20
21
  font-size: 1em;
21
22
  }
23
+ .maplibregl-ctrl-attrib-inner {
24
+ display: inline-block;
25
+ }
22
26
  `;
23
27
 
28
+ /**
29
+ * Component properties.
30
+ * @memberof Panoramax.components.menus.MapLegend#
31
+ * @type {Object}
32
+ * @property {boolean} [light=false] Lighter version (for iframes)
33
+ */
34
+ static properties = {
35
+ light: {type: Boolean},
36
+ };
37
+
38
+ constructor() {
39
+ super();
40
+ this.light = false;
41
+ }
42
+
43
+ /** @private */
44
+ connectedCallback() {
45
+ super.connectedCallback();
46
+ onceParentAvailable(this).then(() => this.requestUpdate());
47
+ }
48
+
24
49
  /** @private */
25
50
  render() {
51
+ /* eslint-disable indent */
26
52
  const mapAttrib = this._parent?.map?._attribution?._innerContainer;
53
+ const mapLabelParts = this._parent?._t.map.map_data.split("{m}");
27
54
 
28
- return html`
29
- ${mapAttrib && mapAttrib.innerHTML.length > 0 ? html`${this._parent?._t.map.map_data}<br />${mapAttrib}` : nothing}
30
- `;
55
+ return this.light ?
56
+ (mapAttrib && mapAttrib.innerHTML.length > 0 ? mapAttrib : nothing)
57
+ : html`
58
+ ${mapAttrib && mapAttrib.innerHTML.length > 0
59
+ ? html`${mapLabelParts.shift()}${mapAttrib}${mapLabelParts.shift()}`
60
+ : nothing}
61
+ `;
31
62
  }
32
63
  }
33
64
 
@@ -0,0 +1,74 @@
1
+ import { LitElement, nothing, css, html } from "lit";
2
+ import { onceParentAvailable } from "../../utils/widgets";
3
+ import { panel } from "../styles";
4
+
5
+ /**
6
+ * Mini picture legend shows info about picture capture date, when seen in mini component of viewer.
7
+ * @class Panoramax.components.menus.MiniPictureLegend
8
+ * @element pnx-mini-picture-legend
9
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
10
+ * @example
11
+ * ```html
12
+ * <pnx-mini-picture-legend ._parent=${viewer} />
13
+ * ```
14
+ */
15
+ export default class MiniPictureLegend extends LitElement {
16
+ /** @private */
17
+ static styles = [panel, css`
18
+ .pnx-panel {
19
+ bottom: 0;
20
+ right: 0;
21
+ width: unset;
22
+ min-width: unset;
23
+ border-radius: 10px;
24
+ border-top-right-radius: 0;
25
+ border-bottom-left-radius: 0;
26
+ border-right: none;
27
+ border-bottom: none;
28
+ padding: 2px 5px;
29
+ font-size: 0.7em;
30
+ }
31
+ `];
32
+
33
+ /** @private */
34
+ static properties = {
35
+ _caption: {state: true},
36
+ };
37
+
38
+ /** @private */
39
+ connectedCallback() {
40
+ super.connectedCallback();
41
+
42
+ onceParentAvailable(this)
43
+ .then(() => this._parent.onceReady())
44
+ .then(() => {
45
+ this._onPicChange(this._parent.psv.getPictureMetadata());
46
+ this._parent.psv.addEventListener("picture-loaded", () => {
47
+ this._onPicChange(this._parent.psv.getPictureMetadata());
48
+ });
49
+ this._parent.psv.addEventListener("sequence-stopped", () => {
50
+ this._onPicChange(this._parent.psv.getPictureMetadata());
51
+ });
52
+ });
53
+ }
54
+
55
+ /** @private */
56
+ _onPicChange(picMeta) {
57
+ this._caption = picMeta?.caption;
58
+ }
59
+
60
+ /** @private */
61
+ render() {
62
+ /* eslint-disable indent */
63
+ return this._caption?.date ?
64
+ html`<div class="pnx-panel">${
65
+ this._caption.date.toLocaleDateString(
66
+ this._parent?.lang || window.navigator.language,
67
+ { year: "numeric", month: "long", day: "numeric" }
68
+ )
69
+ }</div>`
70
+ : nothing;
71
+ }
72
+ }
73
+
74
+ customElements.define("pnx-mini-picture-legend", MiniPictureLegend);