qwc2 2025.11.19 → 2025.11.27

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 (68) hide show
  1. package/components/AppMenu.js +141 -204
  2. package/components/AttributeTableWidget.js +5 -0
  3. package/components/FeatureAttributesWindow.js +1 -2
  4. package/components/FullscreenSwitcher.js +3 -0
  5. package/components/Icon.js +6 -0
  6. package/components/ImportLayer.js +3 -9
  7. package/components/LayerInfoWindow.js +1 -2
  8. package/components/MapButton.js +2 -0
  9. package/components/NumericInputWindow.js +1 -2
  10. package/components/PickFeature.js +1 -1
  11. package/components/PluginsContainer.js +54 -9
  12. package/components/ResizeableWindow.js +18 -9
  13. package/components/SearchBox.js +117 -124
  14. package/components/ServiceInfoWindow.js +1 -2
  15. package/components/StandardApp.js +0 -1
  16. package/components/ThemeLayersListWindow.js +8 -7
  17. package/components/ThemeList.js +7 -2
  18. package/components/WindowManager.js +0 -1
  19. package/components/map/layers/VectorLayer.js +4 -2
  20. package/components/map3d/HeightProfile3D.js +0 -1
  21. package/components/map3d/Map3D.js +1 -1
  22. package/components/map3d/View3DSwitcher.js +2 -1
  23. package/components/map3d/drawtool/NumericInput3D.js +1 -2
  24. package/components/map3d/layers/VectorLayer3D.js +2 -2
  25. package/components/style/App.css +4 -0
  26. package/components/style/AppMenu.css +33 -48
  27. package/components/style/DefaultColorScheme.css +1 -0
  28. package/components/style/PickFeature.css +0 -6
  29. package/components/style/ResizeableWindow.css +0 -4
  30. package/components/style/SearchBox.css +0 -21
  31. package/components/widgets/ColorButton.js +7 -2
  32. package/components/widgets/ComboBox.js +18 -16
  33. package/components/widgets/EditableSelect.js +5 -10
  34. package/components/widgets/LayerCatalogWidget.js +66 -16
  35. package/components/widgets/MenuButton.js +16 -15
  36. package/components/widgets/PopupMenu.js +153 -13
  37. package/components/widgets/ToggleSwitch.js +5 -2
  38. package/components/widgets/style/ComboBox.css +7 -20
  39. package/components/widgets/style/EditableSelect.css +0 -2
  40. package/components/widgets/style/MenuButton.css +1 -17
  41. package/components/widgets/style/PopupMenu.css +20 -0
  42. package/package.json +1 -1
  43. package/plugins/AttributeTable.js +0 -1
  44. package/plugins/BackgroundSwitcher.js +104 -8
  45. package/plugins/Cyclomedia.js +1 -2
  46. package/plugins/FeatureForm.js +3 -6
  47. package/plugins/GeometryDigitizer.js +1 -2
  48. package/plugins/HeightProfile.js +2 -5
  49. package/plugins/Identify.js +2 -5
  50. package/plugins/LayerCatalog.js +2 -13
  51. package/plugins/LayerTree.js +30 -17
  52. package/plugins/MapLegend.js +1 -2
  53. package/plugins/ObjectList.js +0 -1
  54. package/plugins/Panoramax.js +1 -2
  55. package/plugins/Print.js +1 -2
  56. package/plugins/Routing.js +1 -2
  57. package/plugins/TimeManager.js +2 -5
  58. package/plugins/ValueTool.js +1 -2
  59. package/plugins/View3D.js +0 -1
  60. package/plugins/map/MeasurementSupport.js +2 -2
  61. package/plugins/map3d/Identify3D.js +1 -2
  62. package/plugins/map3d/Measure3D.js +21 -12
  63. package/plugins/style/BackgroundSwitcher.css +2 -1
  64. package/plugins/style/LayerTree.css +3 -18
  65. package/static/translations/ca-ES.json +29 -29
  66. package/static/translations/es-ES.json +34 -34
  67. package/utils/MapUtils.js +6 -0
  68. package/utils/MiscUtils.js +12 -0
@@ -22,11 +22,15 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
22
22
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
23
23
  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); }
24
24
  import React from 'react';
25
+ import { connect } from 'react-redux';
25
26
  import { remove as removeDiacritics } from 'diacritics';
