@panoramax/web-viewer 3.2.3 → 4.0.0-develop-39167b4d

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 (255) hide show
  1. package/.gitlab-ci.yml +13 -6
  2. package/CHANGELOG.md +53 -1
  3. package/CODE_OF_CONDUCT.md +1 -1
  4. package/README.md +1 -1
  5. package/build/editor.html +10 -1
  6. package/build/index.css +12 -12
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +2126 -14
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/photo.html +1 -0
  13. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff +0 -0
  14. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff2 +0 -0
  15. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff +0 -0
  16. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff2 +0 -0
  17. package/build/viewer.html +12 -1
  18. package/build/widgets.html +1 -0
  19. package/config/jest/mocks.js +201 -0
  20. package/config/paths.js +2 -0
  21. package/config/webpack.config.js +52 -0
  22. package/docs/03_URL_settings.md +14 -16
  23. package/docs/05_Compatibility.md +59 -76
  24. package/docs/09_Develop.md +46 -11
  25. package/docs/90_Releases.md +2 -2
  26. package/docs/images/class_diagram.drawio +60 -45
  27. package/docs/images/class_diagram.jpg +0 -0
  28. package/docs/images/screenshot.jpg +0 -0
  29. package/docs/index.md +135 -0
  30. package/docs/reference/components/core/Basic.md +196 -0
  31. package/docs/reference/components/core/CoverageMap.md +210 -0
  32. package/docs/reference/components/core/Editor.md +224 -0
  33. package/docs/reference/components/core/PhotoViewer.md +307 -0
  34. package/docs/reference/components/core/Viewer.md +350 -0
  35. package/docs/reference/components/layout/BottomDrawer.md +35 -0
  36. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  37. package/docs/reference/components/layout/Mini.md +45 -0
  38. package/docs/reference/components/layout/Tabs.md +45 -0
  39. package/docs/reference/components/menus/MapBackground.md +32 -0
  40. package/docs/reference/components/menus/MapFilters.md +15 -0
  41. package/docs/reference/components/menus/MapLayers.md +15 -0
  42. package/docs/reference/components/menus/MapLegend.md +15 -0
  43. package/docs/reference/components/menus/PictureLegend.md +16 -0
  44. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  45. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  46. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  47. package/docs/reference/components/menus/ReportForm.md +15 -0
  48. package/docs/reference/components/menus/ShareMenu.md +15 -0
  49. package/docs/reference/components/ui/Button.md +40 -0
  50. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  51. package/docs/reference/components/ui/CopyButton.md +38 -0
  52. package/docs/reference/components/ui/Grade.md +32 -0
  53. package/docs/reference/components/ui/LinkButton.md +45 -0
  54. package/docs/reference/components/ui/ListGroup.md +22 -0
  55. package/docs/reference/components/ui/Loader.md +56 -0
  56. package/docs/reference/components/ui/Map.md +239 -0
  57. package/docs/reference/components/ui/MapMore.md +256 -0
  58. package/docs/reference/components/ui/Photo.md +385 -0
  59. package/docs/reference/components/ui/Popup.md +56 -0
  60. package/docs/reference/components/ui/ProgressBar.md +32 -0
  61. package/docs/reference/components/ui/QualityScore.md +45 -0
  62. package/docs/reference/components/ui/SearchBar.md +63 -0
  63. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  64. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  65. package/docs/reference/components/ui/widgets/Legend.md +49 -0
  66. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  67. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  68. package/docs/reference/components/ui/widgets/OSMEditors.md +15 -0
  69. package/docs/reference/components/ui/widgets/PictureLegendActions.md +32 -0
  70. package/docs/reference/components/ui/widgets/Player.md +33 -0
  71. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  72. package/docs/reference/utils/API.md +334 -0
  73. package/docs/reference/utils/InitParameters.md +68 -0
  74. package/docs/reference/utils/URLHandler.md +107 -0
  75. package/docs/reference.md +79 -0
  76. package/docs/shortcuts.md +11 -0
  77. package/docs/tutorials/aerial_imagery.md +19 -0
  78. package/docs/tutorials/authentication.md +10 -0
  79. package/docs/tutorials/custom_widgets.md +59 -0
  80. package/docs/tutorials/map_style.md +39 -0
  81. package/docs/tutorials/migrate_v4.md +153 -0
  82. package/docs/tutorials/synced_coverage.md +43 -0
  83. package/mkdocs.yml +66 -5
  84. package/package.json +22 -17
  85. package/public/editor.html +21 -29
  86. package/public/index.html +17 -12
  87. package/public/map.html +19 -18
  88. package/public/photo.html +55 -0
  89. package/public/viewer.html +22 -26
  90. package/public/widgets.html +306 -0
  91. package/scripts/doc.js +79 -0
  92. package/src/components/core/Basic.css +48 -0
  93. package/src/components/core/Basic.js +349 -0
  94. package/src/components/core/CoverageMap.css +9 -0
  95. package/src/components/core/CoverageMap.js +139 -0
  96. package/src/components/core/Editor.css +23 -0
  97. package/src/components/core/Editor.js +390 -0
  98. package/src/components/core/PhotoViewer.css +48 -0
  99. package/src/components/core/PhotoViewer.js +499 -0
  100. package/src/components/core/Viewer.css +98 -0
  101. package/src/components/core/Viewer.js +564 -0
  102. package/src/components/core/index.js +12 -0
  103. package/src/components/index.js +13 -0
  104. package/src/components/layout/BottomDrawer.js +257 -0
  105. package/src/components/layout/CorneredGrid.js +112 -0
  106. package/src/components/layout/Mini.js +117 -0
  107. package/src/components/layout/Tabs.js +133 -0
  108. package/src/components/layout/index.js +9 -0
  109. package/src/components/menus/MapBackground.js +106 -0
  110. package/src/components/menus/MapFilters.js +400 -0
  111. package/src/components/menus/MapLayers.js +143 -0
  112. package/src/components/menus/MapLegend.js +34 -0
  113. package/src/components/menus/PictureLegend.js +257 -0
  114. package/src/components/menus/PictureMetadata.js +317 -0
  115. package/src/components/menus/PlayerOptions.js +95 -0
  116. package/src/components/menus/QualityScoreDoc.js +36 -0
  117. package/src/components/menus/ReportForm.js +133 -0
  118. package/src/components/menus/Share.js +100 -0
  119. package/src/components/menus/index.js +15 -0
  120. package/src/components/styles.js +383 -0
  121. package/src/components/ui/Button.js +77 -0
  122. package/src/components/ui/ButtonGroup.css +57 -0
  123. package/src/components/ui/ButtonGroup.js +68 -0
  124. package/src/components/ui/CopyButton.js +106 -0
  125. package/src/components/ui/Grade.js +54 -0
  126. package/src/components/ui/LinkButton.js +67 -0
  127. package/src/components/ui/ListGroup.js +66 -0
  128. package/src/components/ui/Loader.js +203 -0
  129. package/src/components/{Map.css → ui/Map.css} +5 -17
  130. package/src/components/{Map.js → ui/Map.js} +148 -156
  131. package/src/components/ui/MapMore.js +324 -0
  132. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  133. package/src/components/{Photo.js → ui/Photo.js} +313 -101
  134. package/src/components/ui/Popup.js +145 -0
  135. package/src/components/ui/ProgressBar.js +104 -0
  136. package/src/components/ui/QualityScore.js +147 -0
  137. package/src/components/ui/SearchBar.js +367 -0
  138. package/src/components/ui/TogglableGroup.js +157 -0
  139. package/src/components/ui/index.js +22 -0
  140. package/src/components/ui/widgets/GeoSearch.css +21 -0
  141. package/src/components/ui/widgets/GeoSearch.js +139 -0
  142. package/src/components/ui/widgets/Legend.js +113 -0
  143. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  144. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  145. package/src/components/ui/widgets/OSMEditors.js +155 -0
  146. package/src/components/ui/widgets/PictureLegendActions.js +117 -0
  147. package/src/components/ui/widgets/Player.css +7 -0
  148. package/src/components/ui/widgets/Player.js +151 -0
  149. package/src/components/ui/widgets/Zoom.js +82 -0
  150. package/src/components/ui/widgets/index.js +13 -0
  151. package/src/img/loader_base.jpg +0 -0
  152. package/src/img/panoramax.svg +13 -0
  153. package/src/img/switch_big.svg +20 -10
  154. package/src/index.js +7 -9
  155. package/src/translations/br.json +1 -0
  156. package/src/translations/da.json +38 -15
  157. package/src/translations/de.json +5 -3
  158. package/src/translations/en.json +35 -15
  159. package/src/translations/eo.json +38 -15
  160. package/src/translations/es.json +1 -1
  161. package/src/translations/fr.json +36 -16
  162. package/src/translations/hu.json +1 -1
  163. package/src/translations/it.json +39 -16
  164. package/src/translations/ja.json +182 -1
  165. package/src/translations/nl.json +106 -6
  166. package/src/translations/pl.json +1 -1
  167. package/src/translations/sv.json +182 -0
  168. package/src/translations/zh_Hant.json +35 -14
  169. package/src/utils/API.js +109 -49
  170. package/src/utils/InitParameters.js +388 -0
  171. package/src/utils/PhotoAdapter.js +1 -0
  172. package/src/utils/URLHandler.js +362 -0
  173. package/src/utils/geocoder.js +152 -0
  174. package/src/utils/{I18n.js → i18n.js} +7 -3
  175. package/src/utils/index.js +11 -0
  176. package/src/utils/{Map.js → map.js} +256 -77
  177. package/src/utils/picture.js +442 -0
  178. package/src/utils/utils.js +324 -0
  179. package/src/utils/widgets.js +55 -0
  180. package/tests/components/core/Basic.test.js +121 -0
  181. package/tests/components/core/BasicMock.js +25 -0
  182. package/tests/components/core/CoverageMap.test.js +20 -0
  183. package/tests/components/core/Editor.test.js +20 -0
  184. package/tests/components/core/PhotoViewer.test.js +57 -0
  185. package/tests/components/core/Viewer.test.js +84 -0
  186. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +73 -0
  187. package/tests/components/core/__snapshots__/Viewer.test.js.snap +145 -0
  188. package/tests/components/ui/CopyButton.test.js +52 -0
  189. package/tests/components/ui/Loader.test.js +55 -0
  190. package/tests/components/{Map.test.js → ui/Map.test.js} +73 -61
  191. package/tests/components/{Photo.test.js → ui/Photo.test.js} +97 -63
  192. package/tests/components/ui/Popup.test.js +26 -0
  193. package/tests/components/ui/QualityScore.test.js +18 -0
  194. package/tests/components/ui/SearchBar.test.js +110 -0
  195. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +33 -0
  196. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  197. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  198. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +70 -6
  199. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  200. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  201. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  202. package/tests/utils/API.test.js +83 -83
  203. package/tests/utils/InitParameters.test.js +499 -0
  204. package/tests/utils/URLHandler.test.js +401 -0
  205. package/tests/utils/__snapshots__/API.test.js.snap +10 -0
  206. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  207. package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +1 -1
  208. package/tests/utils/__snapshots__/map.test.js.snap +11 -0
  209. package/tests/utils/__snapshots__/picture.test.js.snap +327 -0
  210. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  211. package/tests/utils/geocoder.test.js +37 -0
  212. package/tests/utils/{I18n.test.js → i18n.test.js} +8 -8
  213. package/tests/utils/map.test.js +126 -0
  214. package/tests/utils/picture.test.js +745 -0
  215. package/tests/utils/utils.test.js +288 -0
  216. package/tests/utils/widgets.test.js +31 -0
  217. package/docs/01_Start.md +0 -149
  218. package/docs/02_Usage.md +0 -831
  219. package/docs/04_Advanced_examples.md +0 -216
  220. package/src/Editor.css +0 -37
  221. package/src/Editor.js +0 -361
  222. package/src/StandaloneMap.js +0 -114
  223. package/src/Viewer.css +0 -203
  224. package/src/Viewer.js +0 -1246
  225. package/src/components/CoreView.css +0 -70
  226. package/src/components/CoreView.js +0 -175
  227. package/src/components/Loader.css +0 -74
  228. package/src/components/Loader.js +0 -120
  229. package/src/img/loader_hd.jpg +0 -0
  230. package/src/utils/Exif.js +0 -193
  231. package/src/utils/Utils.js +0 -631
  232. package/src/utils/Widgets.js +0 -562
  233. package/src/viewer/URLHash.js +0 -469
  234. package/src/viewer/Widgets.css +0 -880
  235. package/src/viewer/Widgets.js +0 -1470
  236. package/tests/Editor.test.js +0 -126
  237. package/tests/StandaloneMap.test.js +0 -45
  238. package/tests/Viewer.test.js +0 -366
  239. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  240. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  241. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  242. package/tests/components/CoreView.test.js +0 -92
  243. package/tests/components/Loader.test.js +0 -38
  244. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  245. package/tests/utils/Exif.test.js +0 -124
  246. package/tests/utils/Map.test.js +0 -113
  247. package/tests/utils/Utils.test.js +0 -300
  248. package/tests/utils/Widgets.test.js +0 -107
  249. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  250. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  251. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  252. package/tests/viewer/URLHash.test.js +0 -559
  253. package/tests/viewer/Widgets.test.js +0 -127
  254. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  255. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
