qwc2 2026.3.24 → 2026.4.2

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 (58) hide show
  1. package/README.md +2 -23
  2. package/components/AppMenu.js +29 -30
  3. package/components/AttributeTableWidget.js +8 -1
  4. package/components/SearchBox.js +2 -1
  5. package/components/map/layers/MVTLayer.js +15 -15
  6. package/components/map3d/ColorLayer3D.js +158 -0
  7. package/components/map3d/Map3D.js +98 -192
  8. package/components/map3d/drawtool/NumericInput3D.js +2 -2
  9. package/components/map3d/layers/GeoTIFFLayer3D.js +5 -4
  10. package/components/map3d/layers/Layer3D.js +168 -0
  11. package/components/map3d/layers/MVTLayer3D.js +59 -0
  12. package/components/map3d/layers/VectorLayer3D.js +10 -7
  13. package/components/map3d/layers/WFSLayer3D.js +8 -7
  14. package/components/map3d/layers/WMSLayer3D.js +6 -4
  15. package/components/map3d/layers/WMTSLayer3D.js +4 -3
  16. package/components/map3d/layers/index.js +3 -2
  17. package/components/map3d/utils/MiscUtils3D.js +10 -10
  18. package/components/style/AppMenu.css +61 -25
  19. package/components/style/AttributeTableWidget.css +5 -5
  20. package/icons/sunexp.svg +129 -0
  21. package/package.json +6 -4
  22. package/plugins/Bookmark.js +3 -2
  23. package/plugins/Identify.js +30 -6
  24. package/plugins/LayerTree.js +21 -1
  25. package/plugins/TopBar.js +15 -11
  26. package/plugins/map3d/HideObjects3D.js +4 -2
  27. package/plugins/map3d/LayerTree3D.js +2 -2
  28. package/plugins/map3d/MeasureObjects3D.js +8 -6
  29. package/plugins/map3d/SunExposure3D.js +415 -0
  30. package/plugins/map3d/TopBar3D.js +11 -5
  31. package/plugins/map3d/style/SunExposure3D.css +46 -0
  32. package/plugins/style/Portal.css +0 -5
  33. package/reducers/layers.js +17 -0
  34. package/scripts/gen-plugin-docs.js +4 -0
  35. package/static/translations/bg-BG.json +13 -0
  36. package/static/translations/ca-ES.json +13 -0
  37. package/static/translations/cs-CZ.json +13 -0
  38. package/static/translations/de-CH.json +15 -2
  39. package/static/translations/de-DE.json +15 -2
  40. package/static/translations/en-US.json +13 -0
  41. package/static/translations/es-ES.json +13 -0
  42. package/static/translations/fi-FI.json +13 -0
  43. package/static/translations/fr-FR.json +13 -0
  44. package/static/translations/hu-HU.json +13 -0
  45. package/static/translations/it-IT.json +13 -0
  46. package/static/translations/ja-JP.json +13 -0
  47. package/static/translations/nl-NL.json +13 -0
  48. package/static/translations/no-NO.json +13 -0
  49. package/static/translations/pl-PL.json +13 -0
  50. package/static/translations/pt-BR.json +13 -0
  51. package/static/translations/pt-PT.json +13 -0
  52. package/static/translations/ro-RO.json +13 -0
  53. package/static/translations/ru-RU.json +13 -0
  54. package/static/translations/sv-SE.json +13 -0
  55. package/static/translations/tr-TR.json +13 -0
  56. package/static/translations/tsconfig.json +11 -0
  57. package/static/translations/uk-UA.json +13 -0
  58. package/utils/LayerUtils.js +24 -11
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![Logo](https://raw.githubusercontent.com/qgis/qwc2/refs/heads/master/static/assets/img/qwc-logo.svg) QGIS Web Client
1
+ ![Logo](https://raw.githubusercontent.com/qgis/qwc2/refs/heads/master/static/assets/img/qwc-logo.svg) QGIS Web Client · [qwc.app](https://qwc.app)
2
2
  =================
3
3
 
4
4
  ## Introduction
@@ -10,28 +10,7 @@ The `qwc2` NPM package can be used as a dependency to build a custom QWC applica
10
10
 
11
11
  ### Main Features
12
12
 
13
- - Modular and easily configurable and extensible
14
- - Responsive, separately configurable for desktop and mobile devices
15
- - Theme switcher
16
- - Search with configurable search providers
17
- - Layer tree
18
- * Toggle layers and groups
19
- * Change layer order and opacity
20
- * Import external WMS/WFS/WMTS/GeoJSON/KML layers
21
- * Compare layers
22
- - Feature info
23
- - Printing using QGIS print layouts
24
- - Share permalinks
25
- - Bookmarks
26
- - Measuring tools
27
- - Height profile
28
- - Redlining
29
- - Editing and attribute table
30
- - Attribute table
31
- - Export map (raster images, DXF)
32
- - Time manager for temporal layers
33
- - Themeable with color schemes
34
- - [Additional plugins!](https://qwc-services.github.io/master/references/qwc2_plugins/)
13
+ See [qwc.app/features](https://qwc.app/features).
35
14
 
36
15
  ## Quick start
37
16
 
@@ -72,8 +72,8 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
72
72
  _this.props.setCurrentTask(null);
73
73
  }
74
74
  _this.props.onMenuToggled(!_this.state.menuVisible);
75
- if (_this.props.menuCompact) {
76
- _this.props.setMenuMargin(!_this.state.menuVisible ? MiscUtils.convertEmToPx(3.75) : 0, 0);
75
+ if (_this.props.menuDisplayMode !== "normal") {
76
+ _this.props.setMenuMargin(!_this.state.menuVisible ? MiscUtils.convertEmToPx(3.5) : 0, 0);
77
77
  }
78
78
  _this.setState(function (state) {
79
79
  return {
@@ -84,7 +84,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
84
84
  });
85
85
  });
86
86
  _defineProperty(_this, "checkCloseMenu", function (ev) {
87
- if (_this.menuEl && !_this.menuEl.contains(ev.target) && !_this.props.keepMenuOpen) {
87
+ if (_this.menuEl && !_this.menuEl.contains(ev.target) && _this.props.menuDisplayMode === "normal") {
88
88
  _this.toggleMenu();
89
89
  MiscUtils.killEvent(ev);
90
90
  }
@@ -98,7 +98,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
98
98
  });
99
99
  });
100
100
  _defineProperty(_this, "onMenuitemClicked", function (item) {
101
- if (!_this.props.keepMenuOpen && _this.state.menuVisible) {
101
+ if (_this.props.menuDisplayMode === "normal" && _this.state.menuVisible) {
102
102
  _this.toggleMenu();
103
103
  }
104
104
  if (item.url) {
@@ -111,6 +111,10 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
111
111
  _defineProperty(_this, "renderMenuItems", function (items, level, filter) {
112
112
  var submenu = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
113
113
  return (items || []).map(function (item) {
114
+ var trargs = item.trargs || [];
115
+ var label = item.title ? LocaleUtils.tr.apply(LocaleUtils, [item.title].concat(_toConsumableArray(trargs))) : LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "")].concat(_toConsumableArray(trargs)));
116
+ var comment = item.comment ? LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "") + "_comment"].concat(_toConsumableArray(trargs))) : "";
117
+ var labelclass = _this.props.menuDisplayMode === "icononly" ? "appmenu-menu-item-tooltip" : "appmenu-menu-item-label";
114
118
  if (item.subitems) {
115
119
  var _item$key;
116
120
  var expanded = filter || _this.state.submenusVisible[level] === item.key;
@@ -123,7 +127,6 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
123
127
  "appmenu-submenu": true,
124
128
  "appmenu-submenu-expanded": expanded
125
129
  });
126
- var label = item.title ? LocaleUtils.tr(item.title) : LocaleUtils.tr("appmenu.items." + item.key);
127
130
  return [/*#__PURE__*/React.createElement("div", {
128
131
  className: className,
129
132
  key: (_item$key = item.key) !== null && _item$key !== void 0 ? _item$key : item.title,
@@ -137,14 +140,12 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
137
140
  tabIndex: 0
138
141
  }, /*#__PURE__*/React.createElement(Icon, {
139
142
  icon: item.icon,
140
- size: "xlarge",
141
- title: _this.props.menuIconOnly ? label : null
142
- }), !_this.props.menuIconOnly ? label : null), subitems];
143
+ size: "xlarge"
144
+ }), /*#__PURE__*/React.createElement("span", {
145
+ className: labelclass
146
+ }, label)), subitems];
143
147
  } else {
144
- var trargs = item.trargs || [];
145
- var _label = item.title ? LocaleUtils.tr.apply(LocaleUtils, [item.title].concat(_toConsumableArray(trargs))) : LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "")].concat(_toConsumableArray(trargs)));
146
- var comment = item.comment ? LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "") + "_comment"].concat(_toConsumableArray(trargs))) : "";
147
- if (!filter || removeDiacritics(_label.toLowerCase()).match(filter) || comment && removeDiacritics(comment.toLowerCase()).match(filter)) {
148
+ if (!filter || removeDiacritics(label.toLowerCase()).match(filter) || comment && removeDiacritics(comment.toLowerCase()).match(filter)) {
148
149
  var _className = classnames({
149
150
  "appmenu-menu-item": true,
150
151
  "appmenu-menu-item-nested": submenu
@@ -162,13 +163,10 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
162
163
  tabIndex: 0
163
164
  }, /*#__PURE__*/React.createElement(Icon, {
164
165
  icon: item.icon,
165
- size: "xlarge",
166
- title: _this.props.menuIconOnly ? _label : null
167
- }), !_this.props.menuIconOnly ? /*#__PURE__*/React.createElement("span", {
168
- className: "appmenu-menu-item-label"
169
- }, _label, comment ? /*#__PURE__*/React.createElement("div", {
170
- className: "appmenu-menu-item-comment"
171
- }, comment) : null) : null);
166
+ size: "xlarge"
167
+ }), /*#__PURE__*/React.createElement("span", {
168
+ className: labelclass
169
+ }, label));
172
170
  }