26
27
  import isEmpty from 'lodash.isempty';
27
28
  import PropTypes from 'prop-types';
29
+ import { addLayer, removeLayer, replacePlaceholderLayer } from '../../actions/layers';
30
+ import { NotificationType, showNotification, closeWindow } from '../../actions/windows';
28
31
  import LayerUtils from '../../utils/LayerUtils';
29
32
  import LocaleUtils from '../../utils/LocaleUtils';
33
+ import MiscUtils from '../../utils/MiscUtils';
30
34
  import ServiceLayerUtils from '../../utils/ServiceLayerUtils';
31
35
  import Icon from '../Icon';
32
36
  import InputContainer from './InputContainer';
@@ -94,31 +98,57 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
94
98
  };
95
99
  });
96
100
  });
97
- _defineProperty(_this, "addServiceLayer", function (entry) {
101
+ _defineProperty(_this, "checkAddServiceLayer", function (entry) {
102
+ var _entry$name;
98
103
  var asGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
99
- if (entry.resource) {
104
+ var resource = entry.resource ? LayerUtils.splitLayerUrlParam(entry.resource) : null;
105
+ var existingSublayers = _this.props.layers.reduce(function (res, layer) {
106
+ var _entry$type, _entry$url;
107
+ if (layer.type === ((_entry$type = entry.type) !== null && _entry$type !== void 0 ? _entry$type : resource === null || resource === void 0 ? void 0 : resource.type) && layer.url === ((_entry$url = entry.url) !== null && _entry$url !== void 0 ? _entry$url : resource === null || resource === void 0 ? void 0 : resource.url)) {
108
+ return [].concat(_toConsumableArray(res), _toConsumableArray(LayerUtils.getSublayerNames(layer)), [layer.name]);
109
+ }
110
+ return res;
111
+ }, []);
112
+ if (existingSublayers.includes((_entry$name = entry.name) !== null && _entry$name !== void 0 ? _entry$name : resource === null || resource === void 0 ? void 0 : resource.name)) {
113
+ var _ref;
114
+ var text = (_ref = LocaleUtils.tr("themelayerslist.existinglayers") + ": " + entry.title) !== null && _ref !== void 0 ? _ref : entry.name;
115
+ var actions = [{
116
+ name: LocaleUtils.tr("themelayerslist.addanyway"),
117
+ onClick: function onClick() {
118
+ _this.addServiceLayer(entry, resource, asGroup);
119
+ return true;
120
+ }
121
+ }];
122
+ _this.props.showNotification("existinglayers", text, NotificationType.INFO, false, actions);
123
+ } else {
124
+ _this.addServiceLayer(entry, resource, asGroup);
125
+ }
126
+ });
127
+ _defineProperty(_this, "addServiceLayer", function (entry, resource) {
128
+ var asGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
129
+ _this.props.closeWindow("existinglayers");
130
+ if (resource) {
100
131
  var _entry$title;
101
- var params = LayerUtils.splitLayerUrlParam(entry.resource);
102
132
  // Create placeholder layer
103
133
  _this.props.addLayer({
104
- id: params.id,
134
+ id: resource.id,
105
135
  type: "placeholder",
106
- name: params.name,
107
- title: (_entry$title = entry.title) !== null && _entry$title !== void 0 ? _entry$title : params.name,
108
- role: params.USERLAYER,
136
+ name: resource.name,
137
+ title: (_entry$title = entry.title) !== null && _entry$title !== void 0 ? _entry$title : resource.name,
138
+ role: resource.USERLAYER,
109
139
  loading: true
110
140
  });
111
- ServiceLayerUtils.findLayers(params.type, params.url, [params], _this.props.mapCrs, function (id, layer) {
141
+ ServiceLayerUtils.findLayers(resource.type, resource.url, [resource], _this.props.mapCrs, function (id, layer) {
112
142
  if (layer) {
113
143
  if (entry.sublayers === false || !asGroup) {
114
144
  layer.sublayers = null;
115
145
  }
116
- LayerUtils.propagateLayerProperty(layer, "opacity", params.opacity);
117
- _this.props.replacePlaceholderLayer(params.id, layer);
146
+ LayerUtils.propagateLayerProperty(layer, "opacity", resource.opacity);
147
+ _this.props.replacePlaceholderLayer(resource.id, layer);
118
148
  } else {
119
149
  // eslint-disable-next-line
120
150
  alert(LocaleUtils.tr("importlayer.addfailed"));
121
- _this.props.removeLayer(params.id);
151
+ _this.props.removeLayer(resource.id);
122
152
  }
123
153
  });
124
154
  } else if (entry.type === "wms" || entry.type === "wfs" || entry.type === "wmts") {
@@ -144,6 +174,11 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
144
174
  });
145
175
  }
146
176
  }
177
+ }, {
178
+ key: "componentWillUnmount",
179
+ value: function componentWillUnmount() {
180
+ this.props.closeWindow("existinglayers");
181
+ }
147
182
  }, {
148
183
  key: "renderCatalogEntry",
149
184
  value: function renderCatalogEntry(entry, path) {
@@ -174,14 +209,16 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
174
209
  }), /*#__PURE__*/React.createElement("span", {
175
210
  className: "layer-catalog-widget-entry-contents",
176
211
  onClick: function onClick() {
177
- return type ? _this2.addServiceLayer(entry, !hasSublayers) : _this2.toggleLayerListEntry(path);
178
- }
212
+ return type ? _this2.checkAddServiceLayer(entry, !hasSublayers) : _this2.toggleLayerListEntry(path);
213
+ },
214
+ onKeyDown: MiscUtils.checkKeyActivate,
215
+ tabIndex: 0
179
216
  }, type ? /*#__PURE__*/React.createElement("span", {
180
217
  className: "layer-catalog-widget-entry-service"
181
218
  }, type) : null, entry.title), hasSublayers && type === "wms" ? /*#__PURE__*/React.createElement(Icon, {
182
219
  icon: "group",
183
220
  onClick: function onClick() {
184
- return _this2.addServiceLayer(entry, true);
221
+ return _this2.checkAddServiceLayer(entry, true);
185
222
  },
186
223
  title: LocaleUtils.tr("importlayer.asgroup")
187
224
  }) : null), entry.expanded ? sublayers : null);
