@panoramax/web-viewer 3.2.3-develop-d7e5a16d → 3.2.3-develop-6257391e

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 (221) hide show
  1. package/.gitlab-ci.yml +3 -0
  2. package/CHANGELOG.md +19 -0
  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 +2 -2
  7. package/build/index.css.map +1 -1
  8. package/build/index.html +1 -1
  9. package/build/index.js +1682 -5
  10. package/build/index.js.map +1 -1
  11. package/build/map.html +1 -1
  12. package/build/viewer.html +10 -1
  13. package/build/widgets.html +1 -0
  14. package/config/jest/mocks.js +172 -0
  15. package/config/paths.js +1 -0
  16. package/config/webpack.config.js +26 -0
  17. package/docs/03_URL_settings.md +3 -11
  18. package/docs/05_Compatibility.md +59 -76
  19. package/docs/09_Develop.md +30 -11
  20. package/docs/90_Releases.md +2 -2
  21. package/docs/images/class_diagram.drawio +28 -28
  22. package/docs/images/class_diagram.jpg +0 -0
  23. package/docs/index.md +112 -0
  24. package/docs/reference/components/core/Basic.md +153 -0
  25. package/docs/reference/components/core/CoverageMap.md +160 -0
  26. package/docs/reference/components/core/Editor.md +172 -0
  27. package/docs/reference/components/core/Viewer.md +288 -0
  28. package/docs/reference/components/layout/CorneredGrid.md +29 -0
  29. package/docs/reference/components/layout/Mini.md +45 -0
  30. package/docs/reference/components/menus/MapBackground.md +32 -0
  31. package/docs/reference/components/menus/MapFilters.md +15 -0
  32. package/docs/reference/components/menus/MapLayers.md +15 -0
  33. package/docs/reference/components/menus/MapLegend.md +15 -0
  34. package/docs/reference/components/menus/PictureLegend.md +15 -0
  35. package/docs/reference/components/menus/PictureMetadata.md +15 -0
  36. package/docs/reference/components/menus/PlayerOptions.md +15 -0
  37. package/docs/reference/components/menus/QualityScoreDoc.md +15 -0
  38. package/docs/reference/components/menus/ReportForm.md +15 -0
  39. package/docs/reference/components/menus/ShareMenu.md +15 -0
  40. package/docs/reference/components/ui/Button.md +39 -0
  41. package/docs/reference/components/ui/ButtonGroup.md +36 -0
  42. package/docs/reference/components/ui/CopyButton.md +35 -0
  43. package/docs/reference/components/ui/Grade.md +32 -0
  44. package/docs/reference/components/ui/LinkButton.md +44 -0
  45. package/docs/reference/components/ui/Loader.md +54 -0
  46. package/docs/reference/components/ui/Map.md +214 -0
  47. package/docs/reference/components/ui/MapMore.md +233 -0
  48. package/docs/reference/components/ui/Photo.md +369 -0
  49. package/docs/reference/components/ui/Popup.md +56 -0
  50. package/docs/reference/components/ui/QualityScore.md +45 -0
  51. package/docs/reference/components/ui/SearchBar.md +63 -0
  52. package/docs/reference/components/ui/TogglableGroup.md +39 -0
  53. package/docs/reference/components/ui/widgets/GeoSearch.md +32 -0
  54. package/docs/reference/components/ui/widgets/Legend.md +32 -0
  55. package/docs/reference/components/ui/widgets/MapFiltersButton.md +33 -0
  56. package/docs/reference/components/ui/widgets/MapLayersButton.md +15 -0
  57. package/docs/reference/components/ui/widgets/Player.md +32 -0
  58. package/docs/reference/components/ui/widgets/Share.md +15 -0
  59. package/docs/reference/components/ui/widgets/Zoom.md +15 -0
  60. package/docs/reference/utils/API.md +311 -0
  61. package/docs/reference/utils/InitParameters.md +67 -0
  62. package/docs/reference/utils/URLHandler.md +102 -0
  63. package/docs/reference.md +73 -0
  64. package/docs/shortcuts.md +11 -0
  65. package/docs/tutorials/aerial_imagery.md +19 -0
  66. package/docs/tutorials/authentication.md +10 -0
  67. package/docs/tutorials/custom_widgets.md +64 -0
  68. package/docs/tutorials/map_style.md +27 -0
  69. package/docs/tutorials/migrate_v4.md +122 -0
  70. package/docs/tutorials/synced_coverage.md +42 -0
  71. package/mkdocs.yml +60 -5
  72. package/package.json +10 -7
  73. package/public/editor.html +21 -29
  74. package/public/index.html +3 -3
  75. package/public/map.html +19 -18
  76. package/public/viewer.html +18 -24
  77. package/public/widgets.html +265 -0
  78. package/scripts/doc.js +77 -0
  79. package/src/components/core/Basic.css +44 -0
  80. package/src/components/core/Basic.js +258 -0
  81. package/src/components/core/CoverageMap.css +9 -0
  82. package/src/components/core/CoverageMap.js +105 -0
  83. package/src/components/core/Editor.css +23 -0
  84. package/src/components/core/Editor.js +354 -0
  85. package/src/components/core/Viewer.css +109 -0
  86. package/src/components/core/Viewer.js +707 -0
  87. package/src/components/core/index.js +11 -0
  88. package/src/components/index.js +13 -0
  89. package/src/components/layout/CorneredGrid.js +109 -0
  90. package/src/components/layout/Mini.js +117 -0
  91. package/src/components/layout/index.js +7 -0
  92. package/src/components/menus/MapBackground.js +106 -0
  93. package/src/components/menus/MapFilters.js +386 -0
  94. package/src/components/menus/MapLayers.js +143 -0
  95. package/src/components/menus/MapLegend.js +54 -0
  96. package/src/components/menus/PictureLegend.js +103 -0
  97. package/src/components/menus/PictureMetadata.js +188 -0
  98. package/src/components/menus/PlayerOptions.js +96 -0
  99. package/src/components/menus/QualityScoreDoc.js +36 -0
  100. package/src/components/menus/ReportForm.js +133 -0
  101. package/src/components/menus/Share.js +228 -0
  102. package/src/components/menus/index.js +15 -0
  103. package/src/components/styles.js +365 -0
  104. package/src/components/ui/Button.js +75 -0
  105. package/src/components/ui/ButtonGroup.css +49 -0
  106. package/src/components/ui/ButtonGroup.js +68 -0
  107. package/src/components/ui/CopyButton.js +71 -0
  108. package/src/components/ui/Grade.js +54 -0
  109. package/src/components/ui/LinkButton.js +68 -0
  110. package/src/components/ui/Loader.js +188 -0
  111. package/src/components/{Map.css → ui/Map.css} +5 -17
  112. package/src/components/{Map.js → ui/Map.js} +114 -138
  113. package/src/components/ui/MapMore.js +324 -0
  114. package/src/components/{Photo.css → ui/Photo.css} +6 -6
  115. package/src/components/{Photo.js → ui/Photo.js} +279 -90
  116. package/src/components/ui/Popup.js +145 -0
  117. package/src/components/ui/QualityScore.js +152 -0
  118. package/src/components/ui/SearchBar.js +363 -0
  119. package/src/components/ui/TogglableGroup.js +162 -0
  120. package/src/components/ui/index.js +20 -0
  121. package/src/components/ui/widgets/GeoSearch.css +21 -0
  122. package/src/components/ui/widgets/GeoSearch.js +139 -0
  123. package/src/components/ui/widgets/Legend.js +51 -0
  124. package/src/components/ui/widgets/MapFiltersButton.js +104 -0
  125. package/src/components/ui/widgets/MapLayersButton.js +79 -0
  126. package/src/components/ui/widgets/Player.css +7 -0
  127. package/src/components/ui/widgets/Player.js +148 -0
  128. package/src/components/ui/widgets/Share.js +30 -0
  129. package/src/components/ui/widgets/Zoom.js +82 -0
  130. package/src/components/ui/widgets/index.js +12 -0
  131. package/src/img/panoramax.svg +13 -0
  132. package/src/img/switch_big.svg +20 -10
  133. package/src/index.js +6 -9
  134. package/src/translations/da.json +1 -1
  135. package/src/translations/de.json +1 -1
  136. package/src/translations/en.json +5 -3
  137. package/src/translations/eo.json +1 -1
  138. package/src/translations/es.json +1 -1
  139. package/src/translations/fr.json +5 -3
  140. package/src/translations/hu.json +1 -1
  141. package/src/translations/it.json +1 -1
  142. package/src/translations/ja.json +1 -1
  143. package/src/translations/nl.json +1 -1
  144. package/src/translations/pl.json +1 -1
  145. package/src/translations/sv.json +1 -1
  146. package/src/translations/zh_Hant.json +1 -1
  147. package/src/utils/API.js +74 -42
  148. package/src/utils/InitParameters.js +354 -0
  149. package/src/utils/URLHandler.js +364 -0
  150. package/src/utils/geocoder.js +116 -0
  151. package/src/utils/{I18n.js → i18n.js} +3 -1
  152. package/src/utils/index.js +11 -0
  153. package/src/utils/{Map.js → map.js} +216 -80
  154. package/src/utils/picture.js +433 -0
  155. package/src/utils/utils.js +315 -0
  156. package/src/utils/widgets.js +93 -0
  157. package/tests/components/ui/CopyButton.test.js +52 -0
  158. package/tests/components/ui/Loader.test.js +54 -0
  159. package/tests/components/{Map.test.js → ui/Map.test.js} +19 -61
  160. package/tests/components/{Photo.test.js → ui/Photo.test.js} +89 -57
  161. package/tests/components/ui/Popup.test.js +24 -0
  162. package/tests/components/ui/QualityScore.test.js +17 -0
  163. package/tests/components/ui/SearchBar.test.js +107 -0
  164. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +34 -0
  165. package/tests/components/ui/__snapshots__/Loader.test.js.snap +56 -0
  166. package/tests/components/{__snapshots__ → ui/__snapshots__}/Map.test.js.snap +11 -38
  167. package/tests/components/{__snapshots__ → ui/__snapshots__}/Photo.test.js.snap +57 -4
  168. package/tests/components/ui/__snapshots__/Popup.test.js.snap +29 -0
  169. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +11 -0
  170. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +65 -0
  171. package/tests/utils/API.test.js +1 -14
  172. package/tests/utils/InitParameters.test.js +485 -0
  173. package/tests/utils/URLHandler.test.js +350 -0
  174. package/tests/utils/__snapshots__/URLHandler.test.js.snap +21 -0
  175. package/tests/utils/__snapshots__/picture.test.js.snap +315 -0
  176. package/tests/utils/__snapshots__/widgets.test.js.snap +19 -0
  177. package/tests/utils/geocoder.test.js +37 -0
  178. package/tests/utils/{I18n.test.js → i18n.test.js} +1 -1
  179. package/tests/utils/map.test.js +67 -0
  180. package/tests/utils/picture.test.js +745 -0
  181. package/tests/utils/utils.test.js +288 -0
  182. package/tests/utils/widgets.test.js +90 -0
  183. package/docs/01_Start.md +0 -149
  184. package/docs/02_Usage.md +0 -831
  185. package/docs/04_Advanced_examples.md +0 -216
  186. package/src/Editor.css +0 -37
  187. package/src/Editor.js +0 -361
  188. package/src/StandaloneMap.js +0 -114
  189. package/src/Viewer.css +0 -203
  190. package/src/Viewer.js +0 -1246
  191. package/src/components/CoreView.css +0 -70
  192. package/src/components/CoreView.js +0 -175
  193. package/src/components/Loader.css +0 -74
  194. package/src/components/Loader.js +0 -120
  195. package/src/utils/Exif.js +0 -193
  196. package/src/utils/Utils.js +0 -631
  197. package/src/utils/Widgets.js +0 -562
  198. package/src/viewer/URLHash.js +0 -469
  199. package/src/viewer/Widgets.css +0 -880
  200. package/src/viewer/Widgets.js +0 -1470
  201. package/tests/Editor.test.js +0 -126
  202. package/tests/StandaloneMap.test.js +0 -45
  203. package/tests/Viewer.test.js +0 -366
  204. package/tests/__snapshots__/Editor.test.js.snap +0 -298
  205. package/tests/__snapshots__/StandaloneMap.test.js.snap +0 -30
  206. package/tests/__snapshots__/Viewer.test.js.snap +0 -195
  207. package/tests/components/CoreView.test.js +0 -92
  208. package/tests/components/Loader.test.js +0 -38
  209. package/tests/components/__snapshots__/Loader.test.js.snap +0 -15
  210. package/tests/utils/Exif.test.js +0 -124
  211. package/tests/utils/Map.test.js +0 -113
  212. package/tests/utils/Utils.test.js +0 -300
  213. package/tests/utils/Widgets.test.js +0 -107
  214. package/tests/utils/__snapshots__/Exif.test.js.snap +0 -43
  215. package/tests/utils/__snapshots__/Utils.test.js.snap +0 -41
  216. package/tests/utils/__snapshots__/Widgets.test.js.snap +0 -44
  217. package/tests/viewer/URLHash.test.js +0 -559
  218. package/tests/viewer/Widgets.test.js +0 -127
  219. package/tests/viewer/__snapshots__/URLHash.test.js.snap +0 -108
  220. package/tests/viewer/__snapshots__/Widgets.test.js.snap +0 -403
  221. /package/tests/utils/__snapshots__/{Map.test.js.snap → geocoder.test.js.snap} +0 -0