173
171
  return null;
174
172
  }
@@ -215,7 +213,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
215
213
  MiscUtils.killEvent(ev);
216
214
  } else if (ev.key === 'Escape') {
217
215
  var _this$menuBtn, _this$menuBtn$focus;
218
- if (!_this.props.menuCompact) {
216
+ if (_this.props.menuDisplayMode === "normal") {
219
217
  _this.toggleMenu();
220
218
  }
221
219
  (_this$menuBtn = _this.menuBtn) === null || _this$menuBtn === void 0 || (_this$menuBtn$focus = _this$menuBtn.focus) === null || _this$menuBtn$focus === void 0 || _this$menuBtn$focus.call(_this$menuBtn);
@@ -237,7 +235,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
237
235
  return _createClass(AppMenu, [{
238
236
  key: "componentDidMount",
239
237
  value: function componentDidMount() {
240
- if (this.props.showOnStartup) {
238
+ if (this.props.showOnStartup || this.props.menuDisplayMode !== "normal") {
241
239
  this.toggleMenu();
242
240
  }
243
241
  this.addKeyBindings(this.props.menuItems);
@@ -249,7 +247,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
249
247
  key: "componentDidUpdate",
250
248
  value: function componentDidUpdate(prevProps, prevState) {
251
249
  var _this2 = this;
252
- if (this.state.menuVisible && !prevState.menuVisible && !this.props.menuCompact) {
250
+ if (this.state.menuVisible && !prevState.menuVisible) {
253
251
  // Need to wait until slide in transition is over
254
252
  setTimeout(function () {
255
253
  var _this2$filterfield, _this2$filterfield$fo;
@@ -259,7 +257,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
259
257
  setTimeout(function () {
260
258
  return document.addEventListener('click', _this2.checkCloseMenu);
261
259
  }, 0);
262
- } else if (prevState.menuVisible && !this.state.menuVisible && !this.props.menuCompact) {
260
+ } else if (prevState.menuVisible && !this.state.menuVisible) {
263
261
  document.removeEventListener('click', this.checkCloseMenu);
264
262
  }
265
263
  }
@@ -281,13 +279,13 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
281
279
  _this$props$buttonCon;
282
280
  var isMobile = ConfigUtils.isMobile();
283
281
  var visible = !this.props.currentTaskBlocked && this.state.menuVisible;
284
- var showLabel = !this.props.menuCompact && !isMobile;
282
+ var showLabel = this.props.menuDisplayMode === "normal" && !isMobile;
285
283
  var className = classnames({
286
284
  "AppMenu": true,
287
285
  "appmenu-blocked": this.props.currentTaskBlocked,
288
286
  "appmenu-visible": visible,
289
- "appmenu-compact": this.props.menuCompact,
290
- "appmenu-icononly": this.props.menuIconOnly,
287
+ "appmenu-compact": this.props.menuDisplayMode === "compact",
288
+ "appmenu-icononly": this.props.menuDisplayMode === "icononly",
291
289
  "appmenu-nolabel": !showLabel
292
290
  });
293
291
  var filter = this.state.filter ? new RegExp(removeDiacritics(this.state.filter).replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"), "i") : null;
@@ -313,6 +311,8 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
313
311
  }))]), /*#__PURE__*/React.createElement("div", {
314
312
  className: "appmenu-menu-container",
315
313
  tabIndex: -1
314
+ }, /*#__PURE__*/React.createElement("div", {
315
+ className: "appmenu-menu-aligner"
316
316
  }, /*#__PURE__*/React.createElement("div", {
317
317
  className: "appmenu-menu",
318
318
  inert: !visible,
@@ -321,7 +321,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
321
321
  _this3.menuEl = el;
322
322
  MiscUtils.setupKillTouchEvents(el);
323
323
  }
324
- }, this.props.showFilterField ? /*#__PURE__*/React.createElement("div", {
324
+ }, this.props.showFilterField && this.props.menuDisplayMode !== "icononly" ? /*#__PURE__*/React.createElement("div", {
325
325
  className: "appmenu-menu-item appmenu-menu-item-filter",
326
326
  onFocus: this.focusFilterField,
327
327
  onKeyDown: this.keyNav,
@@ -352,7 +352,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
352
352
  });
353
353
  },
354
354
  role: "suffix"
355
- }))) : null, this.renderMenuItems(this.props.menuItems, 0, filter))));
355
+ }))) : null, this.renderMenuItems(this.props.menuItems, 0, filter)))));
356
356
  }