@@ -0,0 +1,57 @@
1
+ pnx-button-group > pnx-button {
2
+ display: inline-flex;
3
+ }
4
+
5
+ pnx-button-group > pnx-button::part(btn) {
6
+ height: unset;
7
+ }
8
+
9
+ /* Togglable in group */
10
+ pnx-button-group > pnx-togglable-group > pnx-button {
11
+ width: 100%;
12
+ height: 100%;
13
+ }
14
+
15
+ /* Row */
16
+ pnx-button-group[dir="row"] > :not(:first-child):not(:last-child)::part(btn),
17
+ pnx-button-group[dir="row"] > :not(:first-child):not(:last-child) > ::part(btn) {
18
+ border-radius: 0;
19
+ border-left: none;
20
+ border-right: none;
21
+ }
22
+
23
+ pnx-button-group[dir="row"] > :first-child::part(btn),
24
+ pnx-button-group[dir="row"] > :first-child > ::part(btn) {
25
+ border-top-right-radius: 0;
26
+ border-bottom-right-radius: 0;
27
+ border-right: none;
28
+ }
29
+
30
+ pnx-button-group[dir="row"] > :last-child::part(btn),
31
+ pnx-button-group[dir="row"] > :last-child > ::part(btn) {
32
+ border-top-left-radius: 0;
33
+ border-bottom-left-radius: 0;
34
+ border-left: none;
35
+ }
36
+
37
+ /* Column */
38
+ pnx-button-group[dir="column"] > :not(:first-child):not(:last-child)::part(btn),
39
+ pnx-button-group[dir="column"] > :not(:first-child):not(:last-child) > ::part(btn) {
40
+ border-radius: 0;
41
+ border-top: none;
42
+ border-bottom: none;
43
+ }
44
+
45
+ pnx-button-group[dir="column"] > :first-child::part(btn),
46
+ pnx-button-group[dir="column"] > :first-child > ::part(btn) {
47
+ border-bottom-right-radius: 0;
48
+ border-bottom-left-radius: 0;
49
+ border-bottom: none;
50
+ }
51
+
52
+ pnx-button-group[dir="column"] > :last-child::part(btn),
53
+ pnx-button-group[dir="column"] > :last-child > ::part(btn) {
54
+ border-top-left-radius: 0;
55
+ border-top-right-radius: 0;
56
+ border-top: none;
57
+ }
@@ -0,0 +1,68 @@
1
+ import { LitElement, css, html } from "lit";
2
+ import "./ButtonGroup.css";
3
+
4
+ /**
5
+ * Button Group element allows to merge many button in a single bar.
6
+ * @class Panoramax.components.ui.ButtonGroup
7
+ * @element pnx-button-group
8
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
9
+ * @example
10
+ * ```html
11
+ * <pnx-button-group id="pnx-widget-player" dir="row" size="xl" class="pnx-print-hidden">
12
+ * <pnx-button>B1</pnx-button>
13
+ * <pnx-button>B2</pnx-button>
14
+ * </pnx-button-group>
15
+ * ```
16
+ */
17
+ export default class ButtonGroup extends LitElement {
18
+ /** @private */
19
+ static styles = css`
20
+ div {
21
+ display: flex;
22
+ flex-wrap: nowrap;
23
+ align-items: stretch;
24
+ align-content: stretch;
25
+ justify-content: center;
26
+ }
27
+
28
+ div.row { flex-direction: row; }
29
+ div.column { flex-direction: column; }
30
+
31
+ div.xl { line-height: 38px; font-size: 20px; }
32
+ div.row.xl { height: 38px; }
33
+ div.column.xl { width: 38px; }
34
+
35
+ div.row ::slotted(*) { height: 100%; min-width: 24px; }
36
+ div.column ::slotted(*) { width: 100%; min-height: 24px; }
37
+
38
+ div.row.xl ::slotted(*) { min-width: 38px; }
39
+ div.column.xl ::slotted(*) { min-height: 38px; }
40
+ `;
41
+
42
+ /**
43
+ * Component properties.
44
+ * @memberof Panoramax.components.ui.ButtonGroup#
45
+ * @type {Object}
46
+ * @property {string} [dir] Group direction (row, column)
47
+ * @property {string} [size] Group size (md, xl)
48
+ */
49
+ static properties = {
50
+ dir: {type: String},
51
+ size: {type: String},
52
+ };
53
+
54
+ constructor() {
55
+ super();
56
+ this.dir = "row";
57
+ this.size = "md";
58
+ }
59
+
60
+ /** @private */
61
+ render() {
62
+ return html`<div class="${this.dir} ${this.size}">
63
+ <slot></slot>
64
+ </div>`;
65
+ }
66
+ }
67
+
68
+ customElements.define("pnx-button-group", ButtonGroup);
@@ -0,0 +1,106 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { fa } from "../../utils/widgets";
3
+ import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
4
+ import { faCopy } from "@fortawesome/free-solid-svg-icons/faCopy";
5
+ import { btn, faSvg } from "../styles";
6
+ import { classMap } from "lit/directives/class-map.js";
7
+
8
+ /**
9
+ * Copy Button element allows top copy in clipboard some text.
10
+ * @class Panoramax.components.ui.CopyButton
11
+ * @element pnx-copy-button
12
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
13
+ * @example
14
+ * ```html
15
+ * <pnx-copy-button text="content to copy" ._t=${viewer._t}>
16
+ * Copy me !
17
+ * </pnx-copy-button>
18
+ * ```
19
+ */
20
+ export default class CopyButton extends LitElement {
21
+ /** @private */
22
+ static styles = [faSvg, btn, css`
23
+ .pnx-btn-unstyled {
24
+ border: none;
25
+ background: none;
26
+ font-family: var(--font-family);
27
+ font-size: 1em;
28
+ color: var(--widget-font);
29
+ cursor: pointer;
30
+ padding: 0;
31
+ margin: 0;
32
+ }
33
+ `];
34
+
35
+ /**
36
+ * Component properties.
37
+ * @memberof Panoramax.components.ui.CopyButton#
38
+ * @type {Object}
39
+ * @property {string} [text] Text to copy in clipboard on click (use either this parameter or input, not both)
40
+ * @property {input} [input] ID of a HTML input field to copy content from in clipboard (use either this parameter or text, not both)
41
+ * @property {string} [kind=full] The style variation of the button (full, outline, flat, superflat, inline, superinline)
42
+ * @property {string} [size=md] The size of the button (sm, md, l, xl, xxl)
43
+ * @property {boolean} [unstyled=false] Disable all styling (for list group integration)
44
+ */
45
+ static properties = {
46
+ text: {type: String},
47
+ input: {type: String},
48
+ kind: {type: String},
49
+ size: {type: String},
50
+ unstyled: {type: Boolean},
51
+ _active: {state: true, type: Boolean},
52
+ };
53
+
54
+ constructor() {
55
+ super();
56
+ this.data = "";
57
+ this.input = "";
58
+ this.unstyled = false;
59
+ this.kind = "full";
60
+ this.size = "md";
61
+ this._active = false;
62
+ this.addEventListener("click", this._onClick);
63
+ }
64
+
65
+ /** @private */
66
+ _onClick() {
67
+ let textToCopy;
68
+ if(this.input !== "") {
69
+ const inputField = document.getElementById(this.input);
70
+ textToCopy = inputField.innerText || inputField.value;
71
+ }
72
+ else if(this.text !== "") {
73
+ textToCopy = this.text;
74
+ }
75
+
76
+ if(!navigator?.clipboard) {
77
+ alert("Clipboard is not available");
78
+ }
79
+ else {
80
+ navigator.clipboard.writeText(textToCopy);
81
+ this._active = true;
82
+ setTimeout(() => this._active = false, 2000);
83
+ }
84
+ }
85
+
86
+ /** @private */
87
+ render() {
88
+ /* eslint-disable indent */
89
+ const classes = {
90
+ "pnx-btn": !this.unstyled,
91
+ "pnx-btn-full": !this.unstyled,
92
+ "pnx-btn-active": !this.unstyled && this._active,
93
+ "pnx-btn-unstyled": this.unstyled,
94
+ [`pnx-btn-${this.kind}`]: !this.unstyled,
95
+ [`pnx-btn-${this.size}`]: !this.unstyled,
96
+ };
97
+ return html`<button class=${classMap(classes)} part="btn">
98
+ ${this._active ?
99
+ html`${this._t?.pnx.copied || ""} ${fa(faCheck)}` :
100
+ html`<slot>${fa(faCopy)} ${this._t?.pnx.copy || ""}</slot>`
101
+ }
102
+ </button>`;
103
+ }
104
+ }
105
+
106
+ customElements.define("pnx-copy-button", CopyButton);
@@ -0,0 +1,54 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { fa } from "../../utils/widgets";
3
+ import { faStar } from "@fortawesome/free-solid-svg-icons/faStar";
4
+ import { faStar as farStar } from "@fortawesome/free-regular-svg-icons/faStar";
5
+ import { faSvg } from "../styles";
6
+
7
+ /**
8
+ * Grade element displays a 5-star rating.
9
+ * @class Panoramax.components.ui.Grade
10
+ * @element pnx-grade
11
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
12
+ * @example
13
+ * ```html
14
+ * <pnx-grade stars="5" .t=${viewer._t} />
15
+ * ```
16
+ */
17
+ export default class Grade extends LitElement {
18
+ /** @private */
19
+ static styles = [ faSvg, css`
20
+ span { color: var(--orange); }
21
+ `];
22
+
23
+ /**
24
+ * Component properties.
25
+ * @memberof Panoramax.components.ui.Grade#
26
+ * @type {Object}
27
+ * @property {number} [stars=0] 1 to 5 grade (or 0 for unknown value)
28
+ */
29
+ static properties = {
30
+ stars: {type: Number},
31
+ };
32
+
33
+ constructor() {
34
+ super();
35
+ this.stars = 0;
36
+ }
37
+
38
+ /** @private */
39
+ render() {
40
+ const nbStars = this.stars || 0;
41
+ const fastars = [];
42
+ for(let i=1; i <= nbStars; i++) {
43
+ fastars.push(fa(faStar));
44
+ }
45
+ for(let i=nbStars+1; i <= 5; i++) {
46
+ fastars.push(fa(farStar));
47
+ }
48
+ return html`<span>
49
+ ${fastars}
50
+ </span> (${this.stars ? this.stars+"/5" : this._t?.pnx.metadata_quality_missing || "?"})`;
51
+ }
52
+ }
53
+
54
+ customElements.define("pnx-grade", Grade);
@@ -0,0 +1,67 @@
1
+ import { LitElement } from "lit";
2
+ import { btn } from "../styles";
3
+
4
+ /**
5
+ * Link Button element displays a HTML `<a>` anchor with a button style.
6
+ * @class Panoramax.components.ui.LinkButton
7
+ * @element pnx-link-button
8
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
9
+ * @example
10
+ * ```html
11
+ * <pnx-link-button
12
+ * title="Redirect to other website"
13
+ * kind="outline"
14
+ * href="https://panoramax.fr"
15
+ * target="_blank"
16
+ * >
17
+ * Click to go on Panoramax
18
+ * </pnx-link-button>
19
+ * ```
20
+ */
21
+ export default class LinkButton extends LitElement {
22
+ /** @private */
23
+ static styles = btn;
24
+
25
+ /**
26
+ * Component properties.
27
+ * @memberof Panoramax.components.ui.LinkButton#
28
+ * @type {Object}
29
+ * @property {string} [href] The URL the button should navigate to when clicked
30
+ * @property {string} [target] Specifies where to open the linked document (e.g., '_blank')
31
+ * @property {string} [title] Tooltip text displayed when hovering over the button
32
+ * @property {string} [download] Indicates if the linked resource should be downloaded
33
+ * @property {string} [class] Custom CSS class for additional styling
34
+ * @property {string} [kind=full] The style variation of the button (full, outline, flat, superflat)
35
+ * @property {string} [size=md] The size of the button (sm, md, l, xl, xxl)
36
+ */
37
+ static properties = {
38
+ href: { type: String },
39
+ target: { type: String },
40
+ title: { type: String },
41
+ download: { type: String },
42
+ class: { type: String },
43
+ kind: {type: String},
44
+ size: {type: String},
45
+ };
46
+
47
+ constructor() {
48
+ super();
49
+ this.kind = "full";
50
+ this.size = "md";
51
+ }
52
+
53
+ /** @private */
54
+ render() {
55
+ const a = document.createElement("a");
56
+ a.setAttribute("part", "btn");
57
+ this.constructor.observedAttributes
58
+ .filter(k => this[k] !== undefined)
59
+ .forEach(k => a.setAttribute(k, this[k]));
60
+ a.classList.add("pnx-btn", `pnx-btn-${this.kind}`, `pnx-btn-${this.size}`);
61
+ const slot = document.createElement("slot");
62
+ a.appendChild(slot);
63
+ return a;
64
+ }
65
+ }
66
+
67
+ customElements.define("pnx-link-button", LinkButton);
@@ -0,0 +1,66 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { panel } from "../styles";
3
+
4
+ /**
5
+ * List Group element displays a menu having a list of rapid actions (links, buttons).
6
+ *
7
+ * Note that you may only want to use basic HTML elements (`a`, `button`) instead of Panoramax ones.
8
+ * The list group overrides style, so using `pnx-*` component may conflict on styling.
9
+ * @class Panoramax.components.ui.ListGroup
10
+ * @element pnx-list-group
11
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
12
+ * @slot `default` Any element you want to add in list.
13
+ * @example
14
+ * ```html
15
+ * <pnx-list-group>
16
+ * <a href="https://web.site/">First link</a>
17
+ * <button>Second button</button>
18
+ * </pnx-list-group>
19
+ * ```
20
+ */
21
+ export default class ListGroup extends LitElement {
22
+ /** @private */
23
+ static styles = [ panel, css`
24
+ :host ::slotted(*) {
25
+ text-decoration: none;
26
+ border: none;
27
+ border-bottom: 1px solid var(--widget-border-div);
28
+ background: none;
29
+ display: block;
30
+ width: 100%;
31
+ color: var(--widget-font);
32
+ font-family: var(--font-family);
33
+ cursor: pointer;
34
+ font-size: 1em;
35
+ font-weight: 400;
36
+ line-height: 18px;
37
+ padding: 5px 10px;
38
+ min-width: 150px;
39
+ width: 100%;
40
+ text-align: left;
41
+ box-sizing: border-box;
42
+ }
43
+
44
+ :host ::slotted(*:hover) {
45
+ background-color: var(--widget-bg-hover);
46
+ }
47
+
48
+ :host ::slotted(*:first-child) {
49
+ border-top-left-radius: 5px;
50
+ border-top-right-radius: 5px;
51
+ }
52
+
53
+ :host ::slotted(*:last-child) {
54
+ border: none;
55
+ border-bottom-left-radius: 5px;
56
+ border-bottom-right-radius: 5px;
57
+ }
58
+ ` ];
59
+
60
+ /** @private */
61
+ render() {
62
+ return html`<slot></slot>`;
63
+ }
64
+ }
65
+
66
+ customElements.define("pnx-list-group", ListGroup);
@@ -0,0 +1,203 @@
1
+ import { LitElement, html, css, unsafeCSS, nothing } from "lit";
2
+ import LogoDead from "../../img/logo_dead.svg";
3
+ import LoaderBg from "../../img/loader_base.jpg";
4
+
5
+ /**
6
+ * Loader component display a full page covering for user waiting.
7
+ * @class Panoramax.components.ui.Loader
8
+ * @element pnx-loader
9
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
10
+ * @example
11
+ * ```html
12
+ * <pnx-loader ._parent=${this.viewer} />
13
+ * ```
14
+ */
15
+ export default class Loader extends LitElement {
16
+ /** @private */
17
+ static styles = css`
18
+ :host {
19
+ position: absolute;
20
+ inset: 0;
21
+ display: flex;
22
+ flex-direction: column;
23
+ justify-content: center;
24
+ gap: 10px;
25
+ align-items: center;
26
+ background-image: url('${unsafeCSS(LoaderBg)}');
27
+ background-repeat: no-repeat;
28
+ background-size: cover;
29
+ background-position: center;
30
+ z-index: 200;
31
+ font-family: var(--font-family);
32
+ font-weight: 550;
33
+ color: var(--black);
34
+ font-size: 1.4em;
35
+ text-align: center;
36
+ visibility: hidden;
37
+ opacity: 0;
38
+ }
39
+ :host(*[visible]) {
40
+ visibility: visible;
41
+ opacity: 1;
42
+ }
43
+
44
+ div.label {
45
+ background-color: rgba(255,255,255,0.5);
46
+ box-shadow: white 0 0 10px;
47
+ padding: 3px 10px;
48
+ border-radius: 50px;
49
+ }
50
+ /* Logo */
51
+ img.logo-dead { width: 100px; }
52
+ `;
53
+
54
+ /**
55
+ * Component properties.
56
+ * @memberof Panoramax.components.ui.Loader#
57
+ * @type {Object}
58
+ * @property {boolean} [visible=true] Is the loader visible to user ?
59
+ * @property {boolean} [no-label=false] Set to true to avoid loading label display
60
+ * @property {number} [value] Progress bar percentage (0-100)
61
+ */
62
+ static properties = {
63
+ _mode: {state: true},
64
+ _label: {state: true},
65
+ _isLabelFun: {state: true},
66
+ visible: {type: Boolean, reflect: true},
67
+ "no-label": {type: Boolean},
68
+ value: {type: Number},
69
+ };
70
+
71
+ constructor() {
72
+ super();
73
+ this.visible = true;
74
+ this["no-label"] = false;
75
+ this._mode = "loading";
76
+ this._isLabelFun = false;
77
+ this.value = -1;
78
+ }
79
+
80
+ /** @private */
81
+ connectedCallback() {
82
+ super.connectedCallback();
83
+ this._nextLabel();
84
+ }
85
+
86
+ /**
87
+ * Is the loader currently visible ?
88
+ * @returns {boolean} True if visible
89
+ * @memberof Panoramax.components.ui.Loader#
90
+ */
91
+ isVisible() {
92
+ return this.visible;
93
+ }
94
+
95
+ /**
96
+ * Dismiss loader, or show error
97
+ * @param {object} [err] Optional error object to show in browser console
98
+ * @param {str} [errMeaningful] Optional error message to show to user
99
+ * @param {fct} [next] Optional function to run after loader dismiss
100
+ * @memberof Panoramax.components.ui.Loader#
101
+ */
102
+ dismiss(err = null, errMeaningful = null, next = null) {
103
+ clearTimeout(this._loaderLabelChanger);
104
+
105
+ if(!err) {
106
+ this.value = 100;
107
+ this._mode = "done";
108
+ this.visible = false;
109
+ this.style.transition = "all 0.5s";
110
+ setTimeout(() => this.parentNode.removeChild(this), 2000);
111
+
112
+ /**
113
+ * Event when component is ready to use.
114
+ * This happens when loader screen disappear, with picture and map loaded.
115
+ *
116
+ * To follow more precisely loading steps, you can also watch for sub-components `ready` events.
117
+ * ```js
118
+ * // Watch API-readiness
119
+ * viewer.addEventListener("api:ready", ...); // From parent
120
+ * viewer.api.addEventListener("ready", ...); // Or on sub-component
121
+ * ```
122
+ * @event Panoramax.components.core.Basic#ready
123
+ * @type {CustomEvent}
124
+ */
125
+ const readyEvt = new CustomEvent("ready");
126
+ this._parent.dispatchEvent(readyEvt);
127
+
128
+ if(next) { next(); }
129
+ }
130
+ else {
131
+ if(err !== true) { console.error(err); }
132
+
133
+ let errHtml = [ this._parent?._t.pnx.error, html`<br />` ];
134
+
135
+ if(errMeaningful) { errHtml.push(errMeaningful, html`<br />`); }
136
+
137
+ if(next) {
138
+ errHtml.push(html`<pnx-button kind="full">${this._parent?._t.pnx.error_click}</pnx-button>`);
139
+ this.addEventListener("click", next);
140
+ }
141
+ else { errHtml.push(html`<small>${this._parent?._t.pnx.error_retry}</small>`); }
142
+
143
+ this._mode = "error";
144
+ this._label = errHtml;
145
+
146
+ const errLabel = errMeaningful || "Panoramax JS had a blocking exception";
147
+
148
+ /**
149
+ * Event for viewer failing to initially load.
150
+ *
151
+ * To follow more precisely loading failures, you can also watch for sub-components `broken` events.
152
+ * ```js
153
+ * // Watch API breaks
154
+ * viewer.addEventListener("api:broken", ...); // From parent
155
+ * viewer.api.addEventListener("broken", ...); // Or on sub-component
156
+ * ```
157
+ * @event Panoramax.components.core.Basic#broken
158
+ * @type {CustomEvent}
159
+ * @property {string} detail.error The user-friendly error message to display
160
+ */
161
+ const brokenEvt = new CustomEvent("broken", {
162
+ detail: { error: errLabel }
163
+ });
164
+ this._parent.dispatchEvent(brokenEvt);
165
+
166
+ // Throw error
167
+ throw new Error(errLabel);
168
+ }
169
+ }
170
+
171
+ /** @private */
172
+ _nextLabel() {
173
+ if(!this._isLabelFun) {
174
+ this._label = this._parent?._t.pnx.loading_labels_serious[
175
+ Math.floor(Math.random() * this._parent?._t.pnx.loading_labels_serious.length)
176
+ ];
177
+ this._isLabelFun = true;
178
+ }
179
+ else {
180
+ this._label = this._parent?._t.pnx.loading_labels_fun[
181
+ Math.floor(Math.random() * this._parent?._t.pnx.loading_labels_fun.length)
182
+ ];
183
+ }
184
+ this._loaderLabelChanger = setTimeout(this._nextLabel.bind(this), 500 + Math.random() * 1000);
185
+ }
186
+
187
+ /** @private */
188
+ render() {
189
+ if(this._mode == "error") {
190
+ return html`
191
+ <img class="logo-dead" src=${LogoDead} alt="" title=${this._parent?._t.map.loading} />
192
+ ${this._label}
193
+ `;
194
+ }
195
+
196
+ return html`
197
+ <pnx-progress-bar .value=${this.value}></pnx-progress-bar>
198
+ ${this["no-label"] ? nothing : html`<div class="label">${this._label}</div>`}
199
+ `;
200
+ }
201
+ }
202
+
203
+ customElements.define("pnx-loader", Loader);
@@ -1,17 +1,10 @@
1
- /* Force maplibre to fill all available space */
2
- .gvs-map.maplibregl-map {
3
- width: 100%;
4
- height: 100%;
5
- background-color: white;
6
- }
7
-
8
1
  /* Picture thumbnail on map */
