@panoramax/web-viewer 3.2.3 → 4.0.0-develop-9f9cf858

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 +56 -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,133 @@
1
+ import { LitElement, html, css, nothing } from "lit";
2
+ import { faSvg, titles, select, textarea, input } from "../styles";
3
+ import { fa } from "../../utils/widgets";
4
+ import { faAt } from "@fortawesome/free-solid-svg-icons/faAt";
5
+ import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons/faTriangleExclamation";
6
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons/faCircleInfo";
7
+ import { faCommentDots } from "@fortawesome/free-solid-svg-icons/faCommentDots";
8
+ import { faPaperPlane } from "@fortawesome/free-solid-svg-icons/faPaperPlane";
9
+ import { getUserAccount } from "../../utils/utils";
10
+
11
+ const REPORT_NATURE = [
12
+ "", "blur_missing", "blur_excess", "inappropriate", "privacy",
13
+ "picture_low_quality", "mislocated", "copyright", "other"
14
+ ];
15
+
16
+ /**
17
+ * Report Form displays a form to send issues about pictures.
18
+ * @class Panoramax.components.menus.ReportForm
19
+ * @element pnx-report-form
20
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
21
+ * @example
22
+ * ```html
23
+ * <pnx-report-form ._parent=${viewer} />
24
+ * ```
25
+ */
26
+ export default class ReportForm extends LitElement {
27
+ /** @private */
28
+ static styles = [ titles, faSvg, select, textarea, input, css`
29
+ .group {
30
+ margin-bottom: 10px;
31
+ }
32
+
33
+ .group:not(.group-inline) label {
34
+ margin-bottom: 5px;
35
+ display: inline-block;
36
+ }
37
+ ` ];
38
+
39
+ /** @private */
40
+ static properties = {
41
+ mode: {state: true},
42
+ failure: {state: true},
43
+ };
44
+
45
+ /** @private */
46
+ _onSubmit(e) {
47
+ e.preventDefault();
48
+
49
+ const picMeta = this._parent?.psv?.getPictureMetadata();
50
+ const data = Object.fromEntries(new FormData(e.target));
51
+ const params = {
52
+ issue: data.issue,
53
+ picture_id: data["whole-sequence"] ? null : picMeta?.id,
54
+ reporter_comments: data.comments,
55
+ reporter_email: data.email,
56
+ sequence_id: picMeta?.sequence?.id
57
+ };
58
+
59
+ this.mode = "wait";
60
+
61
+ // Call API
62
+ this._parent?.api.sendReport(params).then(() => {
63
+ this.mode = "success";
64
+ }).catch(e => {
65
+ console.error(e);
66
+ this.mode = "failure";
67
+ this.failure = e;
68
+ });
69
+ }
70
+
71
+ /** @private */
72
+ render() {
73
+ const userAccount = getUserAccount();
74
+
75
+ if(this.mode) {
76
+ return html`
77
+ <h4>${fa(faTriangleExclamation)} ${this._parent?._t.pnx.report}</h4>
78
+ <p>
79
+ ${this.mode === "wait" ? this._parent?._t.pnx.report_wait : nothing}
80
+ ${this.mode === "success" ? this._parent?._t.pnx.report_success : nothing}
81
+ ${this.mode === "failure" ? this._parent?._t.pnx.report_failure.replace("{e}", this.failure) : nothing}
82
+ </p>
83
+ `;
84
+ }
85
+
86
+ return html`
87
+ <h4>${fa(faTriangleExclamation)} ${this._parent?._t.pnx.report}</h4>
88
+
89
+ ${userAccount && this._parent?._t ? html`
90
+ <p>${this._parent?._t.pnx.report_auth.replace("{a}", userAccount.name)}</p>
91
+ ` : nothing}
92
+
93
+ <form @submit=${this._onSubmit.bind(this)}>
94
+ <div class="group">
95
+ <label for="issue">${fa(faCircleInfo)} ${this._parent?._t.pnx.report_nature_label}</label>
96
+ <select name="issue" id="issue" required class="pnx-100w">
97
+ ${REPORT_NATURE.map(nature => html`
98
+ <option
99
+ value=${nature}
100
+ ${nature === "" ? html`disabled selected hidden` : nothing}
101
+ >
102
+ ${this._parent?._t.pnx.report_nature[nature]}
103
+ </option>
104
+ `)}
105
+ </select>
106
+ </div>
107
+
108
+ <div class="group group-inline">
109
+ <input name="whole-sequence" id="whole-sequence" type="checkbox" />
110
+ <label for="whole-sequence">${this._parent?._t.pnx.report_whole_sequence}</label>
111
+ </div>
112
+
113
+ <div class="group">
114
+ <label for="comments">${fa(faCommentDots)} ${this._parent?._t.pnx.report_details}</label>
115
+ <textarea name="comments" id="comments" placeholder=${this._parent?._t.pnx.report_details_placeholder}></textarea>
116
+ </div>
117
+
118
+ ${!userAccount ? html`
119
+ <div class="group">
120
+ <label for="email">${fa(faAt)} ${this._parent?._t.pnx.report_email}</label>
121
+ <input type="email" name="email" id="email" placeholder=${this._parent?._t.pnx.report_email_placeholder} class="pnx-100w" />
122
+ </div>
123
+ `: nothing}
124
+
125
+ <pnx-button type="submit" style="width: 100%">
126
+ ${fa(faPaperPlane)} ${this._parent?._t.pnx.report_submit}
127
+ </pnx-button>
128
+ </form>
129
+ `;
130
+ }
131
+ }
132
+
133
+ customElements.define("pnx-report-form", ReportForm);
@@ -0,0 +1,100 @@
1
+ import { LitElement, css, html } from "lit";
2
+ import { fa } from "../../utils/widgets";
3
+ import { faSvg, textarea, titles, input } from "../styles";
4
+ import { faMap } from "@fortawesome/free-solid-svg-icons/faMap";
5
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons/faCircleInfo";
6
+ import { faShareAlt } from "@fortawesome/free-solid-svg-icons/faShareAlt";
7
+ import { faLink } from "@fortawesome/free-solid-svg-icons/faLink";
8
+
9
+ /**
10
+ * Share Menu displays links for quick picture sharing.
11
+ * @class Panoramax.components.menus.ShareMenu
12
+ * @element pnx-share-menu
13
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
14
+ * @example
15
+ * ```html
16
+ * <pnx-share-menu ._parent=${viewer} />
17
+ * ```
18
+ */
19
+ export default class ShareMenu extends LitElement {
20
+ /** @private */
21
+ static styles = [ faSvg, input, textarea, titles, css`
22
+ div[slot="content"] {
23
+ margin-top: 10px;
24
+ }
25
+ .links {
26
+ display: flex;
27
+ gap: 5px;
28
+ }
29
+ .embed {
30
+ display: flex;
31
+ gap: 5px;
32
+ align-items: center;
33
+ flex-direction: column;
34
+ }
35
+ ` ];
36
+
37
+ /** @private */
38
+ static properties = {
39
+ _url: {state: true},
40
+ };
41
+
42
+ constructor() {
43
+ super();
44
+ this._onUrlChange();
45
+ }
46
+
47
+ /** @private */
48
+ connectedCallback() {
49
+ super.connectedCallback();
50
+ this._parent?.onceReady().then(() => {
51
+ this._onUrlChange();
52
+ this._parent.urlHandler.addEventListener("url-changed", this._onUrlChange.bind(this));
53
+ });
54
+ }
55
+
56
+ /** @private */
57
+ _onUrlChange() {
58
+ const baseUrl = window.location.href.replace(/\/$/, "");
59
+ this._url = this._parent?.urlHandler?.nextShortLink(baseUrl) || baseUrl;
60
+ }
61
+
62
+ /** @private */
63
+ render() {
64
+ const iframe = `<iframe src="${this._url}" style="border: none; width: 500px; height: 300px"></iframe>`;
65
+
66
+ return html`
67
+ <h4>${fa(faShareAlt)} ${this._parent?._t.pnx.share}</h4>
68
+ <pnx-tabs>
69
+ <h4 slot="title">${fa(faLink)} ${this._parent?._t.pnx.share_page}</h4>
70
+ <div slot="content">
71
+ <div class="links">
72
+ <input type="text" readonly value=${this._url} style="flex: 2" />
73
+ <pnx-copy-button ._t=${this._parent?._t} text=${this._url}></pnx-copy-button>
74
+ </div>
75
+ </div>
76
+
77
+ <h4 slot="title">${fa(faMap)} ${this._parent?._t.pnx.share_embed}</h4>
78
+ <div slot="content">
79
+ <div class="embed">
80
+ <pnx-link-button
81
+ href="https://docs.panoramax.fr/web-viewer/03_URL_settings/"
82
+ target="_blank"
83
+ kind="superinline"
84
+ size="sm"
85
+ >
86
+ ${fa(faCircleInfo)} ${this._parent?._t.pnx.share_embed_docs}
87
+ </pnx-link-button>
88
+ <textarea readonly>${iframe}</textarea>
89
+ <pnx-copy-button
90
+ ._t=${this._parent?._t}
91
+ text=${iframe}
92
+ style="width: 100%"
93
+ ></pnx-copy-button>
94
+ </div>
95
+ </div>
96
+ </pnx-tabs>`;
97
+ }
98
+ }
99
+
100
+ customElements.define("pnx-share-menu", ShareMenu);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Complex menus components
3
+ * @module Panoramax:components:menus
4
+ */
5
+
6
+ export {default as MapFilters} from "./MapFilters";
7
+ export {default as MapLayers} from "./MapLayers";
8
+ export {default as MapBackground} from "./MapBackground";
9
+ export {default as PlayerOptions} from "./PlayerOptions";
10
+ export {default as QualityScoreDoc} from "./QualityScoreDoc";
11
+ export {default as ReportForm} from "./ReportForm";
12
+ export {default as Share} from "./Share";
13
+ export {default as PictureLegend} from "./PictureLegend";
14
+ export {default as MapLegend} from "./MapLegend";
15
+ export {default as PictureMetadata} from "./PictureMetadata";
@@ -0,0 +1,383 @@
1
+ import { css } from "lit";
2
+
3
+ /* eslint-disable import/no-unused-modules */
4
+
5
+ // Classic panel
6
+ export const panel = css`
7
+ .pnx-panel {
8
+ position: absolute;
9
+ transition: opacity 0.2s 0.1s;
10
+ border-radius: 25px;
11
+ border: 1px solid var(--widget-border-div);
12
+ background-color: var(--widget-bg);
13
+ color: var(--widget-font);
14
+ min-width: 250px;
15
+ box-sizing: border-box;
16
+ font-family: var(--font-family);
17
+ }
18
+
19
+ .pnx-panel.pnx-hidden {
20
+ opacity: 0;
21
+ display: block !important;
22
+ pointer-events: none;
23
+ }
24
+
25
+ .pnx-panel.pnx-padded {
26
+ padding: 15px;
27
+ }
28
+ `;
29
+
30
+ // Font Awesome SVG
31
+ export const faSvg = css`
32
+ .svg-inline--fa {
33
+ display: var(--fa-display, inline-block);
34
+ height: 1em;
35
+ overflow: visible;
36
+ vertical-align: -0.125em;
37
+ }
38
+ svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
39
+ overflow: visible;
40
+ box-sizing: content-box;
41
+ }
42
+ @keyframes fa-spin {
43
+ from {transform:rotate(0deg);}
44
+ to {transform:rotate(360deg);}
45
+ }
46
+ .fa-spin {
47
+ animation: fa-spin 2s infinite linear;
48
+ }
49
+ `;
50
+
51
+ // Textarea
52
+ export const textarea = css`
53
+ textarea {
54
+ background-color: var(--widget-bg);
55
+ color: var(--widget-font);
56
+ border: 1px solid var(--widget-border-div);
57
+ border-radius: 10px;
58
+ padding: 5px;
59
+ width: 100%;
60
+ box-sizing: border-box;
61
+ font-family: var(--font-family);
62
+ }
63
+ `;
64
+
65
+ // Select
66
+ export const select = css`
67
+ select {
68
+ background-color: var(--widget-bg);
69
+ color: var(--widget-font);
70
+ border: 1px solid var(--widget-border-div);
71
+ border-radius: 20px;
72
+ font-size: 16px;
73
+ padding: 2px 10px;
74
+ font-family: var(--font-family);
75
+ }
76
+
77
+ select.pnx-100w {
78
+ width: 100%;
79
+ box-sizing: border-box;
80
+ }
81
+ `;
82
+
83
+ // Input
84
+ export const input = css`
85
+ input {
86
+ background-color: var(--widget-bg);
87
+ color: var(--widget-font);
88
+ border: 1px solid var(--widget-border-div);
89
+ border-radius: 20px;
90
+ font-size: 16px;
91
+ padding: 2px 10px;
92
+ font-family: var(--font-family);
93
+ }
94
+
95
+ input.pnx-100w {
96
+ width: 100%;
97
+ box-sizing: border-box;
98
+ }
99
+ `;
100
+
101
+ // Buttons
102
+ export const btn = css`
103
+ :host {
104
+ display: inline-flex;
105
+ }
106
+
107
+ /* Common properties */
108
+ .pnx-btn {
109
+ white-space: nowrap;
110
+ font-size: 1em;
111
+ font-family: var(--font-family);
112
+ flex-grow: 1;
113
+ flex-shrink: 1;
114
+ text-align: center;
115
+ padding: 5px;
116
+ font-weight: 600;
117
+ flex-basis: 30%;
118
+ line-height: 18px;
119
+ justify-content: center;
120
+ border-radius: 8px;
121
+ cursor: pointer;
122
+ text-decoration: none;
123
+ display: inline-flex;
124
+ align-items: center;
125
+ gap: 5px;
126
+ position: relative;
127
+ width: 100%;
128
+ height: 100%;
129
+ min-width: 26px;
130
+ }
131
+
132
+ .pnx-btn:disabled { color: var(--widget-bg-inactive); }
133
+
134
+ .pnx-btn.pnx-btn-active,
135
+ .pnx-btn.pnx-btn-active:hover,
136
+ .pnx-btn.pnx-btn-full.pnx-btn-active:hover,
137
+ .pnx-btn.pnx-btn-outline.pnx-btn-active:hover {
138
+ background-color: var(--widget-bg-active);
139
+ border-color: var(--widget-bg-active);
140
+ color: var(--widget-font-active);
141
+ }
142
+
143
+ .pnx-btn .svg-inline--fa,
144
+ .pnx-btn ::slotted(.svg-inline--fa),
145
+ .pnx-btn slot .svg-inline--fa {
146
+ height: 16px;
147
+ }
148
+
149
+ /* Sizing */
150
+ .pnx-btn-sm {
151
+ border-radius: 6px;
152
+ line-height: 12px;
153
+ font-size: 12px;
154
+ min-width: unset;
155
+ }
156
+
157
+ .pnx-btn.pnx-btn-sm .svg-inline--fa,
158
+ .pnx-btn.pnx-btn-sm ::slotted(.svg-inline--fa) {
159
+ height: 12px;
160
+ }
161
+
162
+ .pnx-btn-l {
163
+ border-radius: 12px;
164
+ height: 24px;
165
+ line-height: 24px;
166
+ font-size: 20px;
167
+ min-width: 24px;
168
+ }
169
+
170
+ .pnx-btn-xl {
171
+ border-radius: 20px;
172
+ height: 40px;
173
+ line-height: 40px;
174
+ font-size: 16px;
175
+ font-weight: 500;
176
+ min-width: 40px;
177
+ padding: 0 10px;
178
+ gap: 8px;
179
+ }
180
+
181
+ .pnx-btn.pnx-btn-xl .svg-inline--fa,
182
+ .pnx-btn.pnx-btn-xl ::slotted(.svg-inline--fa) {
183
+ height: 16px;
184
+ }
185
+
186
+ .pnx-btn-xxl {
187
+ border-radius: 28px;
188
+ height: 56px;
189
+ line-height: 56px;
190
+ font-size: 24px;
191
+ min-width: 56px;
192
+ }
193
+
194
+ .pnx-btn.pnx-btn-xxl .svg-inline--fa,
195
+ .pnx-btn.pnx-btn-xxl ::slotted(.svg-inline--fa) {
196
+ height: 24px;
197
+ }
198
+
199
+ /* Fully-filled style */
200
+ .pnx-btn-full {
201
+ background-color: var(--widget-bg-primary);
202
+ color: var(--widget-font-direct);
203
+ border: none;
204
+ }
205
+
206
+ .pnx-btn-full:not(:disabled):hover {
207
+ background-color: var(--widget-bg-primary-hover);
208
+ }
209
+
210
+ /* Outline style */
211
+ .pnx-btn-outline {
212
+ border: 1px solid var(--widget-border-btn);
213
+ color: var(--widget-font-direct);
214
+ background-color: var(--widget-bg);
215
+ }
216
+
217
+ .pnx-btn-outline:not(:disabled):hover {
218
+ background-color: var(--widget-bg-hover);
219
+ }
220
+
221
+ /* Flat style */
222
+ .pnx-btn-flat,
223
+ .pnx-btn-flat.pnx-btn-active,
224
+ .pnx-btn-flat.pnx-btn-active:hover,
225
+ .pnx-btn-flat:not(:disabled):hover {
226
+ border: 1px solid var(--widget-border-div);
227
+ color: var(--widget-font);
228
+ background-color: var(--widget-bg);
229
+ }
230
+
231
+ .pnx-btn-flat:not(:disabled):hover {
232
+ background-color: var(--widget-bg-hover);
233
+ }
234
+
235
+ /* Superflat style */
236
+ .pnx-btn-superflat,
237
+ .pnx-btn-superflat.pnx-btn-active,
238
+ .pnx-btn-superflat.pnx-btn-active:hover,
239
+ .pnx-btn-superflat:not(:disabled):hover {
240
+ border: 1px solid var(--widget-border-div);
241
+ color: var(--widget-font-direct);
242
+ background-color: var(--widget-bg);
243
+ }
244
+
245
+ .pnx-btn-superflat:not(:disabled):hover {
246
+ background-color: var(--widget-bg-hover);
247
+ }
248
+
249
+ /* Inline style */
250
+ .pnx-btn-inline,
251
+ .pnx-btn-inline.pnx-btn-active,
252
+ .pnx-btn-inline.pnx-btn-active:hover,
253
+ .pnx-btn-inline:not(:disabled):hover,
254
+ .pnx-btn-superinline,
255
+ .pnx-btn-superinline.pnx-btn-active,
256
+ .pnx-btn-superinline.pnx-btn-active:hover,
257
+ .pnx-btn-superinline:not(:disabled):hover {
258
+ border: none;
259
+ color: var(--widget-font);
260
+ background: none;
261
+ }
262
+
263
+ .pnx-btn-inline:not(:disabled):hover,
264
+ .pnx-btn-superinline:not(:disabled):hover {
265
+ background-color: var(--widget-bg-hover);
266
+ }
267
+
268
+ /* Superinline style */
269
+ .pnx-btn-superinline,
270
+ .pnx-btn-superinline.pnx-btn-active,
271
+ .pnx-btn-superinline.pnx-btn-active:hover,
272
+ .pnx-btn-superinline:not(:disabled):hover {
273
+ color: var(--widget-font-direct);
274
+ }
275
+ `;
276
+
277
+ // Titles
278
+ export const titles = css`
279
+ h1, h2, h3, h4, h5, h6 {
280
+ font-family: var(--font-family);
281
+ }
282
+
283
+ h3 {
284
+ font-size: 1.1em;
285
+ line-height: 1.1em;
286
+ font-weight: 500;
287
+ margin: 10px 0 10px 0;
288
+ }
289
+
290
+ h4 {
291
+ font-size: 1.0em;
292
+ line-height: 1.0em;
293
+ font-weight: 500;
294
+ margin: 15px 0;
295
+ display: flex;
296
+ align-items: center;
297
+ justify-content: flex-start;
298
+ gap: 5px;
299
+ }
300
+
301
+ h4:first-of-type { margin-top: 0; }
302
+
303
+ h4 > svg.svg-inline--fa {
304
+ height: 18px;
305
+ }
306
+
307
+ h4[slot="title"] {
308
+ margin: 0;
309
+ justify-content: center;
310
+ font-size: 0.8em;
311
+ line-height: 2em;
312
+ padding: 0.5em 0;
313
+ }
314
+ h4[slot="title"] svg.svg-inline--fa {
315
+ height: 14px;
316
+ }
317
+ `;
318
+
319
+ // Active icon badge
320
+ export const activeIcon = css`
321
+ .pnx-active-icon {
322
+ box-sizing: border-box;
323
+ background-color: var(--orange);
324
+ border: 3px solid #fff;
325
+ border-radius: 8px;
326
+ height: 15px;
327
+ left: 20px;
328
+ position: absolute;
329
+ top: 5px;
330
+ width: 15px;
331
+ }
332
+ `;
333
+
334
+ // Placeholder background
335
+ export const placeholder = css`
336
+ @keyframes animatedBackground {
337
+ from {
338
+ background-position: 0 0;
339
+ }
340
+ to {
341
+ background-position: 1000px 0;
342
+ }
343
+ }
344
+
345
+ .pnx-placeholder-loading {
346
+ width: 100px;
347
+ height: 100px;
348
+ background-image: linear-gradient(
349
+ 90deg,
350
+ #e4e4e4 0%,
351
+ #f1f1f1 40%,
352
+ #ededed 60%,
353
+ #e4e4e4 100%
354
+ );
355
+ background-position: 0px 0px;
356
+ background-repeat: repeat;
357
+ animation: animatedBackground 5s linear infinite;
358
+ }
359
+ `;
360
+
361
+ // Expandable block
362
+ export const expandable = css`
363
+ details summary {
364
+ font-size: 1.0em;
365
+ line-height: 1.0em;
366
+ font-weight: 500;
367
+ margin: 15px 0;
368
+ cursor: pointer;
369
+ }
370
+
371
+ details summary svg {
372
+ height: 18px;
373
+ vertical-align: sub;
374
+ margin-right: 2px;
375
+ }
376
+ `;
377
+
378
+ // Print hidden
379
+ export const noprint = css`
380
+ @media print {
381
+ .pnx-print-hidden { display: none !important; }
382
+ }
383
+ `;
@@ -0,0 +1,77 @@
1
+ import { LitElement } from "lit";
2
+ import { btn } from "../styles";
3
+
4
+ /**
5
+ * Button element displays a direct action button.
6
+ * Binds to a HTML button, so you can use any events offered by it.
7
+ * @class Panoramax.components.ui.Button
8
+ * @element pnx-button
9
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
10
+ * @example
11
+ * ```html
12
+ * <pnx-button kind="flat" size="l" @click=${() => alert("click!")}>
13
+ * Click on me
14
+ * </pnx-button>
15
+ * ```
16
+ */
17
+ export default class Button extends LitElement {
18
+ /** @private */
19
+ static styles = btn;
20
+
21
+ /**
22
+ * Component properties.
23
+ * @memberof Panoramax.components.ui.Button#
24
+ * @type {Object}
25
+ * @property {boolean} [active=false] Whether the button is in an active state.
26
+ * @property {string} [kind=full] The style variation of the button (full, outline, flat, superflat, inline, superinline)
27
+ * @property {string} [size=md] The size of the button (sm, md, l, xl, xxl)
28
+ * @property {boolean} [disabled=false] Whether the button is disabled.
29
+ * @property {string} [type] The button type (e.g., 'submit').
30
+ * @property {string} [title] Tooltip text displayed when hovering over the button
31
+ */
32
+ static properties = {
33
+ active: {type: Boolean},
34
+ kind: {type: String},
35
+ size: {type: String},
36
+ disabled: {type: Boolean},
37
+ type: {type: String},
38
+ title: { type: String },
39
+ };
40
+
41
+ constructor() {
42
+ super();
43
+ this.active = false;
44
+ this.disabled = false;
45
+ this.kind = "full";
46
+ this.size = "md";
47
+ }
48
+
49
+ /** @private */
50
+ connectedCallback() {
51
+ super.connectedCallback();
52
+
53
+ if(this.type === "submit") {
54
+ this.addEventListener("click", () => this.closest("FORM")?.requestSubmit());
55
+ }
56
+ }
57
+
58
+ /** @private */
59
+ render() {
60
+ const b = document.createElement("button");
61
+ b.setAttribute("part", "btn");
62
+
63
+ this.constructor.observedAttributes
64
+ .filter(k => this[k] !== undefined && this[k] !== false && !["active", "kind", "size"].includes(k))
65
+ .forEach(k => b.setAttribute(k, this[k]));
66
+
67
+ b.classList.add("pnx-btn", `pnx-btn-${this.kind}`, `pnx-btn-${this.size}`);
68
+ if(this.active) { b.classList.add("pnx-btn-active"); }
69
+
70
+ const slot = document.createElement("slot");
71
+ b.appendChild(slot);
72
+
73
+ return b;
74
+ }
75
+ }
76
+
77
+ customElements.define("pnx-button", Button);