@@ -0,0 +1,365 @@
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: sans-serif;
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
+ }
62
+ `;
63
+
64
+ // Select
65
+ export const select = css`
66
+ select {
67
+ background-color: var(--widget-bg);
68
+ color: var(--widget-font);
69
+ border: 1px solid var(--widget-border-div);
70
+ border-radius: 20px;
71
+ font-size: 16px;
72
+ padding: 2px 10px;
73
+ }
74
+
75
+ select.pnx-100w {
76
+ width: 100%;
77
+ box-sizing: border-box;
78
+ }
79
+ `;
80
+
81
+ // Input
82
+ export const input = css`
83
+ input {
84
+ background-color: var(--widget-bg);
85
+ color: var(--widget-font);
86
+ border: 1px solid var(--widget-border-div);
87
+ border-radius: 20px;
88
+ font-size: 16px;
89
+ padding: 2px 10px;
90
+ }
91
+
92
+ input.pnx-100w {
93
+ width: 100%;
94
+ box-sizing: border-box;
95
+ }
96
+ `;
97
+
98
+ // Buttons
99
+ export const btn = css`
100
+ :host {
101
+ display: inline-block;
102
+ }
103
+
104
+ /* Common properties */
105
+ .pnx-btn {
106
+ white-space: nowrap;
107
+ font-size: 0.9em;
108
+ font-family: sans-serif;
109
+ flex-grow: 1;
110
+ flex-shrink: 1;
111
+ text-align: center;
112
+ padding: 5px;
113
+ font-weight: 600;
114
+ flex-basis: 30%;
115
+ line-height: 18px;
116
+ justify-content: center;
117
+ border-radius: 8px;
118
+ cursor: pointer;
119
+ text-decoration: none;
120
+ display: inline-flex;
121
+ align-items: center;
122
+ gap: 5px;
123
+ position: relative;
124
+ width: 100%;
125
+ height: 100%;
126
+ }
127
+
128
+ .pnx-btn:disabled { color: var(--widget-bg-inactive); }
129
+
130
+ .pnx-btn.pnx-btn-active,
131
+ .pnx-btn.pnx-btn-active:hover,
132
+ .pnx-btn.pnx-btn-full.pnx-btn-active:hover,
133
+ .pnx-btn.pnx-btn-outline.pnx-btn-active:hover {
134
+ background-color: var(--widget-bg-active);
135
+ border-color: var(--widget-bg-active);
136
+ color: var(--widget-font-active);
137
+ }
138
+
139
+ .pnx-btn .svg-inline--fa,
140
+ .pnx-btn ::slotted(.svg-inline--fa) {
141
+ height: 16px;
142
+ }
143
+
144
+ /* Sizing */
145
+ .pnx-btn-l {
146
+ border-radius: 12px;
147
+ height: 24px;
148
+ line-height: 24px;
149
+ font-size: 20px;
150
+ width: 24px;
151
+ }
152
+
153
+ .pnx-btn-xl {
154
+ border-radius: 20px;
155
+ height: 40px;
156
+ line-height: 40px;
157
+ font-size: 16px;
158
+ font-weight: 400;
159
+ min-width: 40px;
160
+ padding: 0 10px;
161
+ gap: 8px;
162
+ }
163
+
164
+ .pnx-btn.pnx-btn-xl .svg-inline--fa,
165
+ .pnx-btn.pnx-btn-xl ::slotted(.svg-inline--fa) {
166
+ height: 16px;
167
+ }
168
+
169
+ .pnx-btn-xxl {
170
+ border-radius: 28px;
171
+ height: 56px;
172
+ line-height: 56px;
173
+ font-size: 24px;
174
+ width: 56px;
175
+ }
176
+
177
+ .pnx-btn.pnx-btn-xxl .svg-inline--fa,
178
+ .pnx-btn.pnx-btn-xxl ::slotted(.svg-inline--fa) {
179
+ height: 24px;
180
+ }
181
+
182
+ /* Fully-filled style */
183
+ .pnx-btn-full {
184
+ background-color: var(--widget-bg-primary);
185
+ color: var(--widget-font-direct);
186
+ border: none;
187
+ }
188
+
189
+ .pnx-btn-full:not(:disabled):hover {
190
+ background-color: var(--widget-bg-primary-hover);
191
+ }
192
+
193
+ /* Outline style */
194
+ .pnx-btn-outline {
195
+ border: 1px solid var(--widget-border-btn);
196
+ color: var(--widget-font-direct);
197
+ background-color: var(--widget-bg);
198
+ }
199
+
200
+ .pnx-btn-outline:not(:disabled):hover {
201
+ background-color: var(--widget-bg-hover);
202
+ }
203
+
204
+ /* Flat style */
205
+ .pnx-btn-flat,
206
+ .pnx-btn-flat.pnx-btn-active,
207
+ .pnx-btn-flat.pnx-btn-active:hover,
208
+ .pnx-btn-flat:not(:disabled):hover {
209
+ border: 1px solid var(--widget-border-div);
210
+ color: var(--widget-font);
211
+ background-color: var(--widget-bg);
212
+ }
213
+
214
+ .pnx-btn-flat:not(:disabled):hover {
215
+ background-color: var(--widget-bg-hover);
216
+ }
217
+
218
+ /* Superflat style */
219
+ .pnx-btn-superflat,
220
+ .pnx-btn-superflat.pnx-btn-active,
221
+ .pnx-btn-superflat.pnx-btn-active:hover,
222
+ .pnx-btn-superflat:not(:disabled):hover {
223
+ border: 1px solid var(--widget-border-div);
224
+ color: var(--widget-font-direct);
225
+ background-color: var(--widget-bg);
226
+ }
227
+
228
+ .pnx-btn-superflat:not(:disabled):hover {
229
+ background-color: var(--widget-bg-hover);
230
+ }
231
+ `;
232
+
233
+ // Titles
234
+ export const titles = css`
235
+ h3 {
236
+ font-size: 1.1em;
237
+ line-height: 1.1em;
238
+ font-weight: 500;
239
+ margin: 10px 0 10px 0;
240
+ }
241
+
242
+ h4 {
243
+ font-size: 1.0em;
244
+ line-height: 1.0em;
245
+ font-weight: 500;
246
+ margin: 15px 0;
247
+ display: flex;
248
+ align-items: center;
249
+ justify-content: flex-start;
250
+ gap: 5px;
251
+ }
252
+
253
+ h4:first-of-type { margin-top: 0; }
254
+
255
+ h4 > svg.svg-inline--fa {
256
+ height: 18px;
257
+ }
258
+ `;
259
+
260
+ // Active icon badge
261
+ export const activeIcon = css`
262
+ .pnx-active-icon {
263
+ box-sizing: border-box;
264
+ background-color: var(--orange);
265
+ border: 3px solid #fff;
266
+ border-radius: 8px;
267
+ height: 15px;
268
+ left: 20px;
269
+ position: absolute;
270
+ top: 5px;
271
+ width: 15px;
272
+ }
273
+ `;
274
+
275
+ // Placeholder background
276
+ export const placeholder = css`
277
+ @keyframes animatedBackground {
278
+ from {
279
+ background-position: 0 0;
280
+ }
281
+ to {
282
+ background-position: 1000px 0;
283
+ }
284
+ }
285
+
286
+ .pnx-placeholder-loading {
287
+ width: 100px;
288
+ height: 100px;
289
+ background-image: linear-gradient(
290
+ 90deg,
291
+ #e4e4e4 0%,
292
+ #f1f1f1 40%,
293
+ #ededed 60%,
294
+ #e4e4e4 100%
295
+ );
296
+ background-position: 0px 0px;
297
+ background-repeat: repeat;
298
+ animation: animatedBackground 5s linear infinite;
299
+ }
300
+ `;
301
+
302
+ // Expandable block
303
+ export const expandable = css`
304
+ details summary {
305
+ font-size: 1.0em;
306
+ line-height: 1.0em;
307
+ font-weight: 500;
308
+ margin: 15px 0;
309
+ cursor: pointer;
310
+ }
311
+
312
+ details summary svg {
313
+ height: 18px;
314
+ vertical-align: sub;
315
+ margin-right: 2px;
316
+ }
317
+ `;
318
+
319
+ // Tables
320
+ export const tables = css`
321
+ table {
322
+ border-collapse: collapse;
323
+ font-size: 0.9rem;
324
+ width: 100%;
325
+ }
326
+
327
+ thead {
328
+ background-color: var(--blue-pale);
329
+ }
330
+
331
+ th[scope="row"] {
332
+ text-align: left;
333
+ }
334
+
335
+ th, td {
336
+ border: 1px solid var(--grey-semi-dark);
337
+ padding: 8px 10px;
338
+ max-width: 600px;
339
+ }
340
+
341
+ .pnx-table-light th[scope="row"] {
342
+ width: 30%;
343
+ }
344
+
345
+ .pnx-table-light th,
346
+ .pnx-table-light td {
347
+ border: none;
348
+ padding: 5px 10px;
349
+ text-align: left;
350
+ }
351
+
352
+ .pnx-table-light .pnx-td-with-id {
353
+ display: flex;
354
+ justify-content: space-between;
355
+ align-items: center;
356
+ }
357
+
358
+ table:not(.pnx-table-light) td:last-of-type {
359
+ text-align: center;
360
+ }
361
+
362
+ table:not(.pnx-table-light) tbody > tr:nth-of-type(even) {
363
+ background-color: var(--grey);
364
+ }
365
+ `;
@@ -0,0 +1,75 @@
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)
27
+ * @property {string} [size=md] The size of the button (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
+ */
31
+ static properties = {
32
+ active: {type: Boolean},
33
+ kind: {type: String},
34
+ size: {type: String},
35
+ disabled: {type: Boolean},
36
+ type: {type: String},
37
+ };
38
+
39
+ constructor() {
40
+ super();
41
+ this.active = false;
42
+ this.disabled = false;
43
+ this.kind = "full";
44
+ this.size = "md";
45
+ }
46
+
47
+ /** @private */
48
+ connectedCallback() {
49
+ super.connectedCallback();
50
+
51
+ if(this.type === "submit") {
52
+ this.addEventListener("click", () => this.closest("FORM")?.requestSubmit());
53
+ }
54
+ }
55
+
56
+ /** @private */
57
+ render() {
58
+ const b = document.createElement("button");
59
+ b.setAttribute("part", "btn");
60
+
61
+ this.constructor.observedAttributes
62
+ .filter(k => this[k] !== undefined && this[k] !== false && !["active", "kind", "size"].includes(k))
63
+ .forEach(k => b.setAttribute(k, this[k]));
64
+
65
+ b.classList.add("pnx-btn", `pnx-btn-${this.kind}`, `pnx-btn-${this.size}`);
66
+ if(this.active) { b.classList.add("pnx-btn-active"); }
67
+
68
+ const slot = document.createElement("slot");
69
+ b.appendChild(slot);
70
+
71
+ return b;
72
+ }
73
+ }
74
+
75
+ customElements.define("pnx-button", Button);
@@ -0,0 +1,49 @@
1
+ /* Togglable in group */
2
+ pnx-button-group > pnx-togglable-group > pnx-button {
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+
7
+ /* Row */
8
+ pnx-button-group[dir="row"] > :not(:first-child):not(:last-child)::part(btn),
9
+ pnx-button-group[dir="row"] > :not(:first-child):not(:last-child) > ::part(btn) {
10
+ border-radius: 0;
11
+ border-left: none;
12
+ border-right: none;
13
+ }
14
+
15
+ pnx-button-group[dir="row"] > :first-child::part(btn),
16
+ pnx-button-group[dir="row"] > :first-child > ::part(btn) {
17
+ border-top-right-radius: 0;
18
+ border-bottom-right-radius: 0;
19
+ border-right: none;
20
+ }
21
+
22
+ pnx-button-group[dir="row"] > :last-child::part(btn),
23
+ pnx-button-group[dir="row"] > :last-child > ::part(btn) {
24
+ border-top-left-radius: 0;
25
+ border-bottom-left-radius: 0;
26
+ border-left: none;
27
+ }
28
+
29
+ /* Column */
30
+ pnx-button-group[dir="column"] > :not(:first-child):not(:last-child)::part(btn),
31
+ pnx-button-group[dir="column"] > :not(:first-child):not(:last-child) > ::part(btn) {
32
+ border-radius: 0;
33
+ border-top: none;
34
+ border-bottom: none;
35
+ }
36
+
37
+ pnx-button-group[dir="column"] > :first-child::part(btn),
38
+ pnx-button-group[dir="column"] > :first-child > ::part(btn) {
39
+ border-bottom-right-radius: 0;
40
+ border-bottom-left-radius: 0;
41
+ border-bottom: none;
42
+ }
43
+
44
+ pnx-button-group[dir="column"] > :last-child::part(btn),
45
+ pnx-button-group[dir="column"] > :last-child > ::part(btn) {
46
+ border-top-left-radius: 0;
47
+ border-top-right-radius: 0;
48
+ border-top: none;
49
+ }
@@ -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%; }
36
+ div.column ::slotted(*) { width: 100%; }
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,71 @@
1
+ import { LitElement, html } 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
+
7
+ /**
8
+ * Copy Button element allows top copy in clipboard some text.
9
+ * @class Panoramax.components.ui.CopyButton
10
+ * @element pnx-copy-button
11
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
12
+ * @example
13
+ * ```html
14
+ * <pnx-copy-button text="content to copy" ._t=${viewer._t}>
15
+ * Copy me !
16
+ * </pnx-copy-button>
17
+ * ```
18
+ */
19
+ export default class CopyButton extends LitElement {
20
+ /** @private */
21
+ static styles = [faSvg, btn];
22
+
23
+ /**
24
+ * Component properties.
25
+ * @memberof Panoramax.components.ui.CopyButton#
26
+ * @type {Object}
27
+ * @property {string} [text] Text to copy in clipboard on click (use either this parameter or input, not both)
28
+ * @property {input} [input] ID of a HTML input field to copy content from in clipboard (use either this parameter or text, not both)
29
+ */
30
+ static properties = {
31
+ text: {type: String},
32
+ input: {type: String},
33
+ _active: {state: true, type: Boolean},
34
+ };
35
+
36
+ constructor() {
37
+ super();
38
+ this.data = "";
39
+ this.input = "";
40
+ this._active = false;
41
+ this.addEventListener("click", this._onClick);
42
+ }
43
+
44
+ /** @private */
45
+ _onClick() {
46
+ let textToCopy;
47
+ if(this.input !== "") {
48
+ const inputField = document.getElementById(this.input);
49
+ textToCopy = inputField.innerText || inputField.value;
50
+ }
51
+ else if(this.text !== "") {
52
+ textToCopy = this.text;
53
+ }
54
+ navigator.clipboard.writeText(textToCopy);
55
+ this._active = true;
56
+ setTimeout(() => this._active = false, 2000);
57
+ }
58
+
59
+ /** @private */
60
+ render() {
61
+ /* eslint-disable indent */
62
+ return html`<button class="pnx-btn pnx-btn-full ${this._active ? "pnx-btn-active" : ""}" part="btn">
63
+ ${this._active ?
64
+ html`${this._t?.pnx.copied || "Copied"} ${fa(faCheck)}` :
65
+ html`<slot>${fa(faCopy)} ${this._t?.pnx.copy || "Copy"}</slot>`
66
+ }
67
+ </button>`;
68
+ }
69
+ }
70
+
71
+ 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);