@panoramax/web-viewer 3.2.3-develop-e277ccb9 → 3.2.3-develop-dbce84df

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 (42) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/build/index.css +1 -1
  3. package/build/index.css.map +1 -1
  4. package/build/index.html +1 -1
  5. package/build/index.js +29 -25
  6. package/build/index.js.map +1 -1
  7. package/build/photo.html +1 -0
  8. package/config/paths.js +1 -0
  9. package/config/webpack.config.js +26 -0
  10. package/docs/03_URL_settings.md +4 -1
  11. package/docs/09_Develop.md +1 -1
  12. package/docs/images/class_diagram.drawio +37 -22
  13. package/docs/images/class_diagram.jpg +0 -0
  14. package/docs/index.md +15 -1
  15. package/docs/reference/components/core/PhotoViewer.md +256 -0
  16. package/docs/reference/components/core/Viewer.md +47 -49
  17. package/docs/reference/components/menus/MapLegend.md +1 -1
  18. package/docs/reference/components/ui/Photo.md +8 -0
  19. package/docs/reference/components/ui/widgets/Legend.md +7 -1
  20. package/docs/reference.md +3 -2
  21. package/docs/tutorials/custom_widgets.md +6 -11
  22. package/docs/tutorials/migrate_v4.md +2 -0
  23. package/mkdocs.yml +1 -0
  24. package/package.json +1 -1
  25. package/public/index.html +14 -9
  26. package/public/photo.html +55 -0
  27. package/src/components/core/PhotoViewer.css +65 -0
  28. package/src/components/core/PhotoViewer.js +441 -0
  29. package/src/components/core/Viewer.js +71 -306
  30. package/src/components/core/index.js +1 -0
  31. package/src/components/menus/MapLegend.js +1 -21
  32. package/src/components/ui/Photo.js +13 -3
  33. package/src/components/ui/widgets/Legend.js +32 -1
  34. package/src/index.js +1 -0
  35. package/src/translations/nl.json +105 -5
  36. package/src/utils/API.js +2 -2
  37. package/src/utils/InitParameters.js +29 -16
  38. package/src/utils/URLHandler.js +11 -5
  39. package/src/utils/map.js +2 -2
  40. package/tests/components/ui/Photo.test.js +6 -6
  41. package/tests/utils/InitParameters.test.js +1 -0
  42. package/tests/utils/URLHandler.test.js +16 -6
@@ -0,0 +1 @@
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Panoramax Photo Viewer</title><style>#viewer{position:relative;width:95%;margin:2.5%;height:400px}#viewer.fullpage{position:fixed;top:0;bottom:0;left:0;right:0;height:unset;width:unset;margin:0}</style><script defer="defer" src="index.js"></script><link href="index.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><pnx-photo-viewer id="viewer" class="fullpage" sequence="ecfe4b2c-0acd-4d3a-a10d-c3e6818755c8" picture="329af5c6-4761-4a6d-9c1e-674fd6daa8b6"/><script>var servers={meta:"https://api.panoramax.xyz/api",ign:"https://panoramax.ign.fr/api",osm:"https://panoramax.openstreetmap.fr/api",local:"http://localhost:5000/api",dev:"https://panoramax.codeureusesenliberte.fr/api"},urlParams=new URLSearchParams(window.location.search),server=servers[urlParams.get("server")||"meta"];window.onload=()=>{document.getElementById("viewer").setAttribute("endpoint",server)}</script></body></html>
package/config/paths.js CHANGED
@@ -53,6 +53,7 @@ module.exports = {
53
53
  appHtmlMap: resolveApp('public/map.html'),
54
54
  appHtmlEditor: resolveApp('public/editor.html'),
55
55
  appHtmlViewer: resolveApp('public/viewer.html'),
56
+ appHtmlPhotoViewer: resolveApp('public/photo.html'),
56
57
  appHtmlWidgets: resolveApp('public/widgets.html'),
57
58
  appLibIndexJs: resolveModule(resolveApp, 'src/index'),
58
59
  appPackageJson: resolveApp('package.json'),
@@ -744,6 +744,32 @@ module.exports = function (webpackEnv) {
744
744
  : undefined
745
745
  )
746
746
  ),
