@panoramax/web-viewer 5.0.0-develop-d26305dd → 5.0.0-develop-be5ba1a7
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.
- package/build/cjs/index.js +1 -1
- package/build/cjs/index_photoviewer.js +1 -1
- package/build/esm/components/core/Basic.js +1 -1
- package/build/esm/translations/el.json +92 -1
- package/package.json +1 -1
- package/build/bundle.cjs +0 -3399
- package/build/bundle.cjs.map +0 -1
- package/build/bundle_photoviewer.cjs +0 -2510
- package/build/bundle_photoviewer.cjs.map +0 -1
- package/build/components/core/Basic.css +0 -56
- package/build/components/core/Basic.js +0 -378
- package/build/components/core/CoverageMap.css +0 -10
- package/build/components/core/CoverageMap.js +0 -169
- package/build/components/core/Editor.css +0 -33
- package/build/components/core/Editor.js +0 -398
- package/build/components/core/PhotoViewer.css +0 -70
- package/build/components/core/PhotoViewer.js +0 -650
- package/build/components/core/Viewer.css +0 -130
- package/build/components/core/Viewer.js +0 -711
- package/build/components/core/index.js +0 -10
- package/build/components/index.js +0 -11
- package/build/components/index_photoviewer.js +0 -6
- package/build/components/layout/BottomDrawer.js +0 -258
- package/build/components/layout/CorneredGrid.js +0 -143
- package/build/components/layout/Mini.js +0 -121
- package/build/components/layout/Tabs.js +0 -140
- package/build/components/layout/index.js +0 -9
- package/build/components/menus/LocationPrecisionDoc.js +0 -42
- package/build/components/menus/MapBackground.js +0 -110
- package/build/components/menus/MapFilters.js +0 -567
- package/build/components/menus/MapLayers.js +0 -238
- package/build/components/menus/MapLegend.js +0 -68
- package/build/components/menus/MiniPictureLegend.js +0 -73
- package/build/components/menus/PictureLegend.js +0 -379
- package/build/components/menus/PictureMetadata.js +0 -380
- package/build/components/menus/PlayerOptions.js +0 -93
- package/build/components/menus/QualityScoreDoc.js +0 -42
- package/build/components/menus/ReportForm.js +0 -132
- package/build/components/menus/SemanticsDoc.js +0 -38
- package/build/components/menus/SemanticsDownload.js +0 -33
- package/build/components/menus/SemanticsFilters.js +0 -153
- package/build/components/menus/SemanticsList.js +0 -413
- package/build/components/menus/SemanticsMetadata.js +0 -368
- package/build/components/menus/Share.js +0 -105
- package/build/components/menus/index.js +0 -22
- package/build/components/menus/index_photoviewer.js +0 -11
- package/build/components/styles.js +0 -557
- package/build/components/ui/AnnotationsSwitch.js +0 -159
- package/build/components/ui/Button.js +0 -77
- package/build/components/ui/ButtonGroup.css +0 -59
- package/build/components/ui/ButtonGroup.js +0 -69
- package/build/components/ui/CopyButton.js +0 -110
- package/build/components/ui/Grade.js +0 -54
- package/build/components/ui/GradeFilter.js +0 -122
- package/build/components/ui/IconSwitch.js +0 -193
- package/build/components/ui/LinkButton.js +0 -67
- package/build/components/ui/ListGroup.js +0 -66
- package/build/components/ui/ListItem.js +0 -90
- package/build/components/ui/Loader.js +0 -203
- package/build/components/ui/Map.css +0 -63
- package/build/components/ui/Map.js +0 -853
- package/build/components/ui/MapMore.js +0 -175
- package/build/components/ui/Photo.css +0 -50
- package/build/components/ui/Photo.js +0 -1502
- package/build/components/ui/Popup.js +0 -145
- package/build/components/ui/ProgressBar.js +0 -104
- package/build/components/ui/QualityScore.js +0 -147
- package/build/components/ui/SearchBar.js +0 -374
- package/build/components/ui/SemanticsEditor.js +0 -191
- package/build/components/ui/SemanticsTable.js +0 -88
- package/build/components/ui/Switch.js +0 -139
- package/build/components/ui/TogglableGroup.js +0 -157
- package/build/components/ui/index.js +0 -29
- package/build/components/ui/index_photoviewer.js +0 -21
- package/build/components/ui/widgets/CopyCoordinates.js +0 -75
- package/build/components/ui/widgets/GeoSearch.css +0 -21
- package/build/components/ui/widgets/GeoSearch.js +0 -150
- package/build/components/ui/widgets/Legend.js +0 -190
- package/build/components/ui/widgets/LevelSelect.css +0 -51
- package/build/components/ui/widgets/LevelSelect.js +0 -143
- package/build/components/ui/widgets/MapFiltersButton.js +0 -114
- package/build/components/ui/widgets/MapLayersButton.js +0 -79
- package/build/components/ui/widgets/OSMEditors.js +0 -155
- package/build/components/ui/widgets/PictureLegendActions.js +0 -99
- package/build/components/ui/widgets/Player.css +0 -7
- package/build/components/ui/widgets/Player.js +0 -154
- package/build/components/ui/widgets/SemanticsFiltersButton.js +0 -65
- package/build/components/ui/widgets/Zoom.js +0 -84
- package/build/components/ui/widgets/index.js +0 -16
- package/build/components/ui/widgets/index_photoviewer.js +0 -7
- package/build/img/arrow_360.svg +0 -14
- package/build/img/arrow_flat.svg +0 -11
- package/build/img/arrow_triangle.svg +0 -9
- package/build/img/arrow_turn.svg +0 -8
- package/build/img/bg_aerial.jpg +0 -0
- package/build/img/bg_streets.jpg +0 -0
- package/build/img/loader_base.jpg +0 -0
- package/build/img/logo_dead.svg +0 -91
- package/build/img/marker.svg +0 -17
- package/build/img/marker_blue.svg +0 -20
- package/build/img/osm.svg +0 -49
- package/build/img/panoramax.svg +0 -13
- package/build/img/switch_big.svg +0 -54
- package/build/img/switch_mini.svg +0 -48
- package/build/img/wd.svg +0 -1
- package/build/index_photoviewer.js +0 -4
- package/build/package.json +0 -148
- package/build/servers.js +0 -14
- package/build/translations/ar.json +0 -1
- package/build/translations/be.json +0 -257
- package/build/translations/br.json +0 -81
- package/build/translations/cy.json +0 -117
- package/build/translations/da.json +0 -300
- package/build/translations/de.json +0 -309
- package/build/translations/en.json +0 -294
- package/build/translations/eo.json +0 -235
- package/build/translations/es.json +0 -292
- package/build/translations/fi.json +0 -1
- package/build/translations/fr.json +0 -294
- package/build/translations/hr.json +0 -294
- package/build/translations/hu.json +0 -294
- package/build/translations/it.json +0 -306
- package/build/translations/ja.json +0 -182
- package/build/translations/ko.json +0 -1
- package/build/translations/nl.json +0 -305
- package/build/translations/nn.json +0 -1
- package/build/translations/pl.json +0 -169
- package/build/translations/pt.json +0 -296
- package/build/translations/pt_BR.json +0 -304
- package/build/translations/sv.json +0 -182
- package/build/translations/ti.json +0 -9
- package/build/translations/tr.json +0 -297
- package/build/translations/uk.json +0 -268
- package/build/translations/zh_Hant.json +0 -309
- package/build/utils/API.js +0 -928
- package/build/utils/InitParameters.js +0 -521
- package/build/utils/MapStyleComposer.js +0 -889
- package/build/utils/PanoraMapProtocol.js +0 -49
- package/build/utils/PhotoAdapter.js +0 -49
- package/build/utils/PresetsManager.js +0 -148
- package/build/utils/SemanticsMapProtocol.js +0 -144
- package/build/utils/URLHandler.js +0 -426
- package/build/utils/geocoder.js +0 -203
- package/build/utils/i18n.js +0 -128
- package/build/utils/index.js +0 -17
- package/build/utils/index_photoviewer.js +0 -14
- package/build/utils/indoor.js +0 -200
- package/build/utils/map.js +0 -788
- package/build/utils/picture.js +0 -507
- package/build/utils/semantics.js +0 -321
- package/build/utils/services.js +0 -148
- package/build/utils/utils.js +0 -433
- package/build/utils/widgets.js +0 -110
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import { LitElement, css, html, nothing } from "lit";
|
|
2
|
-
import { classMap } from "lit/directives/class-map.js";
|
|
3
|
-
import { map } from "lit/directives/map.js";
|
|
4
|
-
import { fa, listenForMenuClosure } from "../../utils/widgets.js";
|
|
5
|
-
import { faSvg } from "../styles.js";
|
|
6
|
-
import {
|
|
7
|
-
faCircleExclamation, faCircleNotch, faMagnifyingGlass, faXmark
|
|
8
|
-
} from "@fortawesome/free-solid-svg-icons";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Search Bar Element displays an interactive search widget.
|
|
13
|
-
* @class Panoramax.components.ui.SearchBar
|
|
14
|
-
* @element pnx-search-bar
|
|
15
|
-
* @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
|
|
16
|
-
* @fires Panoramax.components.ui.SearchBar#result
|
|
17
|
-
* @example
|
|
18
|
-
* ```html
|
|
19
|
-
* <pnx-search-bar
|
|
20
|
-
* id="my-search-bar"
|
|
21
|
-
* placeholder="Search something..."
|
|
22
|
-
* .searcher=${mysearchfct}
|
|
23
|
-
* ._parent=${viewer}
|
|
24
|
-
* reduceable="false"
|
|
25
|
-
* reduced="false"
|
|
26
|
-
* size="xxl" @result=${e => console.log(e.detail)}
|
|
27
|
-
* >
|
|
28
|
-
* <!-- Optional icon for display on left-side of search bar -->
|
|
29
|
-
* </pnx-search-bar>
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export default class SearchBar extends LitElement {
|
|
33
|
-
/** @private */
|
|
34
|
-
static styles = [ faSvg, css`
|
|
35
|
-
/* Container */
|
|
36
|
-
.sb {
|
|
37
|
-
display: flex;
|
|
38
|
-
align-items: center;
|
|
39
|
-
justify-content: space-between;
|
|
40
|
-
gap: 5px;
|
|
41
|
-
border: 1px solid var(--widget-border-div);
|
|
42
|
-
border-radius: 5px;
|
|
43
|
-
background-color: var(--widget-bg);
|
|
44
|
-
color: var(--widget-font);
|
|
45
|
-
height: 30px;
|
|
46
|
-
border-radius: 20px;
|
|
47
|
-
position: relative;
|
|
48
|
-
padding: 0 0 0 10px;
|
|
49
|
-
width: fit-content;
|
|
50
|
-
max-width: 100%;
|
|
51
|
-
box-sizing: border-box;
|
|
52
|
-
font-family: var(--font-family);
|
|
53
|
-
}
|
|
54
|
-
.sb.sb-xxl {
|
|
55
|
-
height: 40px;
|
|
56
|
-
line-height: 40px;
|
|
57
|
-
}
|
|
58
|
-
.sb.sb-reduceable {
|
|
59
|
-
width: 360px;
|
|
60
|
-
}
|
|
61
|
-
.sb.sb-reduceable.sb-reduced {
|
|
62
|
-
width: fit-content;
|
|
63
|
-
padding: 0;
|
|
64
|
-
gap: 0;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* Text field */
|
|
68
|
-
.sb input {
|
|
69
|
-
background: none;
|
|
70
|
-
border: none !important;
|
|
71
|
-
outline: none;
|
|
72
|
-
height: 20px;
|
|
73
|
-
width: 100%;
|
|
74
|
-
font-family: var(--font-family);
|
|
75
|
-
}
|
|
76
|
-
.sb.sb-xxl input {
|
|
77
|
-
font-size: 1.1em;
|
|
78
|
-
}
|
|
79
|
-
.sb.sb-reduceable.sb-reduced input {
|
|
80
|
-
display: none;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/* Status icon */
|
|
84
|
-
.sb-icon {
|
|
85
|
-
cursor: pointer;
|
|
86
|
-
height: 30px;
|
|
87
|
-
line-height: 30px;
|
|
88
|
-
width: 30px;
|
|
89
|
-
min-width: 30px;
|
|
90
|
-
text-align: center;
|
|
91
|
-
}
|
|
92
|
-
.sb.sb-xxl .sb-icon {
|
|
93
|
-
height: 40px;
|
|
94
|
-
line-height: 40px;
|
|
95
|
-
width: 40px;
|
|
96
|
-
min-width: 40px;
|
|
97
|
-
}
|
|
98
|
-
.sb-icon svg {
|
|
99
|
-
pointer-events: none;
|
|
100
|
-
width: 14px;
|
|
101
|
-
height: 14px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/* Search results */
|
|
105
|
-
.sb-results {
|
|
106
|
-
position: absolute;
|
|
107
|
-
top: 35px;
|
|
108
|
-
list-style: none;
|
|
109
|
-
margin: 0;
|
|
110
|
-
padding: 0;
|
|
111
|
-
max-width: calc(100% - 20px);
|
|
112
|
-
border: 1px solid var(--widget-border-div);
|
|
113
|
-
border-radius: 10px;
|
|
114
|
-
background-color: var(--widget-bg);
|
|
115
|
-
color: var(--widget-font);
|
|
116
|
-
z-index: 130;
|
|
117
|
-
font-size: 1.05em;
|
|
118
|
-
line-height: normal;
|
|
119
|
-
font-family: var(--font-family);
|
|
120
|
-
max-height: 50vh;
|
|
121
|
-
overflow-y: auto;
|
|
122
|
-
}
|
|
123
|
-
.sb.sb-xxl .sb-results {
|
|
124
|
-
top: 45px;
|
|
125
|
-
}
|
|
126
|
-
.sb-result,
|
|
127
|
-
.sb-empty {
|
|
128
|
-
display: block;
|
|
129
|
-
padding: 5px 15px;
|
|
130
|
-
white-space: nowrap;
|
|
131
|
-
overflow: hidden;
|
|
132
|
-
text-overflow: ellipsis;
|
|
133
|
-
cursor: pointer;
|
|
134
|
-
border-radius: 0;
|
|
135
|
-
}
|
|
136
|
-
.sb-result:hover {
|
|
137
|
-
background-color: var(--widget-bg-hover);
|
|
138
|
-
}
|
|
139
|
-
.sb-result:first-child {
|
|
140
|
-
border-top-right-radius: 10px;
|
|
141
|
-
border-top-left-radius: 10px;
|
|
142
|
-
padding-top: 15px;
|
|
143
|
-
}
|
|
144
|
-
.sb-result:last-child {
|
|
145
|
-
border-bottom-right-radius: 10px;
|
|
146
|
-
border-bottom-left-radius: 10px;
|
|
147
|
-
padding-bottom: 15px;
|
|
148
|
-
}
|
|
149
|
-
` ];
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Component properties.
|
|
153
|
-
* @memberof Panoramax.components.ui.SearchBar#
|
|
154
|
-
* @type {Object}
|
|
155
|
-
* @property {string} [id] The ID attribute set on component and prefix for input as well
|
|
156
|
-
* @property {string} [placeholder] Default text to display on empty field
|
|
157
|
-
* @property {boolean} [reduceable=false] Can the search bar be collapsed (for mobile view)
|
|
158
|
-
* @property {boolean} [reduced=false] Is the search bar currently collapsed ?
|
|
159
|
-
* @property {string} [value] The default input value
|
|
160
|
-
* @property {string} [size=md] The component sizing (md, xxl)
|
|
161
|
-
* @property {function} [searcher] Search callback, function that takes as parameter the input text value, and resolves on list of results ({title, subtitle} and any other data you'd like to get on validation)
|
|
162
|
-
* @property {boolean} [no-menu-closure=false] Set to true to ignore menu closure events
|
|
163
|
-
*/
|
|
164
|
-
static properties = {
|
|
165
|
-
id: {type: String},
|
|
166
|
-
placeholder: {type: String},
|
|
167
|
-
reduceable: {type: Boolean, reflect: true},
|
|
168
|
-
reduced: {type: Boolean, reflect: true},
|
|
169
|
-
value: {type: String},
|
|
170
|
-
size: {type: String},
|
|
171
|
-
_icon: {state: true},
|
|
172
|
-
_results: {state: true},
|
|
173
|
-
searcher: {type: Function},
|
|
174
|
-
"no-menu-closure": {type: Boolean},
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
constructor() {
|
|
178
|
-
super();
|
|
179
|
-
|
|
180
|
-
// State properties
|
|
181
|
-
this.reduceable = false;
|
|
182
|
-
this.reduced = false;
|
|
183
|
-
this.placeholder = nothing;
|
|
184
|
-
this.size = "md";
|
|
185
|
-
this._icon = "search";
|
|
186
|
-
this._results = null;
|
|
187
|
-
this["no-menu-closure"] = false;
|
|
188
|
-
|
|
189
|
-
// Other properties
|
|
190
|
-
this._throttler = null;
|
|
191
|
-
delete this._lastSearch;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/** @private */
|
|
195
|
-
connectedCallback() {
|
|
196
|
-
super.connectedCallback();
|
|
197
|
-
if(!this["no-menu-closure"]) { listenForMenuClosure(this, this.reset.bind(this)); }
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/** @private */
|
|
201
|
-
attributeChangedCallback(name, _old, value) {
|
|
202
|
-
super.attributeChangedCallback(name, _old, value);
|
|
203
|
-
|
|
204
|
-
if(name === "value") {
|
|
205
|
-
if([null, undefined, "", "null"].includes(value)) {
|
|
206
|
-
this._icon = "search";
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
this._icon = "empty";
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/** @private */
|
|
215
|
-
_onIconClick() {
|
|
216
|
-
if(["empty", "warn"].includes(this._icon)) {
|
|
217
|
-
this.reset();
|
|
218
|
-
}
|
|
219
|
-
if(this.reduceable && this._icon == "search") {
|
|
220
|
-
this.reduced = !this.reduced;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** @private */
|
|
225
|
-
_onInputChange(e) {
|
|
226
|
-
this.value = e.target.value;
|
|
227
|
-
this._throttledSearch();
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** @private */
|
|
231
|
-
_onResultClick(item) {
|
|
232
|
-
/**
|
|
233
|
-
* Event for search result clicked
|
|
234
|
-
* @event Panoramax.components.ui.SearchBar#result
|
|
235
|
-
* @type {CustomEvent}
|
|
236
|
-
* @property {object|null} detail The data associated to clicked item (format based on searcher function results), or null on reset
|
|
237
|
-
*/
|
|
238
|
-
this.dispatchEvent(new CustomEvent("result", {bubbles: true, composed: true, detail: item}));
|
|
239
|
-
|
|
240
|
-
this._results = null;
|
|
241
|
-
if(this._throttler) {
|
|
242
|
-
clearTimeout(this._throttler);
|
|
243
|
-
this._throttler = null;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if(!this.reduceable && item) {
|
|
247
|
-
this.value = item?.title;
|
|
248
|
-
this._icon = "empty";
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
this.value = "";
|
|
252
|
-
this._icon = "search";
|
|
253
|
-
if(this.reduceable) { this.reduced = true; }
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Limit search calls to every 500ms
|
|
259
|
-
* @private
|
|
260
|
-
*/
|
|
261
|
-
_throttledSearch() {
|
|
262
|
-
if(this._throttler) {
|
|
263
|
-
clearTimeout(this._throttler);
|
|
264
|
-
delete this._throttler;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
this._throttler = setTimeout(this._search.bind(this), 500);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Perform real search
|
|
272
|
-
* @private
|
|
273
|
-
*/
|
|
274
|
-
_search() {
|
|
275
|
-
if(!this.value || this.value.length == 0) {
|
|
276
|
-
this.reset();
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if(!this.searcher) {
|
|
281
|
-
console.warn("No search handler defined");
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
this._icon = "loading";
|
|
286
|
-
this._results = null;
|
|
287
|
-
|
|
288
|
-
this.searcher(this.value).then(data => {
|
|
289
|
-
if(this._icon !== "loading") { return; }
|
|
290
|
-
|
|
291
|
-
this._icon = "empty";
|
|
292
|
-
if(!data || data.length == 0) {
|
|
293
|
-
this._results = [];
|
|
294
|
-
}
|
|
295
|
-
else if(data === true) {
|
|
296
|
-
this._results = null;
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
this._results = data;
|
|
300
|
-
if(!this["no-menu-closure"]) {
|
|
301
|
-
this._parent?.dispatchEvent(new CustomEvent("menu-opened", { detail: { menu: this }}));
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}).catch(e => {
|
|
305
|
-
console.error(e);
|
|
306
|
-
this._icon = "warn";
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Empty results list and reset search bar content.
|
|
312
|
-
*/
|
|
313
|
-
reset() {
|
|
314
|
-
this._onResultClick(null);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/** @private */
|
|
318
|
-
render() {
|
|
319
|
-
const classes = {
|
|
320
|
-
sb: true,
|
|
321
|
-
"sb-xxl": this.size === "xxl",
|
|
322
|
-
"sb-reduceable": this.reduceable,
|
|
323
|
-
"sb-reduced": this.reduced,
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
return html`<div
|
|
327
|
-
id=${this.id}
|
|
328
|
-
class=${classMap(classes)}
|
|
329
|
-
part="container"
|
|
330
|
-
>
|
|
331
|
-
<slot name="pre" class=${classMap({"sb-reduced": this.reduced})}></slot>
|
|
332
|
-
|
|
333
|
-
<input
|
|
334
|
-
id="${this.id}-input"
|
|
335
|
-
type="text"
|
|
336
|
-
placeholder=${this.placeholder}
|
|
337
|
-
autocomplete="off"
|
|
338
|
-
@change=${this._onInputChange.bind(this)}
|
|
339
|
-
@keypress=${this._onInputChange.bind(this)}
|
|
340
|
-
@paste=${this._onInputChange.bind(this)}
|
|
341
|
-
@input=${this._onInputChange.bind(this)}
|
|
342
|
-
.value=${this.value || ""}
|
|
343
|
-
part="input"
|
|
344
|
-
/>
|
|
345
|
-
|
|
346
|
-
<span
|
|
347
|
-
class="sb-icon"
|
|
348
|
-
@click=${this._onIconClick.bind(this)}
|
|
349
|
-
>
|
|
350
|
-
${this._icon == "search" ? fa(faMagnifyingGlass) : nothing}
|
|
351
|
-
${this._icon == "loading" ? fa(faCircleNotch, { classes: ["fa-spin"] }) : nothing}
|
|
352
|
-
${this._icon == "empty" ? fa(faXmark) : nothing}
|
|
353
|
-
${this._icon == "warn" ? fa(faCircleExclamation) : nothing}
|
|
354
|
-
</span>
|
|
355
|
-
|
|
356
|
-
${!this.reduced && this._results ? html`
|
|
357
|
-
<div class="sb-results">
|
|
358
|
-
${this._results.length === 0 ? html`
|
|
359
|
-
<div class="sb-empty">${this._parent?._t?.pnx.search_empty}</div>
|
|
360
|
-
` : nothing}
|
|
361
|
-
|
|
362
|
-
${map(this._results, i => html`
|
|
363
|
-
<div class="sb-result" @click=${() => this._onResultClick(i)}>
|
|
364
|
-
${i.title}
|
|
365
|
-
${i.subtitle && i.subtitle != "" ? html`<br /><small>${i.subtitle}</small>` : nothing}
|
|
366
|
-
</div>
|
|
367
|
-
`)}
|
|
368
|
-
</div>
|
|
369
|
-
` : nothing}
|
|
370
|
-
</div>`;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
customElements.define("pnx-search-bar", SearchBar);
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { LitElement, css, html } from "lit";
|
|
2
|
-
import Basic from "../core/Basic.js";
|
|
3
|
-
import { computeDiffTags, parseSemanticsString, semanticsToString } from "../../utils/semantics.js";
|
|
4
|
-
import { textarea } from "../styles.js";
|
|
5
|
-
import JSON5 from "json5";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Semantics Editor offer an easy-to-use input for adding or editing semantics tags.
|
|
9
|
-
*
|
|
10
|
-
* It manipulates list of `{key: "mypanokey", value: "myvalue"}` entries through `semantics` attribute.
|
|
11
|
-
*
|
|
12
|
-
* @class Panoramax.components.ui.SemanticsEditor
|
|
13
|
-
* @element pnx-semantics-editor
|
|
14
|
-
* @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
|
|
15
|
-
* @fires Panoramax.components.ui.SemanticsEditor#change
|
|
16
|
-
* @example
|
|
17
|
-
* ```html
|
|
18
|
-
* <!-- Basic example -->
|
|
19
|
-
* <pnx-semantics-editor
|
|
20
|
-
* id="editor"
|
|
21
|
-
* semantics=${mypic.semantics}
|
|
22
|
-
* ._t=${viewer._t}
|
|
23
|
-
* onchange=${e => console.log(e.detail.semantics)}
|
|
24
|
-
* />
|
|
25
|
-
*
|
|
26
|
-
* <!-- You can access editor and check its validity through native web browser functions -->
|
|
27
|
-
* <script>
|
|
28
|
-
* const editor = document.getElementById("editor");
|
|
29
|
-
* console.log(editor.checkValidity()); // True if input is valid
|
|
30
|
-
* </script>
|
|
31
|
-
*
|
|
32
|
-
* <!-- You can change specifically style of textarea -->
|
|
33
|
-
* <style>
|
|
34
|
-
* pnx-semantics-editor::part(text) {
|
|
35
|
-
* color: blue;
|
|
36
|
-
* }
|
|
37
|
-
* </style>
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export default class SemanticsEditor extends LitElement {
|
|
41
|
-
static styles = [textarea, css`
|
|
42
|
-
textarea:invalid {
|
|
43
|
-
border: 2px solid var(--red);
|
|
44
|
-
background-color:var(--beige);
|
|
45
|
-
}
|
|
46
|
-
`];
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Component properties.
|
|
50
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
51
|
-
* @type {Object}
|
|
52
|
-
* @property {object} [semantics] The `semantics` field of a picture or annotation feature. It is updated when field changes, but reflect the whole list of new tags (not delta needed by API). If you want delta, please use getDiff function.
|
|
53
|
-
* @property {number} [rows=3] The amount of rows shown for textarea
|
|
54
|
-
*/
|
|
55
|
-
static properties = {
|
|
56
|
-
semantics: {converter: Basic.GetJSONConverter(), reflect: true},
|
|
57
|
-
rows: {type: Number},
|
|
58
|
-
_valid: {state: true},
|
|
59
|
-
_t: {converter: Basic.GetJSONConverter()},
|
|
60
|
-
_firstSemantics: {state: true},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
constructor() {
|
|
64
|
-
super();
|
|
65
|
-
this.semantics = null;
|
|
66
|
-
this._valid = true;
|
|
67
|
-
this._firstSemantics = null;
|
|
68
|
-
this.rows = 3;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** @private */
|
|
72
|
-
connectedCallback() {
|
|
73
|
-
super.connectedCallback();
|
|
74
|
-
this._firstSemantics = this.semantics === null ? [] : JSON5.parse(JSON5.stringify(this.semantics));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Get current delta between initial tags and user changes.
|
|
79
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
80
|
-
* @returns {object[]} The list of tag changes (in API format)
|
|
81
|
-
*/
|
|
82
|
-
getDiff() {
|
|
83
|
-
return computeDiffTags(this._firstSemantics || [], this.semantics);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Check if input is having a valid value.
|
|
88
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
89
|
-
* @returns {boolean} True if it's valid
|
|
90
|
-
*/
|
|
91
|
-
checkValidity() {
|
|
92
|
-
return this._valid;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Force display of invalid input
|
|
97
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
98
|
-
*/
|
|
99
|
-
reportValidity() {
|
|
100
|
-
this.renderRoot.querySelector("textarea")?.reportValidity();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Forces Editor to goes back to its empty, initial state.
|
|
105
|
-
* @param {object} [baseSemantics=null] Initial existing semantics you want to show in editor. This is useful for getting a diff of only new semantic entries. Leave empty if no tags pre-exist.
|
|
106
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
107
|
-
*/
|
|
108
|
-
reset(baseSemantics = null) {
|
|
109
|
-
this.semantics = null;
|
|
110
|
-
this._valid = true;
|
|
111
|
-
|
|
112
|
-
const txt = this.renderRoot.querySelector("textarea");
|
|
113
|
-
txt?.setCustomValidity("");
|
|
114
|
-
txt?.reportValidity();
|
|
115
|
-
|
|
116
|
-
this._firstSemantics = baseSemantics;
|
|
117
|
-
this.semantics = baseSemantics;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Forces Editor to save current text and parse semantics.
|
|
122
|
-
* @memberof Panoramax.components.ui.SemanticsEditor#
|
|
123
|
-
*/
|
|
124
|
-
forceInput() {
|
|
125
|
-
const target = this.renderRoot.querySelector("textarea");
|
|
126
|
-
this._onInput({ target });
|
|
127
|
-
this._onBlur({ target });
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/** @private */
|
|
131
|
-
_onInput(e) {
|
|
132
|
-
const tarea = e.target;
|
|
133
|
-
try {
|
|
134
|
-
this.semantics = parseSemanticsString(tarea.value) || [];
|
|
135
|
-
this._valid = true;
|
|
136
|
-
} catch (err) {
|
|
137
|
-
if(err.message !== "Invalid tags") { console.error(err); }
|
|
138
|
-
this._valid = false;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/** @private */
|
|
143
|
-
_onBlur(e) {
|
|
144
|
-
const prevValidity = e.target.checkValidity();
|
|
145
|
-
|
|
146
|
-
if(this._valid) {
|
|
147
|
-
e.target.setCustomValidity("");
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Event for value change.
|
|
151
|
-
*
|
|
152
|
-
* Note that this event is launched only on valid input.
|
|
153
|
-
*
|
|
154
|
-
* @event Panoramax.components.ui.SemanticsEditor#change
|
|
155
|
-
* @type {CustomEvent}
|
|
156
|
-
* @property {object[]} detail.semantics The new tags list (in API semantics property format)
|
|
157
|
-
* @property {object[]} detail.delta The delta between old and current tags (expected by API)
|
|
158
|
-
*/
|
|
159
|
-
this.dispatchEvent(new CustomEvent("change", {
|
|
160
|
-
detail: {
|
|
161
|
-
semantics: this.semantics || [],
|
|
162
|
-
delta: computeDiffTags(this._firstSemantics || [], this.semantics),
|
|
163
|
-
}
|
|
164
|
-
}));
|
|
165
|
-
}
|
|
166
|
-
else if(prevValidity) { // Do not call again if already shows up, to fix Chrome issue
|
|
167
|
-
e.target.setCustomValidity(this._t?.pnx.semantics_editor_error || "Invalid syntax");
|
|
168
|
-
e.target.reportValidity();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** @private */
|
|
173
|
-
render() {
|
|
174
|
-
return html`
|
|
175
|
-
<textarea
|
|
176
|
-
part="text"
|
|
177
|
-
autocomplete="off"
|
|
178
|
-
autocorrect="off"
|
|
179
|
-
autocapitalize="off"
|
|
180
|
-
spellcheck="false"
|
|
181
|
-
placeholder=${this._t?.pnx.semantics_editor_example || "key1=value1\nprefix|key2=value2"}
|
|
182
|
-
@input=${this._onInput}
|
|
183
|
-
@blur=${this._onBlur}
|
|
184
|
-
rows=${this.rows}
|
|
185
|
-
.value=${semanticsToString(this.semantics)}
|
|
186
|
-
></textarea>
|
|
187
|
-
`;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
customElements.define("pnx-semantics-editor", SemanticsEditor);
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { LitElement, css, html, nothing } from "lit";
|
|
2
|
-
import { table } from "../styles.js";
|
|
3
|
-
import { groupByPrefix } from "../../utils/semantics.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Semantics Tables display all semantics tags from either a picture or an annotation.
|
|
7
|
-
*
|
|
8
|
-
* @class Panoramax.components.ui.SemanticsTable
|
|
9
|
-
* @element pnx-semantics-table
|
|
10
|
-
* @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
|
|
11
|
-
* @example
|
|
12
|
-
* ```html
|
|
13
|
-
* <pnx-semantics-table source=${picture.properties} ._t=${viewer._t} />
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export default class SemanticsTable extends LitElement {
|
|
17
|
-
/** @private */
|
|
18
|
-
static styles = [ table, css`
|
|
19
|
-
:host { display: block; }
|
|
20
|
-
th:first-child, td:first-child { width: 40%; }
|
|
21
|
-
td { vertical-align: top; }
|
|
22
|
-
|
|
23
|
-
td small { color: var(--grey-semi-dark); }
|
|
24
|
-
td a small { color: unset; }
|
|
25
|
-
.qualifiers { margin-top: 5px; }
|
|
26
|
-
.qualifiers > b { margin: 8px 0; }
|
|
27
|
-
.qualifiers ul {
|
|
28
|
-
list-style: none;
|
|
29
|
-
margin: 0px 0px 0px 15px;
|
|
30
|
-
padding: 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
img.prefix-logo {
|
|
34
|
-
max-width: 15px;
|
|
35
|
-
max-height: 15px;
|
|
36
|
-
aspect-ratio: 1;
|
|
37
|
-
vertical-align: middle;
|
|
38
|
-
}
|
|
39
|
-
` ];
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Component properties.
|
|
43
|
-
* @memberof Panoramax.components.ui.SemanticsTable#
|
|
44
|
-
* @type {Object}
|
|
45
|
-
* @property {object} [source] The picture or annotation feature (having a `semantics` property)
|
|
46
|
-
*/
|
|
47
|
-
static properties = {
|
|
48
|
-
source: {type: Object},
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
render() {
|
|
52
|
-
if(!this.source) { return nothing; }
|
|
53
|
-
|
|
54
|
-
const groups = groupByPrefix(this.source.semantics);
|
|
55
|
-
|
|
56
|
-
return html`<table>
|
|
57
|
-
<thead>
|
|
58
|
-
<tr><th>${this._t.pnx.semantics_key}</th><th>${this._t.pnx.semantics_value}</th></tr>
|
|
59
|
-
</thead>
|
|
60
|
-
<tbody>
|
|
61
|
-
${groups.map(g => g.tags.map(tag => html`
|
|
62
|
-
<tr>
|
|
63
|
-
<td>
|
|
64
|
-
${g.prefix != ""
|
|
65
|
-
? (g.logo
|
|
66
|
-
? html`<img src=${g.logo} class="prefix-logo" alt=${g.prefix} title=${g.title} />`
|
|
67
|
-
: html`<small>(${g.prefix})</small>`)
|
|
68
|
-
: nothing
|
|
69
|
-
}
|
|
70
|
-
${g.key_transform ? g.key_transform(tag, this._t) : tag.key}
|
|
71
|
-
</td>
|
|
72
|
-
<td>
|
|
73
|
-
${g.value_transform ? g.value_transform(tag, this._t) : tag.value}
|
|
74
|
-
${tag.qualifiers ? html`<div class="qualifiers">
|
|
75
|
-
<b>${this._t.pnx.semantics_qualifiers}</b>
|
|
76
|
-
<ul>
|
|
77
|
-
${tag.qualifiers.map(q => html`<li>${q.subkey} = ${q.value}</li>`)}
|
|
78
|
-
</ul>
|
|
79
|
-
</div>` : nothing}
|
|
80
|
-
</td>
|
|
81
|
-
</tr>
|
|
82
|
-
`))}
|
|
83
|
-
</tbody>
|
|
84
|
-
</table>`;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
customElements.define("pnx-semantics-table", SemanticsTable);
|