357
357
  }]);
358
358
  }(React.Component);
@@ -362,8 +362,7 @@ _defineProperty(AppMenu, "propTypes", {
362
362
  buttonContents: PropTypes.object,
363
363
  buttonLabel: PropTypes.string,
364
364
  currentTaskBlocked: PropTypes.bool,
365
- keepMenuOpen: PropTypes.bool,
366
- menuCompact: PropTypes.bool,
365
+ menuDisplayMode: PropTypes.string,
367
366
  menuIconOnly: PropTypes.bool,
368
367
  menuItems: PropTypes.array,
369
368
  onMenuToggled: PropTypes.func,
@@ -388,7 +388,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
388
388
  };
389
389
  newState[stateField] = val;
390
390
  // Reset page if a reload is triggered (either filter changed with a set filter value, or filter value cleared)
391
- if (newState.filterVal || _this.state.filterVal && !newState.filterVal) {
391
+ if (newState.filterField && (newState.filterVal || _this.state.filterVal && !newState.filterVal)) {
392
392
  newState.currentPage = 0;
393
393
  _this.reload(_this.state.selectedLayer, false, newState);
394
394
  } else {
@@ -814,6 +814,13 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
814
814
  if (this.state.highlightedFeature !== prevState.highlightedFeature || this.state.features !== prevState.features || this.state.selectedFeatures !== prevState.selectedFeatures) {
815
815
  this.highlightFeatures();
816
816
  }
817
+ if (this.state.loadedLayer !== prevState.loadedLayer && this.props.showDisplayFieldOnly) {
818
+ this.setState(function (state) {
819
+ return {
820
+ filterField: state.curEditConfig.displayField
821
+ };
822
+ });
823
+ }
817
824
  }
818
825
  }, {
819
826
  key: "componentWillUnmount",
@@ -1025,12 +1025,13 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
1025
1025
  var text = LocaleUtils.tr("search.existinglayer") + ": " + existingLayerName;
1026
1026
  _this.props.showNotification("existinglayer", text);
1027
1027
  } else {
1028
+ var _existingLayer$role;
1028
1029
  var existingLayer = _this.props.layers.find(function (l) {
1029
1030
  return l.type === layer.type && l.url === layer.url;
1030
1031
  });
1031
1032
  _this.props.addLayer(_objectSpread(_objectSpread({}, layer), {}, {
1032
1033
  srcid: existingLayer === null || existingLayer === void 0 ? void 0 : existingLayer.srcid,
1033
- role: LayerRole.USERLAYER
1034
+ role: (_existingLayer$role = existingLayer === null || existingLayer === void 0 ? void 0 : existingLayer.role) !== null && _existingLayer$role !== void 0 ? _existingLayer$role : LayerRole.USERLAYER
1034
1035
  }));
1035
1036
  }
1036
1037
  if (_this.props.searchOptions.zoomToLayers && layer.bbox) {
@@ -15,21 +15,21 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
15
15
  import axios from 'axios';
16
16
  import { applyStyle } from 'ol-mapbox-style';
17
17
  import ol from 'openlayers';
18
+ export var createLayer = function createLayer(options) {
19
+ return new ol.layer.VectorTile(_objectSpread({
20
+ minResolution: options.minResolution,
21
+ maxResolution: options.maxResolution,
22
+ declutter: options.declutter,
23
+ source: new ol.source.VectorTile(_objectSpread({
24
+ projection: options.projection,
25
+ format: new ol.format.MVT({}),
26
+ url: options.url,
27
+ tileGrid: options.tileGridConfig ? new ol.tilegrid.TileGrid(_objectSpread({}, options.tileGridConfig)) : undefined
28
+ }, options.sourceConfig || {}))
29
+ }, options.layerConfig || {}));
30
+ };
18
31
  export default {
19
32
  create: function create(options) {
20
- var createLayer = function createLayer() {
21
- return new ol.layer.VectorTile(_objectSpread({
22
- minResolution: options.minResolution,
23
- maxResolution: options.maxResolution,
24
- declutter: options.declutter,
25
- source: new ol.source.VectorTile(_objectSpread({
26
- projection: options.projection,
27
- format: new ol.format.MVT({}),
28
- url: options.url,
29
- tileGrid: options.tileGridConfig ? new ol.tilegrid.TileGrid(_objectSpread({}, options.tileGridConfig)) : undefined
30
- }, options.sourceConfig || {}))
31
- }, options.layerConfig || {}));
32
- };
33
33
  var group = new ol.layer.Group();
34
34
  if (options.style) {
35
35
  axios.get(options.style).then(function (response) {
@@ -40,7 +40,7 @@ export default {
40
40
  Object.keys(glStyle.sources).forEach(function (styleSource) {
41
41
  var _glStyle$sources$styl;
42
42
  ((_glStyle$sources$styl = glStyle.sources[styleSource].url) === null || _glStyle$sources$styl === void 0 ? void 0 : _glStyle$sources$styl.startsWith(".")) && (glStyle.sources[styleSource].url = new URL(glStyle.sources[styleSource].url, options.style).href);
43
- var layer = createLayer();
43
+ var layer = createLayer(options);
44
44
  applyStyle(layer, glStyle, styleSource, options.styleOptions).then(function () {
45
45
  group.getLayers().push(layer);
46
46
  })["catch"](function (e) {
@@ -53,7 +53,7 @@ export default {
53
53
  console.warn("Unable to load style " + options.style + ": " + String(e));
54
54
  });
55
55
  } else {
56
- group.getLayers().push(createLayer());
56
+ group.getLayers().push(createLayer(options));
57
57
  }
58
58
  return group;
59
59
  }
@@ -0,0 +1,158 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
5
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
6
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
7
+ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
8
+ function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
9
+ function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
10
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
11
+ function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
12
+ function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
13
+ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
14
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
15
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
16
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
17
+ /**
18
+ * Copyright 2026 Sourcepole AG
19
+ * All rights reserved.
20
+ *
21
+ * This source code is licensed under the BSD-style license found in the
22
+ * LICENSE file in the root directory of this source tree.
23
+ */
24
+
25
+ import React from 'react';
26
+ import DrapedFeatureCollection from '@giro3d/giro3d/entities/DrapedFeatureCollection';
27
+ import PropTypes from 'prop-types';
28
+ import LayerRegistry3D from './layers/index';
29
+ var ColorLayer3D = /*#__PURE__*/function (_React$Component) {
30
+ function ColorLayer3D(props) {
31
+ var _this;
32
+ _classCallCheck(this, ColorLayer3D);
33
+ _this = _callSuper(this, ColorLayer3D, [props]);
34
+ _defineProperty(_this, "applyLayerOptions", function (layerCreator, prevOptions) {
35
+ var _this$props$map$getLa;
36
+ var options = _this.props.options;
37
+ // Reorder layer
38
+ var layerBelow = (_this$props$map$getLa = _this.props.map.getLayers(function (l) {
39
+ return l.userData.layerId === _this.props.prevLayerId;
40
+ })[0]) !== null && _this$props$map$getLa !== void 0 ? _this$props$map$getLa : null;
41
+ _this.mapLayer.moveAfter(layerBelow);
42
+ // WMS layer handles visibility and opacity internally
43
+ if (_this.props.options.type !== "wms") {
44
+ _this.mapLayer.setVisible(options.visibility);
45
+ _this.mapLayer.setOpacity(options.opacity / 255);
46
+ }
47
+ if (_this.props.options.extrusionHeight !== undefined && _this.props.options.extrusionHeight !== 0) {
48
+ _this.createUpdateExtrudedLayer(layerCreator, options, options.features !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.features));
49
+ } else if ((prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== undefined && (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== 0) {
50
+ _this.props.sceneContext.removeSceneObject(_this.props.options.id + ":extruded");
51
+ }
52
+ });
53
+ _defineProperty(_this, "createUpdateExtrudedLayer", function (layerCreator, options) {
54
+ var _options$features, _options$features$red;
55
+ var forceCreate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
56
+ var objId = options.id + ":extruded";
57
+ var makeColor = function makeColor(c) {
58
+ if (Array.isArray(c)) {
59
+ return c[0] << 16 | c[1] << 8 | c[2];
60
+ } else if (typeof c === "string") {
61
+ return parseInt(c.replace("#", ""), 16);
62
+ } else {
63
+ return c;
64
+ }
65
+ };
66
+ var obj = _this.props.sceneContext.getSceneObject(objId);
67
+ if (!obj || forceCreate) {
68
+ var _options$color;
69
+ if (obj) {
70
+ _this.props.sceneContext.removeSceneObject(objId);
71
+ }
72
+ var layercolor = makeColor((_options$color = options.color) !== null && _options$color !== void 0 ? _options$color : "#FF0000");
73
+ obj = new DrapedFeatureCollection({
74
+ source: layerCreator.createFeatureSource(_this.mapLayer, options, _this.props.sceneContext.mapCrs),
75
+ drapingMode: 'per-feature',
76
+ extrusionOffset: function extrusionOffset(feature) {
77
+ if (typeof obj.userData.extrusionHeight === "string") {
78
+ return parseFloat(feature.getProperties()[obj.userData.extrusionHeight]) || 0;
79
+ } else {
80
+ return obj.userData.extrusionHeight;
81
+ }
82
+ },
83
+ style: function style(feature) {
84
+ var _obj$userData$feature, _obj$userData$feature2;
85
+ return (_obj$userData$feature = (_obj$userData$feature2 = obj.userData.featureStyles) === null || _obj$userData$feature2 === void 0 ? void 0 : _obj$userData$feature2[feature.getId()]) !== null && _obj$userData$feature !== void 0 ? _obj$userData$feature : {
86
+ fill: {
87
+ color: layercolor,
88
+ shading: true
89
+ }
90
+ };
91
+ }
92
+ });
93
+ obj.castShadow = true;
94
+ obj.receiveShadow = true;
95
+ _this.props.sceneContext.addSceneObject(objId, obj, false, {}, false, function () {
96
+ obj.attach(_this.props.map);
97
+ });
98
+ }
99
+ obj.userData.extrusionHeight = options.extrusionHeight;
100
+ obj.userData.featureStyles = (_options$features = options.features) === null || _options$features === void 0 || (_options$features$red = _options$features.reduce) === null || _options$features$red === void 0 ? void 0 : _options$features$red.call(_options$features, function (res, feature) {
101
+ return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, feature.id, {
102
+ fill: {
103
+ color: makeColor(feature.styleOptions.fillColor),
104
+ shading: true
105
+ }
106
+ }));
107
+ }, {});
108
+ obj.opacity = _this.mapLayer.opacity();
109
+ obj.visible = _this.mapLayer.visible();
110
+ if (obj.visible) {
111
+ obj.updateStyles();
112
+ }
113
+ });
114
+ _this.mapLayer = null;
115
+ return _this;
116
+ }
117
+ _inherits(ColorLayer3D, _React$Component);
118
+ return _createClass(ColorLayer3D, [{
119
+ key: "componentDidMount",
120
+ value: function componentDidMount() {
121
+ var layerCreator = LayerRegistry3D[this.props.options.type];
122
+ if (layerCreator) {
123
+ this.mapLayer = layerCreator.create3d(this.props.options, this.props.sceneContext.mapCrs);
124
+ this.mapLayer.attach(this.props.map);
125
+ this.applyLayerOptions(layerCreator, {});
126
+ }
127
+ }
128
+ }, {
129
+ key: "componentDidUpdate",
130
+ value: function componentDidUpdate(prevProps) {
131
+ var layerCreator = LayerRegistry3D[this.props.options.type];
132
+ if (this.mapLayer && layerCreator) {
133
+ layerCreator.update3d(this.mapLayer, this.props.options, prevProps.options, this.props.sceneContext.mapCrs);
134
+ this.applyLayerOptions(layerCreator, prevProps.options);
135
+ }
136
+ }
137
+ }, {
138
+ key: "componentWillUnmount",
139
+ value: function componentWillUnmount() {
140
+ if (this.mapLayer) {
141
+ this.props.sceneContext.removeSceneObject(this.props.options.id + ":extruded");
142
+ this.mapLayer.dispose();
143
+ }
144
+ }
145
+ }, {
146
+ key: "render",
147
+ value: function render() {
148
+ return null;
149
+ }
150
+ }]);
151
+ }(React.Component);
152
+ _defineProperty(ColorLayer3D, "propTypes", {
153
+ map: PropTypes.object,
154
+ options: PropTypes.object,
155
+ prevLayerId: PropTypes.string,
156
+ sceneContext: PropTypes.object
157
+ });
158
+ export { ColorLayer3D as default };