747
+ new HtmlWebpackPlugin(
748
+ Object.assign(
749
+ {},
750
+ {
751
+ inject: true,
752
+ filename: "photo.html",
753
+ template: paths.appHtmlPhotoViewer,
754
+ },
755
+ isEnvProduction
756
+ ? {
757
+ minify: {
758
+ removeComments: true,
759
+ collapseWhitespace: true,
760
+ removeRedundantAttributes: true,
761
+ useShortDoctype: true,
762
+ removeEmptyAttributes: true,
763
+ removeStyleLinkTypeAttributes: true,
764
+ keepClosingSlash: true,
765
+ minifyJS: true,
766
+ minifyCSS: true,
767
+ minifyURLs: true,
768
+ },
769
+ }
770
+ : undefined
771
+ )
772
+ ),
747
773
  // Inlines the webpack runtime script. This script is too small to warrant
748
774
  // a network request.
749
775
  // https://github.com/facebook/create-react-app/issues/5358
@@ -10,6 +10,10 @@ Example:
10
10
  https://api.panoramax.xyz/?map=19.51/48.1204522/-1.7199004&pic=890b6268-7716-4e34-ada9-69985e6c1657
11
11
  ```
12
12
 
13
+ !!! note
14
+
15
+ This works only for __Viewer__ and __Photo Viewer__ components, not for __Editor__ or __Coverage Map__.
16
+
13
17
  ## :fontawesome-solid-computer: Interface settings
14
18
 
15
19
  ### :material-target: `focus`: main shown element
@@ -74,7 +78,6 @@ xyz=10/25/50
74
78
 
75
79
  The `map` parameters handles both map visibility and position. It can take different values:
76
80
 
77
- - `map=none`: to completely disable the map.
78
81
  - `map=zoom/latitude/longitude`: for setting the map position (following [MapLibre GL JS hash format](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/#hash)). It updates automatically when map is moved.
79
82
  - no parameter set: shows the map of the whole world, or zoomed on instance area of interest.
80
83
 
@@ -12,7 +12,7 @@ Here are some inputs about working with Panoramax web client code.
12
12
 
13
13
  The current code is split between various elements:
14
14
 
15
- - __Core components__: a single functional entry, like [Viewer](./reference/components/core/Viewer.md) (map + picture), [Coverage Map](./reference/components/core/CoverageMap.md) or [Editor](./reference/components/core/Editor.md). They share parts of code in [Basic](./reference/components/core/Basic.md) class. They specialized the behaviour of components depending on the needs.
15
+ - __Core components__: a single functional entry, like [Viewer](./reference/components/core/Viewer.md) (map + picture), [Photo Viewer](./reference/components/core/PhotoViewer.md) (picture only), [Coverage Map](./reference/components/core/CoverageMap.md) or [Editor](./reference/components/core/Editor.md). They share parts of code in [Basic](./reference/components/core/Basic.md) class. They specialized the behaviour of components depending on the needs.
16
16
  - __UI components, menus & widgets__: reusable web components, like [Map](./reference/components/ui/Map.md), [Photo](./reference/components/ui/Photo.md) or [Loader](./reference/components/ui/Loader.md). They are used in some views depending of the context.
17
17
  - __Utils__: utility functions, splitted in various files for clarity.
18
18
 
@@ -1,6 +1,6 @@
1
- <mxfile host="app.diagrams.net" modified="2025-03-17T12:37:16.267Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0" etag="SUUWP6lveJk2cUhdSDGS" version="24.1.0" type="device">
1
+ <mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64; rv:136.0) Gecko/20100101 Firefox/136.0" version="26.1.1">
2
2
  <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
3
- <mxGraphModel dx="890" dy="496" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
3
+ <mxGraphModel dx="983" dy="448" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
4
4
  <root>
5
5
  <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
6
6
  <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
@@ -10,20 +10,20 @@
10
10
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-3" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="-sBJLWWXFzCuZ66xZKHM-1" vertex="1">
11
11
  <mxGeometry y="26" width="160" height="8" as="geometry" />
12
12
  </mxCell>
13
- <mxCell id="-sBJLWWXFzCuZ66xZKHM-9" value="Viewer" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
14
- <mxGeometry x="20" y="160" width="160" height="34" as="geometry" />
13
+ <mxCell id="-sBJLWWXFzCuZ66xZKHM-9" value="PhotoViewer" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
14
+ <mxGeometry x="20" y="148" width="160" height="34" as="geometry" />
15
15
  </mxCell>
16
16
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-10" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="-sBJLWWXFzCuZ66xZKHM-9" vertex="1">
17
17
  <mxGeometry y="26" width="160" height="8" as="geometry" />
18
18
  </mxCell>
19
19
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-11" value="CoverageMap" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
20
- <mxGeometry x="200" y="160" width="160" height="34" as="geometry" />
20
+ <mxGeometry x="200" y="148" width="160" height="34" as="geometry" />
21
21
  </mxCell>
22
22
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-12" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="-sBJLWWXFzCuZ66xZKHM-11" vertex="1">
23
23
  <mxGeometry y="26" width="160" height="8" as="geometry" />
24
24
  </mxCell>
25
25
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-13" value="Editor" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
26
- <mxGeometry x="380" y="160" width="160" height="34" as="geometry" />
26
+ <mxGeometry x="380" y="148" width="160" height="34" as="geometry" />
27
27
  </mxCell>
28
28
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-14" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="-sBJLWWXFzCuZ66xZKHM-13" vertex="1">
29
29
  <mxGeometry y="26" width="160" height="8" as="geometry" />
@@ -36,27 +36,33 @@
36
36
  </mxCell>
37
37
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-17" value="" style="endArrow=none;html=1;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" edge="1">
38
38
  <mxGeometry width="50" height="50" relative="1" as="geometry">
39
- <mxPoint x="100" y="140" as="sourcePoint" />
40
- <mxPoint x="460" y="140" as="targetPoint" />
39
+ <mxPoint x="100" y="128" as="sourcePoint" />
40
+ <mxPoint x="460" y="128" as="targetPoint" />
41
41
  </mxGeometry>
42
42
  </mxCell>
43
43
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-19" value="" style="endArrow=none;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-11" edge="1">
44
44
  <mxGeometry width="50" height="50" relative="1" as="geometry">
45
45
  <mxPoint x="370" y="290" as="sourcePoint" />
46
- <mxPoint x="280" y="140" as="targetPoint" />
46
+ <mxPoint x="280" y="130" as="targetPoint" />
47
47
  </mxGeometry>
48
48
  </mxCell>
49
49
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-20" value="" style="endArrow=none;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-13" edge="1">
50
50
  <mxGeometry width="50" height="50" relative="1" as="geometry">
51
51
  <mxPoint x="290" y="170" as="sourcePoint" />
52
- <mxPoint x="460" y="140" as="targetPoint" />
52
+ <mxPoint x="460" y="130" as="targetPoint" />
53
53
  </mxGeometry>
54
54
  </mxCell>
55
55
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-22" value="components.core" style="swimlane;whiteSpace=wrap;html=1;startSize=23;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
56
- <mxGeometry x="10" y="10" width="540" height="200" as="geometry" />
56
+ <mxGeometry x="10" y="10" width="540" height="240" as="geometry" />
57
+ </mxCell>
58
+ <mxCell id="l_DTcpemKbOkDnIudQOG-0" value="Viewer" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="-sBJLWWXFzCuZ66xZKHM-22">
59
+ <mxGeometry x="60" y="200" width="160" height="34" as="geometry" />
60
+ </mxCell>
61
+ <mxCell id="l_DTcpemKbOkDnIudQOG-1" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" vertex="1" parent="l_DTcpemKbOkDnIudQOG-0">
62
+ <mxGeometry y="26" width="160" height="8" as="geometry" />
57
63
  </mxCell>
58
64
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-23" value="components.ui" style="swimlane;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
59
- <mxGeometry x="10" y="230" width="540" height="90" as="geometry" />
65
+ <mxGeometry x="10" y="271" width="540" height="90" as="geometry" />
60
66
  </mxCell>
61
67
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-26" value="Photo" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" parent="-sBJLWWXFzCuZ66xZKHM-23" vertex="1">
62
68
  <mxGeometry x="10" y="40" width="160" height="34" as="geometry" />
@@ -76,16 +82,18 @@
76
82
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-25" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;" parent="-sBJLWWXFzCuZ66xZKHM-24" vertex="1">
77
83
  <mxGeometry y="26" width="160" height="8" as="geometry" />
78
84
  </mxCell>
79
- <mxCell id="-sBJLWWXFzCuZ66xZKHM-30" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-9" target="-sBJLWWXFzCuZ66xZKHM-24" edge="1">
80
- <mxGeometry width="160" relative="1" as="geometry">
85
+ <mxCell id="-sBJLWWXFzCuZ66xZKHM-30" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="l_DTcpemKbOkDnIudQOG-0" target="-sBJLWWXFzCuZ66xZKHM-24" edge="1">
86
+ <mxGeometry x="0.3561" y="-10" width="160" relative="1" as="geometry">
81
87
  <mxPoint x="370" y="300" as="sourcePoint" />
82
88
  <mxPoint x="234" y="272" as="targetPoint" />
89
+ <mxPoint as="offset" />
83
90
  </mxGeometry>
84
91
  </mxCell>
85
- <mxCell id="-sBJLWWXFzCuZ66xZKHM-31" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=0.506;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-10" target="-sBJLWWXFzCuZ66xZKHM-26" edge="1">
86
- <mxGeometry width="160" relative="1" as="geometry">
87
- <mxPoint x="370" y="300" as="sourcePoint" />
92
+ <mxCell id="-sBJLWWXFzCuZ66xZKHM-31" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;entryX=0.123;entryY=0.023;entryDx=0;entryDy=0;entryPerimeter=0;exitX=0.114;exitY=0.919;exitDx=0;exitDy=0;exitPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-10" target="-sBJLWWXFzCuZ66xZKHM-26" edge="1">
93
+ <mxGeometry x="0.4701" width="160" relative="1" as="geometry">
94
+ <mxPoint x="40" y="200" as="sourcePoint" />
88
95
  <mxPoint x="530" y="300" as="targetPoint" />
96
+ <mxPoint as="offset" />
89
97
  </mxGeometry>
90
98
  </mxCell>
91
99
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-32" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-1" target="-sBJLWWXFzCuZ66xZKHM-28" edge="1">
@@ -100,13 +108,14 @@
100
108
  </mxGeometry>
101
109
  </mxCell>
102
110
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-38" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-13" target="-sBJLWWXFzCuZ66xZKHM-24" edge="1">
103
- <mxGeometry width="160" relative="1" as="geometry">
111
+ <mxGeometry x="0.4416" y="4" width="160" relative="1" as="geometry">
104
112
  <mxPoint x="320" y="390" as="sourcePoint" />
105
113
  <mxPoint x="480" y="390" as="targetPoint" />
114
+ <mxPoint as="offset" />
106
115
  </mxGeometry>
107
116
  </mxCell>
108
117
  <mxCell id="-sBJLWWXFzCuZ66xZKHM-39" value="Use" style="endArrow=open;endSize=12;dashed=1;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="-sBJLWWXFzCuZ66xZKHM-11" target="-sBJLWWXFzCuZ66xZKHM-24" edge="1">
109
- <mxGeometry x="-0.5789" width="160" relative="1" as="geometry">
118
+ <mxGeometry x="0.2678" y="6" width="160" relative="1" as="geometry">
110
119
  <mxPoint x="210" y="360" as="sourcePoint" />
111
120
  <mxPoint x="240" y="270" as="targetPoint" />
112
121
  <mxPoint as="offset" />
@@ -117,12 +126,18 @@
117
126
  <mxPoint x="150" y="370" as="sourcePoint" />
118
127
  <mxPoint x="310" y="370" as="targetPoint" />
119
128
  <Array as="points">
120
- <mxPoint x="370" y="220" />
121
- <mxPoint x="250" y="220" />
122
- <mxPoint x="190" y="240" />
129
+ <mxPoint x="350" y="260" />
130
+ <mxPoint x="190" y="280" />
123
131
  </Array>
124
132
  </mxGeometry>
125
133
  </mxCell>
134
+ <mxCell id="l_DTcpemKbOkDnIudQOG-4" value="Extends" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.441;exitY=0.022;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="l_DTcpemKbOkDnIudQOG-0">
135
+ <mxGeometry x="-0.2397" y="-30" width="160" relative="1" as="geometry">
136
+ <mxPoint x="110" y="158" as="sourcePoint" />
137
+ <mxPoint x="140" y="182" as="targetPoint" />
138
+ <mxPoint as="offset" />
139
+ </mxGeometry>
140
+ </mxCell>
126
141
  </root>
127
142
  </mxGraphModel>
128
143
  </diagram>
Binary file
package/docs/index.md CHANGED
@@ -77,7 +77,7 @@ Once ready, you can create for example a viewer. We use web components to do so,
77
77
 
78
78
  ```html