9
2
  .maplibregl-popup-content {
10
3
  padding: 5px !important;
11
4
  position: relative;
12
5
  }
13
6
 
14
- .gvs-map-thumb {
7
+ .pnx-map-thumb {
15
8
  display: inline-block;
16
9
  text-align: center;
17
10
  vertical-align: middle;
@@ -24,7 +17,7 @@
24
17
  to { transform: rotate(360deg); }
25
18
  }
26
19
 
27
- .gvs-map-thumb-loader {
20
+ .pnx-map-thumb-loader {
28
21
  background-color: rgb(230,230,230);
29
22
  border-radius: 65px;
30
23
  max-height: 60px;
@@ -32,7 +25,7 @@
32
25
  animation: rotating 2s linear infinite;
33
26
  }
34
27
 
35
- .gvs-map-thumb-legend {
28
+ .pnx-map-thumb-legend {
36
29
  display: block;
37
30
  position: absolute;
38
31
  bottom: 5px;
@@ -47,19 +40,14 @@
47
40
  padding: 0;
48
41
  }
49
42
 
50
- /* Max size for geocoder search bar */
51
- .maplibregl-ctrl-geocoder {
52
- max-width: 60%;
53
- }
54
-
55
43
  .maplibregl-marker {
56
44
  width: 60px;
57
45
  }
58
46
 
59
47
  /* Resize canvas for print */
60
48
  @media print {
61
- .gvs-map.maplibregl-map canvas {
49
+ .pnx-map.maplibregl-map .maplibregl-canvas-container {
62
50
  width: 100% !important;
63
- height: 100% !important;
51
+ height: unset !important;
64
52
  }
65
53
  }