@@ -234,10 +271,23 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
234
271
  _defineProperty(LayerCatalogWidget, "propTypes", {
235
272
  addLayer: PropTypes.func,
236
273
  catalog: PropTypes.array,
274
+ closeWindow: PropTypes.func,
275
+ layers: PropTypes.array,
237
276
  levelBasedIndentSize: PropTypes.bool,
238
277
  mapCrs: PropTypes.string,
239
278
  pendingRequests: PropTypes.number,
240
279
  removeLayer: PropTypes.func,
241
- replacePlaceholderLayer: PropTypes.func
280
+ replacePlaceholderLayer: PropTypes.func,
281
+ showNotification: PropTypes.func
242
282
  });
243
- export { LayerCatalogWidget as default };
283
+ export default connect(function (state) {
284
+ return {
285
+ layers: state.layers.flat
286
+ };
287
+ }, {
288
+ addLayer: addLayer,
289
+ closeWindow: closeWindow,
290
+ removeLayer: removeLayer,
291
+ replacePlaceholderLayer: replacePlaceholderLayer,
292
+ showNotification: showNotification
293
+ })(LayerCatalogWidget);
@@ -15,6 +15,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
15
15
  import React from 'react';
16
16
  import classnames from 'classnames';
17
17
  import PropTypes from 'prop-types';
18
+ import MiscUtils from '../../utils/MiscUtils';
18
19
  import Icon from '../Icon';
19
20
  import PopupMenu from './PopupMenu';
20
21
  import './style/MenuButton.css';
@@ -62,7 +63,7 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
62
63
  _inherits(MenuButton, _React$Component);