79
79
  <pnx-viewer
80
- endpoint="https://api.panoramax.xyz/api"
80
+ endpoint="https://api.panoramax.xyz/api"
81
81
  />
82
82
  ```
83
83
 
@@ -97,6 +97,20 @@ A simple map for showing Panoramax data availability.
97
97
 
98
98
  [Many options are available as well](./reference/components/core/CoverageMap.md).
99
99
 
100
+ __Photo Viewer__
101
+
102
+ A photo-only viewer, showing one picture at a time, and offering navigation through sequence and nearby pictures.
103
+
104
+ ```html
105
+ <pnx-photo-viewer
106
+ endpoint="https://api.panoramax.xyz/api"
107
+ sequence="id-to-an-existing-sequence"
108
+ picture="id-to-a-picture-in-this-sequence"
109
+ />
110
+ ```
111
+
112
+ [Many options are available as well](./reference/components/core/PhotoViewer.md).
113
+
100
114
  __Editor__
101
115
 
102
116
  A map and photo viewer, focused on a single sequence, for previewing edits made to it.
@@ -0,0 +1,256 @@
1
+ <a name="Panoramax.components.core.PhotoViewer"></a>
2
+
3
+ ## Panoramax.components.core.PhotoViewer ⇐ [<code>Basic</code>](Basic.md/#Panoramax.components.core.Basic)
4
+ **Kind**: static class of <code>Panoramax.components.core</code>
5
+ **Extends**: [<code>Basic</code>](Basic.md/#Panoramax.components.core.Basic)
6
+ **Emits**: [<code>select</code>](Basic.md/#Panoramax.components.core.Basic+event_select), [<code>ready</code>](Basic.md/#Panoramax.components.core.Basic+event_ready), [<code>broken</code>](Basic.md/#Panoramax.components.core.Basic+event_broken)
7
+ **Element**: pnx-photo-viewer
8
+ **Slot**: `top-left` The top-left corner
9
+ **Slot**: `top` The top middle corner
10
+ **Slot**: `top-right` The top-right corner
11
+ **Slot**: `bottom-left` The bottom-left corner
12
+ **Slot**: `bottom` The bottom middle corner
13
+ **Slot**: `bottom-right` The bottom-right corner
14
+ **Properties**
15
+
16
+ | Name | Type | Description |
17
+ | --- | --- | --- |
18
+ | loader | [<code>Loader</code>](../ui/Loader.md/#Panoramax.components.ui.Loader) | The loader screen |
19
+ | api | [<code>API</code>](../../utils/API.md/#Panoramax.utils.API) | The API manager |
20
+ | psv | [<code>Photo</code>](../ui/Photo.md/#Panoramax.components.ui.Photo) | The Photo Sphere Viewer component itself |
21
+ | grid | [<code>CorneredGrid</code>](../layout/CorneredGrid.md/#Panoramax.components.layout.CorneredGrid) | The grid layout manager |
22
+ | popup | [<code>Popup</code>](../ui/Popup.md/#Panoramax.components.ui.Popup) | The popup container |
23
+ | urlHandler | [<code>URLHandler</code>](../../utils/URLHandler.md/#Panoramax.utils.URLHandler) | The URL query parameters manager |
24
+
25
+
26
+ * [.PhotoViewer](#Panoramax.components.core.PhotoViewer) ⇐ [<code>Basic</code>](Basic.md/#Panoramax.components.core.Basic)
27
+ * [new PhotoViewer()](#new_Panoramax.components.core.PhotoViewer_new)
28
+ * [.properties](#Panoramax.components.core.PhotoViewer+properties) : <code>Object</code>
29
+ * [.onceReady()](#Panoramax.components.core.PhotoViewer+onceReady) ⇒ <code>Promise</code>
30
+ * [.oncePSVReady()](#Panoramax.components.core.PhotoViewer+oncePSVReady) ⇒ <code>Promise</code>
31
+ * [.onceFirstPicLoaded()](#Panoramax.components.core.PhotoViewer+onceFirstPicLoaded) ⇒ <code>Promise</code>
32
+ * [.setPopup(visible, [content])](#Panoramax.components.core.PhotoViewer+setPopup)
33
+ * [.moveCenter()](#Panoramax.components.core.PhotoViewer+moveCenter)
34
+ * [.moveLeft()](#Panoramax.components.core.PhotoViewer+moveLeft)
35
+ * [.moveRight()](#Panoramax.components.core.PhotoViewer+moveRight)
36
+ * [.moveUp()](#Panoramax.components.core.PhotoViewer+moveUp)
37
+ * [.moveDown()](#Panoramax.components.core.PhotoViewer+moveDown)
38
+ * [.onceAPIReady()](Basic.md/#Panoramax.components.core.Basic+onceAPIReady) ⇒ <code>Promise</code>
39
+ * [.getClassName()](Basic.md/#Panoramax.components.core.Basic+getClassName) ⇒ <code>string</code>
40
+ * [.select([seqId], [picId], [force])](#Panoramax.components.core.Basic+select)
41
+ * [.isWidthSmall()](Basic.md/#Panoramax.components.core.Basic+isWidthSmall) ⇒ <code>boolean</code>
42
+ * [.isHeightSmall()](Basic.md/#Panoramax.components.core.Basic+isHeightSmall) ⇒ <code>boolean</code>
43
+ * ["menu-opened"](Basic.md/#Panoramax.components.core.Basic+event_menu-opened)
44
+ * ["select"](Basic.md/#Panoramax.components.core.Basic+event_select)
45
+ * ["ready"](Basic.md/#Panoramax.components.core.Basic+event_ready)
46
+ * ["broken"](Basic.md/#Panoramax.components.core.Basic+event_broken)
47
+
48
+ <a name="new_Panoramax.components.core.PhotoViewer_new"></a>
49
+
50
+ ### new PhotoViewer()
51
+ Photo Viewer is a component showing pictures (without any map).
52
+
53
+ This component has a [CorneredGrid](../layout/CorneredGrid.md/#Panoramax.components.layout.CorneredGrid) layout, you can use directly any slot element to pass custom widgets.
54
+
55
+ If you need a viewer with map, checkout [Viewer component](Viewer.md/#Panoramax.components.core.Viewer).
56
+
57
+ **Example**
58
+ ```html
59
+ <!-- Basic example -->
60
+ <pnx-photo-viewer
61
+ endpoint="https://panoramax.openstreetmap.fr/"
62
+ />
63
+
64
+ <!-- With slotted widgets -->
65
+ <pnx-photo-viewer
66
+ endpoint="https://panoramax.openstreetmap.fr/"
67
+ >
68
+ <p slot="top-right">My custom text</p>
69
+ </pnx-photo-viewer>
70
+
71
+ <!-- With only your custom widgets -->
72
+ <pnx-photo-viewer
73
+ endpoint="https://panoramax.openstreetmap.fr/"
74
+ widgets="false"
75
+ >
76
+ <p slot="top-right">My custom text</p>
77
+ </pnx-photo-viewer>
78
+ ```
79
+ <a name="Panoramax.components.core.PhotoViewer+properties"></a>
80
+
81
+ ### photoViewer.properties : <code>Object</code>
82
+ Component properties. All of [Basic properties](Basic.md/#Panoramax.components.core.Basic+properties) are available as well.
83
+
84
+ **Kind**: instance property of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
85
+ **Mixes**: [<code>properties</code>](Basic.md/#Panoramax.components.core.Basic+properties)
86
+ **Overrides**: [<code>properties</code>](Basic.md/#Panoramax.components.core.Basic+properties)
87
+ **Properties**
88
+
89
+ | Name | Type | Default | Description |
90
+ | --- | --- | --- | --- |
91
+ | endpoint | <code>string</code> | | URL to API to use (must be a [STAC API](https://github.com/radiantearth/stac-api-spec/blob/main/overview.md)) |
92
+ | [psv] | <code>object</code> | | [Any option to pass to Photo component](../ui/Photo.md/#Panoramax.components.ui.Photo) as an object.<br />Example: `psv="{'transitionDuration': 500, 'picturesNavigation': 'pic'}"` |
93
+ | [widgets] | <code>string</code> | <code>true</code> | Use default set of widgets ? Set to false to avoid any widget to show up, and use slots to populate as you like. |
94
+ | [picture] | <code>string</code> | | The picture ID to display |
95
+ | [sequence] | <code>string</code> | | The sequence ID of the picture displayed |
96
+ | [fetchOptions] | <code>object</code> | | Set custom options for fetch calls made against API ([same syntax as fetch options parameter](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters)) |
97
+ | [lang] | <code>string</code> | | To override language used for labels. Defaults to using user's preferred languages. |
98
+ | [url-parameters] | <code>string</code> | <code>true</code> | Should the component add and update URL query parameters to save viewer state ? |
99
+
100
+ <a name="Panoramax.components.core.PhotoViewer+onceReady"></a>
101
+
102
+ ### photoViewer.onceReady() ⇒ <code>Promise</code>
103
+ Waits for PhotoViewer to be completely ready (map & PSV loaded, first picture also if one is wanted)
104
+
105
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
106
+ **Overrides**: [<code>onceReady</code>](Basic.md/#Panoramax.components.core.Basic+onceReady)
107
+ **Returns**: <code>Promise</code> - When viewer is ready
108
+ <a name="Panoramax.components.core.PhotoViewer+oncePSVReady"></a>
109
+
110
+ ### photoViewer.oncePSVReady() ⇒ <code>Promise</code>
111
+ Waiting for Photo Sphere Viewer to be available.
112
+
113
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
114
+ **Returns**: <code>Promise</code> - When PSV is ready to use
115
+ <a name="Panoramax.components.core.PhotoViewer+onceFirstPicLoaded"></a>
116
+
117
+ ### photoViewer.onceFirstPicLoaded() ⇒ <code>Promise</code>
118
+ Waits for first picture to display on PSV.
119
+
120
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
121
+ **Fulfil**: <code>undefined</code> When picture is shown
122
+ <a name="Panoramax.components.core.PhotoViewer+setPopup"></a>
123
+
124
+ ### photoViewer.setPopup(visible, [content])
125
+ Change full-page popup visibility and content
126
+
127
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
128
+
129
+ | Param | Type | Default | Description |
130
+ | --- | --- | --- | --- |
131
+ | visible | <code>boolean</code> | | True to make it appear |
132
+ | [content] | <code>string</code> \| <code>Array.&lt;Element&gt;</code> | <code>null</code> | The new popup content |
133
+
134
+ <a name="Panoramax.components.core.PhotoViewer+moveCenter"></a>
135
+
136
+ ### photoViewer.moveCenter()
137
+ Move the view of main component to its center.
138
+ For map, center view on selected picture.
139
+ For picture, center view on image center.
140
+
141
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
142
+ <a name="Panoramax.components.core.PhotoViewer+moveLeft"></a>
143
+
144
+ ### photoViewer.moveLeft()
145
+ Moves the view of main component slightly to the left.
146
+
147
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
148
+ <a name="Panoramax.components.core.PhotoViewer+moveRight"></a>
149
+
150
+ ### photoViewer.moveRight()
151
+ Moves the view of main component slightly to the right.
152
+
153
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
154
+ <a name="Panoramax.components.core.PhotoViewer+moveUp"></a>
155
+
156
+ ### photoViewer.moveUp()
157
+ Moves the view of main component slightly to the top.
158
+
159
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
160
+ <a name="Panoramax.components.core.PhotoViewer+moveDown"></a>
161
+
162
+ ### photoViewer.moveDown()
163
+ Moves the view of main component slightly to the bottom.
164
+
165
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
166
+ <a name="Panoramax.components.core.Basic+onceAPIReady"></a>
167
+
168
+ ### photoViewer.onceAPIReady() ⇒ <code>Promise</code>
169
+ Waits for initial API setup.
170
+
171
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
172
+ **Fulfil**: <code>null</code> When API is ready.
173
+ **Reject**: <code>string</code> Error message
174
+ <a name="Panoramax.components.core.Basic+getClassName"></a>
175
+
176
+ ### photoViewer.getClassName() ⇒ <code>string</code>
177
+ This allows to retrieve an always correct class name.
178
+ This is crap, but avoids issues with Webpack & so on.
179
+
180
+ Each inheriting class must override this method.
181
+
182
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
183
+ **Returns**: <code>string</code> - The class name (for example "Basic")
184
+ <a name="Panoramax.components.core.Basic+select"></a>
185
+
186
+ ### photoViewer.select([seqId], [picId], [force])
187
+ Change the currently picture and/or sequence.
188
+ Calling the method without parameters unselects.
189
+
190
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
191
+
192
+ | Param | Type | Default | Description |
193
+ | --- | --- | --- | --- |
194
+ | [seqId] | <code>string</code> | <code>null</code> | The sequence UUID |
195
+ | [picId] | <code>string</code> | <code>null</code> | The picture UUID |
196
+ | [force] | <code>boolean</code> | <code>false</code> | Force select even if already selected |
197
+
198
+ <a name="Panoramax.components.core.Basic+isWidthSmall"></a>
199
+
200
+ ### photoViewer.isWidthSmall() ⇒ <code>boolean</code>
201
+ Is the view running in a small container (small embed or smartphone)
202
+
203
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
204
+ **Returns**: <code>boolean</code> - True if container is small
205
+ <a name="Panoramax.components.core.Basic+isHeightSmall"></a>
206
+
207
+ ### photoViewer.isHeightSmall() ⇒ <code>boolean</code>
208
+ Is the view running in a small-height container (small embed or smartphone)
209
+
210
+ **Kind**: instance method of [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
211
+ **Returns**: <code>boolean</code> - True if container height is small
212
+ <a name="Panoramax.components.core.Basic+event_menu-opened"></a>
213
+
214
+ ### "menu-opened"
215
+ Event for overlaying menu opening
216
+
217
+ **Kind**: event emitted by [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
218
+ **Properties**
219
+
220
+ | Name | Type | Description |
221
+ | --- | --- | --- |
222
+ | detail.menu | <code>Element</code> | The opened menu |
223
+
224
+ <a name="Panoramax.components.core.Basic+event_select"></a>
225
+
226
+ ### "select"
227
+ Event for sequence/picture selection
228
+
229
+ **Kind**: event emitted by [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
230
+ **Properties**
231
+
232
+ | Name | Type | Description |
233
+ | --- | --- | --- |
234
+ | detail.seqId | <code>string</code> | The selected sequence ID |
235
+ | detail.picId | <code>string</code> | The selected picture ID (or null if not a precise picture clicked) |
236
+ | [detail.prevSeqId] | <code>string</code> | The previously selected sequence ID (or null if none) |
237
+ | [detail.prevPicId] | <code>string</code> | The previously selected picture ID (or null if none) |
238
+
239
+ <a name="Panoramax.components.core.Basic+event_ready"></a>
240
+
241
+ ### "ready"
242
+ Event for component being ready to use (API loaded)
243
+
244
+ **Kind**: event emitted by [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
245
+ <a name="Panoramax.components.core.Basic+event_broken"></a>
246
+
247
+ ### "broken"
248
+ Event for viewer failing to initially load
249
+
250
+ **Kind**: event emitted by [<code>PhotoViewer</code>](#Panoramax.components.core.PhotoViewer)
251
+ **Properties**
252
+
253
+ | Name | Type | Description |
254
+ | --- | --- | --- |
255
+ | detail.error | <code>string</code> | The user-friendly error message to display |
256
+