63
64
  return _createClass(MenuButton, [{
64
65
  key: "componentDidUpdate",
65
- value: function componentDidUpdate(prevProps) {
66
+ value: function componentDidUpdate(prevProps, prevState) {
66
67
  if (this.props.active !== prevProps.active && this.props.active && this.props.active !== this.state.selected) {
67
68
  this.setState({
68
69
  selected: this.props.active
@@ -74,7 +75,6 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
74
75
  value: function render() {
75
76
  var _this2 = this;
76
77
  var children = React.Children.toArray(this.props.children);
77
- var rect = this.el ? this.el.getBoundingClientRect() : null;
78
78
  var buttonContents = null;
79
79
  if (this.props.menuIcon || this.props.menuLabel) {
80
80
  buttonContents = [this.props.menuIcon ? /*#__PURE__*/React.createElement(Icon, {
@@ -97,14 +97,17 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
97
97
  "menubutton-button-active": !!this.props.active,
98
98
  "menubutton-button-hover": this.state.popup
99
99
  });
100
+ var menuClassnames = "menubutton-menu" + (this.props.menuClassName ? " " + this.props.menuClassName : "");
100
101
  return /*#__PURE__*/React.createElement("div", {
101
- className: classes,
102
- ref: function ref(el) {
103
- _this2.el = el;
104
- }
102
+ className: classes
105
103
  }, /*#__PURE__*/React.createElement("div", {
106
104
  className: buttonClassnames,
107
- onClick: this.onMenuClicked
105
+ onClick: this.onMenuClicked,
106
+ onKeyDown: MiscUtils.checkKeyActivate,
107
+ ref: function ref(el) {
108
+ _this2.el = el;
109
+ },
110
+ tabIndex: 0
108
111
  }, /*#__PURE__*/React.createElement("span", {
109
112
  className: "menubutton-button-content",
110
113
  onClick: this.onButtonClicked
@@ -115,23 +118,21 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
115
118
  })), this.props.tooltip ? /*#__PURE__*/React.createElement("span", {
116
119
  className: "menubutton-tooltip " + ("menubutton-tooltip-" + this.props.tooltipPos)
117
120
  }, this.props.tooltip) : null), this.el && this.state.popup ? /*#__PURE__*/React.createElement(PopupMenu, {
118
- className: "menubutton-menu" + (this.props.menuClassName ? " " + this.props.menuClassName : ""),
121
+ anchor: this.el,
122
+ className: menuClassnames,
119
123
  onClose: function onClose() {
120
124
  return _this2.setState({
121
125
  popup: false
122
126
  });
123
- },
124
- width: rect.width,
125
- x: rect.left,
126
- y: rect.bottom
127
+ }
127
128
  }, children.map(function (child) {
128
129
  var classNames = classnames(_defineProperty({
129
- "menubutton-menu-active": child.props.value === _this2.state.selected && !child.props.disabled,
130
- "menubutton-menu-disabled": child.props.disabled
130
+ "menubutton-menu-active": child.props.value === _this2.state.selected && !child.props.disabled
131
131
  }, child.props.className, !!child.props.className));
132
132
  return /*#__PURE__*/React.cloneElement(child, {
133
133
  className: classNames,
134
- onClickCapture: function onClickCapture() {
134
+ disabled: child.props.disabled,
135
+ onClick: function onClick() {
135
136
  return _this2.onChildClicked(child);
136
137
  }
137
138
  });
@@ -12,14 +12,71 @@ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf
12
12
  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; }
13
13
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
14
14
  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); }
15
+ /**
16
+ * Copyright 2024 Sourcepole AG
17
+ * All rights reserved.
18
+ *
19
+ * This source code is licensed under the BSD-style license found in the
20
+ * LICENSE file in the root directory of this source tree.
21
+ */
22
+
15
23
  import React from 'react';
16
24
  import ReactDOM from 'react-dom';
25
+ import classnames from 'classnames';
26
+ import isEmpty from 'lodash.isempty';
17
27
  import PropTypes from 'prop-types';
18
- var PopupMenu = /*#__PURE__*/function (_React$Component) {
28
+ import MiscUtils from '../../utils/MiscUtils';
29
+ import './style/PopupMenu.css';
30
+ var PopupMenu = /*#__PURE__*/function (_React$PureComponent) {
19
31
  function PopupMenu(props) {
20
32
  var _this;
21
33
  _classCallCheck(this, PopupMenu);
22
34
  _this = _callSuper(this, PopupMenu, [props]);
35
+ _defineProperty(_this, "setFocus", function (el) {
36
+ var _this$props$anchor;
37
+ _this.menuEl = el;
38
+ if (el && ((_this$props$anchor = _this.props.anchor) === null || _this$props$anchor === void 0 ? void 0 : _this$props$anchor.nodeName) !== "INPUT") {
39
+ _this.menuEl.focus();
40
+ }
41
+ });
42
+ _defineProperty(_this, "clearFocus", function () {
43
+ var _this$props$anchor2;
44
+ if (((_this$props$anchor2 = _this.props.anchor) === null || _this$props$anchor2 === void 0 ? void 0 : _this$props$anchor2.nodeName) === "INPUT") {
45
+ _this.props.anchor.focus();
46
+ } else {
47
+ _this.menuEl.focus();
48
+ }
49
+ });
50
+ _defineProperty(_this, "keyNav", function (ev) {
51
+ if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') {
52
+ var childCount = _this.menuEl.children.length;
53
+ var delta = ev.key === 'ArrowUp' ? -1 : 1;
54
+ var currentIndex = Array.from(_this.menuEl.children).findIndex(function (el) {
55
+ return document.activeElement === el || el.contains(document.activeElement);
56
+ });
57
+ if (currentIndex === -1) {
58
+ currentIndex = delta === 1 ? childCount - 1 : 0;
59
+ }
60
+ var next = (currentIndex + childCount + delta) % childCount;
61
+ while (_this.menuEl.children[next].tabIndex !== 0 && next !== currentIndex) {
62
+ next = (next + childCount + delta) % childCount;
63
+ }
64
+ if (next !== currentIndex) {
65
+ _this.menuEl.children[next].focus();
66
+ }
67
+ MiscUtils.killEvent(ev);
68
+ } else if (ev.key === 'Escape') {
69
+ var _this$props$onClose, _this$props, _this$props$anchor3, _this$props$anchor3$f;
70
+ (_this$props$onClose = (_this$props = _this.props).onClose) === null || _this$props$onClose === void 0 || _this$props$onClose.call(_this$props);
71
+ (_this$props$anchor3 = _this.props.anchor) === null || _this$props$anchor3 === void 0 || (_this$props$anchor3$f = _this$props$anchor3.focus) === null || _this$props$anchor3$f === void 0 || _this$props$anchor3$f.call(_this$props$anchor3);
72
+ MiscUtils.killEvent(ev);
73
+ } else if (ev.key === 'Enter' || ev.key === ' ') {
74
+ MiscUtils.killEvent(ev);
75
+ } else if (ev.key !== 'Tab' && ev.key !== 'Shift') {
76
+ var _this$props$anchor4, _this$props$anchor4$f;
77
+ (_this$props$anchor4 = _this.props.anchor) === null || _this$props$anchor4 === void 0 || (_this$props$anchor4$f = _this$props$anchor4.focus) === null || _this$props$anchor4$f === void 0 || _this$props$anchor4$f.call(_this$props$anchor4);
78
+ }
79
+ });
23
80
  _this.container = document.createElement("div");
24
81
  _this.container.id = 'popup-container';
25
82
  _this.container.style.position = 'fixed';
@@ -28,43 +85,126 @@ var PopupMenu = /*#__PURE__*/function (_React$Component) {
28
85
  _this.container.style.top = 0;
29
86
  _this.container.style.bottom = 0;
30
87
  _this.container.style.zIndex = 100000;
88
+ if (_this.props.anchor) {
89
+ _this.shields = [];
90
+ var _loop = function _loop(i) {
91
+ _this.shields[i] = document.createElement("div");
92
+ _this.shields[i].style.position = 'absolute';
93
+ _this.shields[i].style.left = "0px";
94
+ _this.shields[i].style.right = "0px";
95
+ _this.shields[i].style.top = "0px";
96
+ _this.shields[i].style.bottom = "0px";
97
+ _this.shields[i].style.pointerEvents = 'initial';
98
+ _this.shields[i].style.zIndex = 0;
99
+ setTimeout(function () {
100
+ return _this.shields[i].addEventListener('click', function () {
101
+ var _this$props$onClose2, _this$props2;
102
+ (_this$props$onClose2 = (_this$props2 = _this.props).onClose) === null || _this$props$onClose2 === void 0 || _this$props$onClose2.call(_this$props2);
103
+ });
104
+ }, 0);
105
+ _this.container.appendChild(_this.shields[i]);
106
+ };
107
+ for (var i = 0; i < 4; ++i) {
108
+ _loop(i);
109
+ }
110
+ _this.container.style.pointerEvents = 'none';
111
+ }
112
+ _this.menuEl = null;
31
113
  setTimeout(function () {
32
114
  return _this.container.addEventListener('click', function () {
33
- var _this$props$onClose, _this$props;
34
- (_this$props$onClose = (_this$props = _this.props).onClose) === null || _this$props$onClose === void 0 || _this$props$onClose.call(_this$props);
115
+ var _this$props$onClose3, _this$props3;
116
+ (_this$props$onClose3 = (_this$props3 = _this.props).onClose) === null || _this$props$onClose3 === void 0 || _this$props$onClose3.call(_this$props3);
35
117
  });
36
118
  }, 0);
37
119
  document.body.appendChild(_this.container);
38
120
  return _this;
39
121
  }
40
- _inherits(PopupMenu, _React$Component);
122
+ _inherits(PopupMenu, _React$PureComponent);
41
123
  return _createClass(PopupMenu, [{
124
+ key: "componentDidMount",
125
+ value: function componentDidMount() {
126
+ var _this$props$anchor5;
127
+ if (((_this$props$anchor5 = this.props.anchor) === null || _this$props$anchor5 === void 0 ? void 0 : _this$props$anchor5.nodeName) === "INPUT") {
128
+ this.props.anchor.addEventListener('keydown', this.keyNav);
129
+ }
130
+ }
131
+ }, {
42
132
  key: "componentWillUnmount",
43
133
  value: function componentWillUnmount() {
134
+ var _this$props$anchor6, _this$props$anchor7, _this$props$anchor7$f;
44
135
  document.body.removeChild(this.container);
136
+ if (((_this$props$anchor6 = this.props.anchor) === null || _this$props$anchor6 === void 0 ? void 0 : _this$props$anchor6.nodeName) === "INPUT") {
137
+ this.props.anchor.removeEventListener('keydown', this.keyNav);
138
+ }
139
+ (_this$props$anchor7 = this.props.anchor) === null || _this$props$anchor7 === void 0 || (_this$props$anchor7$f = _this$props$anchor7.focus) === null || _this$props$anchor7$f === void 0 || _this$props$anchor7$f.call(_this$props$anchor7);
45
140
  }
46
141
  }, {
47
142
  key: "render",
48
143
  value: function render() {
144
+ var _rect$left, _rect, _rect$bottom, _rect2, _ref, _rect$width, _rect3, _this$props$disabledI;
145
+ if (isEmpty(this.props.children)) {
146
+ return null;
147
+ }
148
+ var rect = null;
149
+ if (this.props.anchor) {
150
+ if ((this.props.anchor.parentElement.className || "").includes("input-container")) {
151
+ rect = this.props.anchor.parentElement.getBoundingClientRect();
152
+ } else {
153
+ rect = this.props.anchor.getBoundingClientRect();
154
+ }
155
+ this.shields[0].style.height = rect.top + "px";
156
+ this.shields[0].style.bottom = 0;
157
+ this.shields[1].style.width = rect.left + "px";
158
+ this.shields[1].style.right = 0;
159
+ this.shields[2].style.left = rect.right + "px";
160
+ this.shields[3].style.top = rect.bottom + "px";
161
+ }
162
+ var x = (_rect$left = (_rect = rect) === null || _rect === void 0 ? void 0 : _rect.left) !== null && _rect$left !== void 0 ? _rect$left : this.props.x;
163
+ var y = ((_rect$bottom = (_rect2 = rect) === null || _rect2 === void 0 ? void 0 : _rect2.bottom) !== null && _rect$bottom !== void 0 ? _rect$bottom : this.props.y) - 1;
164
+ var minWidth = (_ref = (_rect$width = (_rect3 = rect) === null || _rect3 === void 0 ? void 0 : _rect3.width) !== null && _rect$width !== void 0 ? _rect$width : this.props.width) !== null && _ref !== void 0 ? _ref : 0;
49
165
  var style = {
50
166
  position: 'absolute',
51
- left: this.props.x + 'px',
52
- top: this.props.y + 'px',
53
- minWidth: this.props.width + 'px',
54
- maxHeight: window.innerHeight - this.props.y + 'px',
55
- overflowY: 'auto'
167
+ left: x + 'px',
168
+ top: y + 'px',
169
+ minWidth: minWidth + 'px',
170
+ maxHeight: window.innerHeight - y - 5 + 'px',
171
+ overflowY: 'auto',
172
+ zIndex: 1,
173
+ pointerEvents: 'initial'
56
174
  };
175
+ if (this.props.setMaxWidth) {
176
+ style.maxWidth = minWidth + 'px';
177
+ }
178
+ var disabledItemClass = (_this$props$disabledI = this.props.disabledItemClass) !== null && _this$props$disabledI !== void 0 ? _this$props$disabledI : "popup-menu-item-disabled";
179
+ var children = Array.isArray(this.props.children) ? this.props.children : [this.props.children];
57
180
  return /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
58
- className: this.props.className,
59
- style: style
60
- }, this.props.children), this.container);
181
+ className: "popup-menu " + this.props.className,
182
+ onKeyDown: this.keyNav,
183
+ onMouseLeave: this.clearFocus,
184
+ ref: this.setFocus,
185
+ style: style,
186
+ tabIndex: 0
187
+ }, children.flat(Infinity).filter(Boolean).map(function (child) {
188
+ var className = classnames(_defineProperty(_defineProperty({}, disabledItemClass, child.props.disabled), child.props.className, !!child.props.className));
189
+ return /*#__PURE__*/React.cloneElement(child, {
190
+ className: className,
191
+ tabIndex: child.props.disabled ? undefined : 0,
192
+ onKeyDown: child.props.disabled ? undefined : MiscUtils.checkKeyActivate,
193
+ onMouseOver: child.props.disabled ? undefined : function (ev) {
194
+ return ev.target.focus();
195
+ }
196
+ });
197
+ })), this.container);
61
198
  }
62
199
  }]);
63
- }(React.Component);
200
+ }(React.PureComponent);
64
201
  _defineProperty(PopupMenu, "propTypes", {
202
+ anchor: PropTypes.object,
65
203
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
66
204
  className: PropTypes.string,
205
+ disabledItemClass: PropTypes.string,
67
206
  onClose: PropTypes.func,
207
+ setMaxWidth: PropTypes.bool,
68
208
  width: PropTypes.number,
69
209
  x: PropTypes.number,
70
210
  y: PropTypes.number
@@ -23,6 +23,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23
23
  import React from 'react';
24
24
  import classnames from 'classnames';
25
25
  import PropTypes from 'prop-types';
26
+ import MiscUtils from '../../utils/MiscUtils';
26
27
  import Icon from '../Icon';
27
28
  import './style/ToggleSwitch.css';
28
29
  var ToggleSwitch = /*#__PURE__*/function (_React$Component) {
@@ -52,7 +53,9 @@ var ToggleSwitch = /*#__PURE__*/function (_React$Component) {
52
53
  });
53
54
  return /*#__PURE__*/React.createElement("div", {
54
55
  className: classNames,
55
- onClick: this.onClick
56
+ onClick: this.onClick,
57
+ onKeyDown: MiscUtils.checkKeyActivate,
58
+ tabIndex: 0
56
59
  }, /*#__PURE__*/React.createElement("span", {
57
60
  className: "toggle-switch-yes"
58
61
  }, /*#__PURE__*/React.createElement(Icon, {
@@ -72,7 +75,7 @@ var ToggleSwitch = /*#__PURE__*/function (_React$Component) {
72
75
  readOnly: this.props.readOnly,
73
76
  required: this.props.required,
74
77
  style: {
75
- visibility: 'none'
78
+ visibility: 'hidden'
76
79
  },
77
80
  type: "checkbox",
78
81
  value: this.props.active
@@ -40,35 +40,18 @@ div.combobox-button > span.icon {
40
40
  flex: 0 0 1em;
41
41
  }
42
42
 
43
- div.combobox-menu {
44
- border: 1px solid var(--border-color);
45
- background-color: var(--list-bg-color);
46
- user-select: none;
47
- -webkit-touch-callout: none;
48
- -webkit-user-select: none;
49
- }
50
-
51
43
  div.combobox-menu-entry {
52
44
  padding: 0.25em;
53
45
  }
54
46
 
55
- div.combobox-menu-entry:not(.combobox-menu-entry-disabled):hover {
56
- background-color: var(--list-item-bg-color-hover);
57
- color: var(--list-item-text-color-hover);
58
- }
59
-
60
47
  div.combobox-menu-entry-active {
61
48
  background-color: var(--list-item-bg-color-active);
62
49
  color: var(--list-item-text-color-active);
63
50
  }
64
51
 
65
- div.combobox-menu-entry-active:hover {
66
- background-color: var(--list-item-bg-color-active-hover)!important;
67
- color: var(--list-item-text-color-active-hover)!important;
68
- }
69
-
70
- div.combobox-menu-entry-disabled {
71
- color: var(--text-color-disabled);
52
+ div.combobox-menu-entry-active:focus {
53
+ background-color: var(--list-item-bg-color-active-hover);
54
+ color: var(--list-item-text-color-active-hover);
72
55
  }
73
56
 
74
57
  div.combobox-menu-entry-group-header {
@@ -78,6 +61,10 @@ div.combobox-menu-entry-group-header {
78
61
  font-weight: bold;
79
62
  }
80
63
 
64
+ div.combobox-menu-entry-group-header:focus {
65
+ background-color: var(--list-section-bg-color-hover);
66
+ }
67
+
81
68
  div.combobox-menu-entry-group-header > span.icon {
82
69
  flex: 0 0 auto;
83
70
  }
@@ -11,10 +11,8 @@ div.editable-select-inputcontainer > span.icon-clear {
11
11
  }
12
12
 
13
13
  div.editable-select-dropdown {
14
- border: 1px solid var(--border-color);
15
14
  max-height: 8em;
16
15
  overflow-y: auto;
17
- background-color: var(--input-bg-color);
18
16
  }
19
17
 
20
18
  div.editable-select-dropdown > div {
@@ -64,36 +64,20 @@ div.menubutton-togglebutton span.menubotton-button-arrow {
64
64
  border-left: 1px solid var(--border-color);
65
65
  }
66
66
 
67
- div.menubutton-menu {
68
- background-color: var(--list-bg-color);
69
- border: 1px solid var(--border-color);
70
- color: var(--text-color);
71
- box-shadow: 0px 2px 4px rgba(136, 136, 136, 0.5);
72
- }
73
-
74
67
  div.menubutton-menu > div {
75
68
  padding: 0.25em;
76
69
  }
77
70
 
78
- div.menubutton-menu > div:hover {
79
- background-color: var(--list-item-bg-color-hover);
80
- color: var(--list-item-text-color-hover);
81
- }
82
-
83
71
  div.menubutton-menu > div.menubutton-menu-active {
84
72
  background-color: var(--list-item-bg-color-active);
85
73
  color: var(--list-item-text-color-active);
86
74
  }
87
75
 
88
- div.menubutton-menu > div.menubutton-menu-active:hover {
76
+ div.menubutton-menu > div.menubutton-menu-active:focus {
89
77
  background-color: var(--list-item-bg-color-active-hover);
90
78
  color: var(--list-item-text-color-active-hover);
91
79
  }
92
80
 
93
- div.menubutton-menu-disabled {
94
- color: var(--text-color-disabled);
95
- }
96
-
97
81
  span.menubutton-tooltip {
98
82
  position: absolute;
99
83
  display: none;
@@ -0,0 +1,20 @@
1
+ div.popup-menu {
2
+ background-color: var(--list-bg-color);
3
+ border: 1px solid var(--border-color);
4
+ color: var(--text-color);
5
+ box-shadow: 0px 2px 4px rgba(136, 136, 136, 0.5);
6
+ }
7
+
8
+ div.popup-menu:focus {
9
+ outline: none;
10
+ }
11
+
12
+ div.popup-menu-item-disabled {
13
+ color: var(--text-color-disabled);
14
+ }
15
+
16
+ div.popup-menu > *:focus {
17
+ background-color: var(--list-item-bg-color-hover);
18
+ color: var(--list-item-text-color-hover);
19
+ outline: none;
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2025.11.19",
3
+ "version": "2025.11.27",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -76,7 +76,6 @@ var AttributeTable = /*#__PURE__*/function (_React$Component) {
76
76
  iface: this.props.iface,
77
77
  initialLayer: (_this$props$taskData = this.props.taskData) === null || _this$props$taskData === void 0 ? void 0 : _this$props$taskData.layer,
78
78
  limitToExtent: this.props.limitToExtent,
79
- role: "body",
80
79
  showEditFormButton: this.props.showEditFormButton,
81
80
  showHiddenFields: this.props.showHiddenFields,
82
81
  showLimitToExtent: this.props.showLimitToExtent,