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
@@ -31,7 +31,6 @@ import { connect } from 'react-redux';
31
31
  import classnames from 'classnames';
32
32
  import { remove as removeDiacritics } from 'diacritics';
33
33
  import isEmpty from 'lodash.isempty';
34
- import isEqual from 'lodash.isequal';
35
34
  import mousetrap from 'mousetrap';
36
35
  import PropTypes from 'prop-types';
37
36
  import { setCurrentTask } from '../actions/task';
@@ -50,9 +49,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
50
49
  _defineProperty(_this, "state", {
51
50
  menuVisible: false,
52
51
  filter: "",
53
- submenusVisible: [],
54
- curEntry: null,
55
- keyNav: false
52
+ submenusVisible: []
56
53
  });
57
54
  _defineProperty(_this, "addKeyBindings", function (items) {
58
55
  items.forEach(function (item) {
@@ -67,84 +64,6 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
67
64
  }
68
65
  });
69
66
  });
70
- _defineProperty(_this, "onKeyPress", function (ev) {
71
- if (ev.key === 'Enter' || ev.key === 'ArrowLeft' || ev.key === 'ArrowUp' || ev.key === 'ArrowRight' || ev.key === 'ArrowDown') {
72
- if (!_this.state.curEntry) {
73
- if (ev.key === 'ArrowUp' || ev.key === 'ArrowDown') {
74
- _this.setState({
75
- curEntry: [ev.key === 'ArrowUp' ? _this.props.menuItems.length - 1 : 0]
76
- });
77
- }
78
- } else {
79
- var curEntry = _toConsumableArray(_this.state.curEntry);
80
- var stack = [_this.props.menuItems];
81
- _this.state.curEntry.forEach(function (entry) {
82
- stack.push(stack[stack.length - 1][entry].subitems);
83
- });
84
- stack.pop();
85
- var leaf = curEntry.pop();
86
- var level = stack.length - 1;
87
- if (ev.key === 'Enter') {
88
- if (!isEmpty(stack[stack.length - 1][leaf].subitems)) {
89
- _this.onSubmenuClicked(stack[stack.length - 1][leaf].key, level);
90
- } else {
91
- _this.onMenuitemClicked(stack[stack.length - 1][leaf]);
92
- }
93
- } else if (ev.key === 'ArrowLeft') {
94
- if (!isEmpty(stack[stack.length - 1][leaf].subitems) && _this.state.submenusVisible[level] === stack[stack.length - 1][leaf].key) {
95
- _this.onSubmenuClicked(stack[stack.length - 1][leaf].key, level);
96
- }
97
- } else if (ev.key === 'ArrowUp') {
98
- leaf -= 1;
99
- if (leaf >= 0 && !isEmpty(stack[stack.length - 1][leaf].subitems) && _this.state.submenusVisible[level] === stack[stack.length - 1][leaf].key) {
100
- curEntry.push(leaf);
101
- leaf = stack[stack.length - 1][leaf].subitems.length - 1;
102
- } else {
103
- while (leaf < 0 && curEntry.length > 0) {
104
- leaf = curEntry.pop();
105
- }
106
- if (leaf < 0) {
107
- leaf = _this.props.menuItems.length - 1;
108
- }
109
- }
110
- } else if (ev.key === 'ArrowRight') {
111
- if (!isEmpty(stack[stack.length - 1][leaf].subitems) && !_this.state.submenusVisible[level]) {
112
- _this.onSubmenuClicked(stack[stack.length - 1][leaf].key, level);
113
- }
114
- } else if (ev.key === 'ArrowDown') {
115
- if (!isEmpty(stack[stack.length - 1][leaf].subitems) && _this.state.submenusVisible[level] === stack[stack.length - 1][leaf].key) {
116
- curEntry.push(leaf);
117
- leaf = 0;
118
- } else {
119
- leaf += 1;
120
- while (leaf > stack[stack.length - 1].length - 1 && curEntry.length > 0) {
121
- leaf = curEntry.pop() + 1;
122
- stack.pop();
123
- }
124
- if (leaf > _this.props.menuItems.length - 1) {
125
- leaf = 0;
126
- }
127
- }
128
- }
129
- _this.setState({
130
- curEntry: [].concat(_toConsumableArray(curEntry), [leaf]),
131
- keyNav: true
132
- });
133
- }
134
- MiscUtils.killEvent(ev);
135
- } else if (ev.key === 'Escape') {
136
- _this.toggleMenu();
137
- MiscUtils.killEvent(ev);
138
- }
139
- });
140
- _defineProperty(_this, "onMouseMove", function (ev) {
141
- if (_this.state.keyNav) {
142
- _this.setState({
143
- keyNav: false
144
- });
145
- }
146
- MiscUtils.killEvent(ev);
147
- });
148
67
  _defineProperty(_this, "toggleMenu", function () {
149
68
  if (!_this.state.menuVisible && _this.props.currentTaskBlocked) {
150
69
  return;
@@ -152,17 +71,6 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
152
71
  if (!_this.state.menuVisible && _this.props.appMenuClearsTask) {
153
72
  _this.props.setCurrentTask(null);
154
73
  }
155
- if (!_this.props.keepMenuOpen) {
156
- if (!_this.state.menuVisible) {
157
- document.addEventListener('click', _this.checkCloseMenu);
158
- document.addEventListener('keydown', _this.onKeyPress, true);
159
- document.addEventListener('mousemove', _this.onMouseMove, true);
160
- } else {
161
- document.removeEventListener('click', _this.checkCloseMenu);
162
- document.removeEventListener('keydown', _this.onKeyPress, true);
163
- document.removeEventListener('mousemove', _this.onMouseMove, true);
164
- }
165
- }
166
74
  _this.props.onMenuToggled(!_this.state.menuVisible);
167
75
  if (_this.props.menuCompact) {
168
76
  _this.props.setMenuMargin(!_this.state.menuVisible ? MiscUtils.convertEmToPx(3.75) : 0, 0);
@@ -178,8 +86,8 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
178
86
  _defineProperty(_this, "checkCloseMenu", function (ev) {
179
87
  if (_this.menuEl && !_this.menuEl.contains(ev.target) && !_this.props.keepMenuOpen) {
180
88
  _this.toggleMenu();
89
+ MiscUtils.killEvent(ev);
181
90
  }
182
- MiscUtils.killEvent(ev);
183
91
  });
184
92
  _defineProperty(_this, "onSubmenuClicked", function (key, level) {
185
93
  var a = _this.state.submenusVisible[level] === key ? [] : [key];
@@ -200,102 +108,68 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
200
108
  _this.props.setCurrentTask(item.task || item.key, item.mode, item.mapClickAction || (item.identifyEnabled ? "identify" : null));
201
109
  }
202
110
  });
203
- _defineProperty(_this, "renderMenuItems", function (items, level, filter, path) {
204
- if (items) {
205
- return items.map(function (item, idx) {
206
- var active = isEqual(_this.state.curEntry, [].concat(_toConsumableArray(path), [idx]));
207
- if (item.subitems) {
208
- var _item$key;
209
- var subitems = _this.renderMenuItems(item.subitems, level + 1, filter, [].concat(_toConsumableArray(path), [idx]));
210
- if (filter && isEmpty(subitems)) {
211
- return null;
212
- }
213
- var visible = filter && !isEmpty(subitems) || _this.state.submenusVisible[level] === item.key;
214
- var className = classnames({
215
- "appmenu-submenu": true,
216
- "appmenu-submenu-active": active,
217
- "appmenu-submenu-expanded": visible
111
+ _defineProperty(_this, "renderMenuItems", function (items, level, filter) {
112
+ var submenu = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
113
+ return (items || []).map(function (item) {
114
+ if (item.subitems) {
115
+ var _item$key;
116
+ var expanded = filter || _this.state.submenusVisible[level] === item.key;
117
+ var subitems = expanded ? _this.renderMenuItems(item.subitems, level + 1, filter, true) : null;
118
+ if (filter && isEmpty(subitems)) {
119
+ return null;
120
+ }
121
+ var className = classnames({
122
+ "appmenu-menu-item": true,
123
+ "appmenu-submenu": true,
124
+ "appmenu-submenu-expanded": expanded
125
+ });
126
+ return [/*#__PURE__*/React.createElement("div", {
127
+ className: className,
128
+ key: (_item$key = item.key) !== null && _item$key !== void 0 ? _item$key : item.title,
129
+ onClick: function onClick() {
130
+ return _this.onSubmenuClicked(item.key, level);
131
+ },
132
+ onKeyDown: _this.keyNav,
133
+ onMouseOver: function onMouseOver(ev) {
134
+ return ev.target.focus();
135
+ },
136
+ tabIndex: 0
137
+ }, /*#__PURE__*/React.createElement(Icon, {
138
+ icon: item.icon,
139
+ size: "xlarge"
140
+ }), item.title ? LocaleUtils.tr(item.title) : LocaleUtils.tr("appmenu.items." + item.key)), subitems];
141
+ } else {
142
+ var trargs = item.trargs || [];
143
+ 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)));
144
+ var comment = item.comment ? LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "") + "_comment"].concat(_toConsumableArray(trargs))) : "";
145
+ if (!filter || removeDiacritics(label.toLowerCase()).match(filter) || comment && removeDiacritics(comment.toLowerCase()).match(filter)) {
146
+ var _className = classnames({
147
+ "appmenu-menu-item": true,
148
+ "appmenu-menu-item-nested": submenu
218
149
  });
219
- return /*#__PURE__*/React.createElement("li", {
220
- className: className,
221
- key: (_item$key = item.key) !== null && _item$key !== void 0 ? _item$key : item.title,
150
+ return /*#__PURE__*/React.createElement("div", {
151
+ className: _className,
152
+ key: item.key ? item.key + (item.mode || "") : item.title,
222
153
  onClick: function onClick() {
223
- return _this.onSubmenuClicked(item.key, level);
224
- },
225
- onMouseEnter: function onMouseEnter() {
226
- if (!_this.state.keyNav) {
227
- _this.setState({
228
- curEntry: [].concat(_toConsumableArray(path), [idx])
229
- });
230
- }
154
+ return _this.onMenuitemClicked(item);
231
155
  },
232
- onMouseLeave: function onMouseLeave() {
233
- if (!_this.state.keyNav) {
234
- _this.setState({
235
- curEntry: null
236
- });
237
- }
156
+ onKeyDown: _this.keyNav,
157
+ onMouseOver: function onMouseOver(ev) {
158
+ return ev.target.focus();
238
159
  },
239
- ref: function ref(el) {
240
- if (active && el && _this.state.keyNav) {
241
- el.scrollIntoView(false);
242
- }
243
- }
160
+ tabIndex: 0
244
161
  }, /*#__PURE__*/React.createElement(Icon, {
245
162
  icon: item.icon,
246
163
  size: "xlarge"
247
- }), item.title ? LocaleUtils.tr(item.title) : LocaleUtils.tr("appmenu.items." + item.key), /*#__PURE__*/React.createElement("ul", null, subitems));
248
- } else {
249
- var trargs = item.trargs || [];
250
- 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)));
251
- var comment = item.comment ? LocaleUtils.tr.apply(LocaleUtils, ["appmenu.items." + item.key + (item.mode || "") + "_comment"].concat(_toConsumableArray(trargs))) : "";
252
- if (!filter || removeDiacritics(label.toLowerCase()).match(filter) || comment && removeDiacritics(comment.toLowerCase()).match(filter)) {
253
- var _className = classnames({
254
- "appmenu-leaf": true,
255
- "appmenu-leaf-active": active
256
- });
257
- return /*#__PURE__*/React.createElement("li", {
258
- className: _className,
259
- key: item.key ? item.key + (item.mode || "") : item.title,
260
- onClick: function onClick() {
261
- return _this.onMenuitemClicked(item);
262
- },
263
- onMouseEnter: function onMouseEnter() {
264
- if (!_this.state.keyNav) {
265
- _this.setState({
266
- curEntry: [].concat(_toConsumableArray(path), [idx])
267
- });
268
- }
269
- },
270
- onMouseLeave: function onMouseLeave() {
271
- if (!_this.state.keyNav) {
272
- _this.setState({
273
- curEntry: null
274
- });
275
- }
276
- },
277
- ref: function ref(el) {
278
- if (active && el && _this.state.keyNav) {
279
- el.scrollIntoView(false);
280
- }
281
- }
282
- }, /*#__PURE__*/React.createElement(Icon, {
283
- icon: item.icon,
284
- size: "xlarge"
285
- }), /*#__PURE__*/React.createElement("span", {
286
- className: "appmenu-leaf-label"
287
- }, label, comment ? /*#__PURE__*/React.createElement("div", {
288
- className: "appmenu-leaf-comment"
289
- }, comment) : null));
290
- }
291
- return null;
164
+ }), /*#__PURE__*/React.createElement("span", {
165
+ className: "appmenu-menu-item-label"
166
+ }, label, comment ? /*#__PURE__*/React.createElement("div", {
167
+ className: "appmenu-menu-item-comment"
168
+ }, comment) : null));
292
169
  }
293
- }).filter(function (x) {
294
- return x;
295
- });
296
- } else {
297
- return null;
298
- }
170
+ return null;
171
+ }
172
+ });
299
173
  });
300
174
  _defineProperty(_this, "setFilterField", function (el) {
301
175
  _this.filterfield = el;
@@ -303,6 +177,54 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
303
177
  mousetrap(el).bind(_this.props.appMenuShortcut, _this.toggleMenu);
304
178
  }
305
179
  });
180
+ _defineProperty(_this, "focusFilterField", function (ev) {
181
+ if (ev.target.classList.contains("appmenu-menu-item-filter")) {
182
+ var _this$filterfield, _this$filterfield$foc;
183
+ (_this$filterfield = _this.filterfield) === null || _this$filterfield === void 0 || (_this$filterfield$foc = _this$filterfield.focus) === null || _this$filterfield$foc === void 0 || _this$filterfield$foc.call(_this$filterfield);
184
+ }
185
+ });
186
+ _defineProperty(_this, "clearFocus", function () {
187
+ document.activeElement.blur();
188
+ });
189
+ _defineProperty(_this, "btnKeyNav", function (ev) {
190
+ if (ev.key === 'ArrowDown') {
191
+ var _this$menuEl$children;
192
+ (_this$menuEl$children = _this.menuEl.children[0]) === null || _this$menuEl$children === void 0 || _this$menuEl$children.focus();
193
+ } else if (ev.key === 'ArrowUp') {
194
+ var _this$menuEl$children2;
195
+ (_this$menuEl$children2 = _this.menuEl.children[_this.menuEl.children.length - 1]) === null || _this$menuEl$children2 === void 0 || _this$menuEl$children2.focus();
196
+ } else {
197
+ MiscUtils.checkKeyActivate(ev);
198
+ }
199
+ });
200
+ _defineProperty(_this, "keyNav", function (ev) {
201
+ if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') {
202
+ var childCount = _this.menuEl.children.length;
203
+ var delta = ev.key === 'ArrowUp' ? -1 : 1;
204
+ var currentIndex = Array.from(_this.menuEl.children).findIndex(function (el) {
205
+ return document.activeElement === el || el.contains(document.activeElement);
206
+ });
207
+ if (currentIndex === -1) {
208
+ currentIndex = delta === 1 ? childCount - 1 : 0;
209
+ }
210
+ var next = (currentIndex + childCount + delta) % childCount;
211
+ _this.menuEl.children[next].focus();
212
+ MiscUtils.killEvent(ev);
213
+ } else if (ev.key === 'Escape') {
214
+ var _this$menuBtn, _this$menuBtn$focus;
215
+ if (!_this.props.menuCompact) {
216
+ _this.toggleMenu();
217
+ }
218
+ (_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);
219
+ MiscUtils.killEvent(ev);
220
+ } else if (ev.key === 'Enter' || ev.key === ' ') {
221
+ if (ev.target.classList.contains("appmenu-menu-item")) {
222
+ ev.target.click();
223
+ MiscUtils.killEvent(ev);
224
+ }
225
+ }
226
+ });
227
+ _this.menuBtn = null;
306
228
  _this.menuEl = null;
307
229
  _this.filterfield = null;
308
230
  _this.boundShortcuts = [];
@@ -324,11 +246,18 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
324
246
  key: "componentDidUpdate",
325
247
  value: function componentDidUpdate(prevProps, prevState) {
326
248
  var _this2 = this;
327
- if (this.state.menuVisible && !prevState.menuVisible && this.filterfield && !this.props.menuCompact) {
249
+ if (this.state.menuVisible && !prevState.menuVisible && !this.props.menuCompact) {
328
250
  // Need to wait until slide in transition is over
329
251
  setTimeout(function () {
330
- _this2.filterfield.focus();
252
+ var _this2$filterfield, _this2$filterfield$fo;
253
+ (_this2$filterfield = _this2.filterfield) === null || _this2$filterfield === void 0 || (_this2$filterfield$fo = _this2$filterfield.focus) === null || _this2$filterfield$fo === void 0 || _this2$filterfield$fo.call(_this2$filterfield);
331
254
  }, 400);
255
+ // Delay one cycle
256
+ setTimeout(function () {
257
+ return document.addEventListener('click', _this2.checkCloseMenu);
258
+ }, 0);
259
+ } else if (prevState.menuVisible && !this.state.menuVisible && !this.props.menuCompact) {
260
+ document.removeEventListener('click', this.checkCloseMenu);
332
261
  }
333
262
  }
334
263
  }, {
@@ -340,11 +269,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
340
269
  if (this.props.appMenuShortcut) {
341
270
  mousetrap.unbind(this.props.appMenuShortcut, this.toggleMenu);
342
271
  }
343
- if (this.state.menuVisible) {
344
- document.removeEventListener('click', this.checkCloseMenu);
345
- document.removeEventListener('keydown', this.onKeyPress, true);
346
- document.removeEventListener('mousemove', this.onMouseMove, true);
347
- }
272
+ document.removeEventListener('click', this.checkCloseMenu);
348
273
  }
349
274
  }, {
350
275
  key: "render",
@@ -362,14 +287,15 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
362
287
  });
363
288
  var filter = this.state.filter ? new RegExp(removeDiacritics(this.state.filter).replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"), "i") : null;
364
289
  return /*#__PURE__*/React.createElement("div", {
365
- className: className,
366
- ref: function ref(el) {
367
- _this3.menuEl = el;
368
- MiscUtils.setupKillTouchEvents(el);
369
- }
290
+ className: className
370
291
  }, /*#__PURE__*/React.createElement("div", {
371
292
  className: "appmenu-button",
372
- onMouseDown: this.toggleMenu,
293
+ onClick: this.toggleMenu,
294
+ onKeyDown: this.btnKeyNav,
295
+ ref: function ref(el) {
296
+ _this3.menuBtn = el;
297
+ },
298
+ tabIndex: 0,
373
299
  title: this.props.buttonLabel
374
300
  }, showLabel ? /*#__PURE__*/React.createElement("span", {
375
301
  className: "appmenu-label"
@@ -378,17 +304,28 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
378
304
  }, /*#__PURE__*/React.createElement(Icon, {
379
305
  icon: "menu-hamburger"
380
306
  }))), /*#__PURE__*/React.createElement("div", {
381
- className: "appmenu-menu-container"
382
- }, /*#__PURE__*/React.createElement("ul", {
383
- className: "appmenu-menu"
384
- }, this.props.showFilterField ? /*#__PURE__*/React.createElement("li", {
385
- className: "appmenu-leaf"
307
+ className: "appmenu-menu-container",
308
+ tabIndex: -1
309
+ }, /*#__PURE__*/React.createElement("div", {
310
+ className: "appmenu-menu",
311
+ inert: visible ? undefined : "true",
312
+ onMouseLeave: this.clearFocus,
313
+ ref: function ref(el) {
314
+ _this3.menuEl = el;
315
+ MiscUtils.setupKillTouchEvents(el);
316
+ }
317
+ }, this.props.showFilterField ? /*#__PURE__*/React.createElement("div", {
318
+ className: "appmenu-menu-item appmenu-menu-item-filter",
319
+ onFocus: this.focusFilterField,
320
+ onKeyDown: this.keyNav,
321
+ onMouseOver: function onMouseOver(ev) {
322
+ return ev.target.focus();
323
+ },
324
+ tabIndex: 0
386
325
  }, /*#__PURE__*/React.createElement(Icon, {
387
326
  icon: "search",
388
327
  size: "xlarge"
389
- }), /*#__PURE__*/React.createElement(InputContainer, {
390
- className: "appmenu-filter"
391
- }, /*#__PURE__*/React.createElement("input", {
328
+ }), /*#__PURE__*/React.createElement(InputContainer, null, /*#__PURE__*/React.createElement("input", {
392
329
  onChange: function onChange(ev) {
393
330
  return _this3.setState({
394
331
  filter: ev.target.value,
@@ -408,7 +345,7 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
408
345
  });
409
346
  },
410
347
  role: "suffix"
411
- }))) : null, this.renderMenuItems(this.props.menuItems, 0, filter, []))));
348
+ }))) : null, this.renderMenuItems(this.props.menuItems, 0, filter))));
412
349
  }
413
350
  }]);
414
351
  }(React.Component);
@@ -55,6 +55,7 @@ import { FeatureCache, KeyValCache, parseExpression, getFeatureTemplate } from '
55
55
  import LayerUtils from '../utils/LayerUtils';
56
56
  import LocaleUtils from '../utils/LocaleUtils';
57
57
  import MapUtils from '../utils/MapUtils';
58
+ import MiscUtils from '../utils/MiscUtils';
58
59
  import VectorLayerUtils from '../utils/VectorLayerUtils';
59
60
  import './style/AttributeTableWidget.css';
60
61
  var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
@@ -761,6 +762,8 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
761
762
  onClick: function onClick() {
762
763
  return _this2.sortBy("id");
763
764
  },
765
+ onKeyDown: MiscUtils.checkKeyActivate,
766
+ tabIndex: 0,
764
767
  title: this.translateFieldName("id")
765
768
  }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("span", {
766
769
  className: "attribtable-table-headername"
@@ -770,6 +773,8 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
770
773
  onClick: function onClick() {
771
774
  return _this2.sortBy(field.id);
772
775
  },
776
+ onKeyDown: MiscUtils.checkKeyActivate,
777
+ tabIndex: 0,
773
778
  title: _this2.translateFieldName(field.name)
774
779
  }, /*#__PURE__*/React.createElement("span", null, _this2.renderColumnResizeHandle(idx + 1, 'l'), /*#__PURE__*/React.createElement("span", {
775
780
  className: "attribtable-table-headername"
@@ -151,8 +151,7 @@ var FeatureAttributesWindow = /*#__PURE__*/function (_React$Component) {
151
151
  scrollable: true,
152
152
  title: LocaleUtils.tr("featureattributes.windowtitle")
153
153
  }, /*#__PURE__*/React.createElement("div", {
154
- className: "feature-attributes-body",
155
- role: "body"
154
+ className: "feature-attributes-body"
156
155
  }, body));
157
156
  }
158
157
  }]);
@@ -26,6 +26,7 @@ import PropTypes from 'prop-types';
26
26
  import { toggleFullscreen } from '../actions/display';
27
27
  import ConfigUtils from '../utils/ConfigUtils';
28
28
  import LocaleUtils from '../utils/LocaleUtils';
29
+ import MiscUtils from '../utils/MiscUtils';
29
30
  import './style/FullscreenSwitcher.css';
30
31
  var FullscreenSwitcher = /*#__PURE__*/function (_React$Component) {
31
32
  function FullscreenSwitcher() {
@@ -75,6 +76,8 @@ var FullscreenSwitcher = /*#__PURE__*/function (_React$Component) {
75
76
  return /*#__PURE__*/React.createElement("div", {
76
77
  className: "FullScreenSwitcher",
77
78
  onClick: this.toggleFullscreen,
79
+ onKeyDown: MiscUtils.checkKeyActivate,
80
+ tabIndex: 0,
78
81
  title: tooltip
79
82
  }, /*#__PURE__*/React.createElement("span", {
80
83
  className: this.props.fullscreen ? "minimize" : "maximize"
@@ -40,6 +40,8 @@ var Icon = /*#__PURE__*/function (_React$Component) {
40
40
  icon_disabled: this.props.disabled,
41
41
  icon_clickable: !!this.props.onClick || !!this.props.onMouseDown || !!this.props.onPointerDown
42
42
  }, "icon-" + this.props.icon, true), "icon_" + this.props.size, !!this.props.size), this.props.className, !!this.props.className));
43
+ var tabIndex = this.props.onClick ? 0 : undefined;
44
+ var onKeyDown = tabIndex !== undefined ? MiscUtils.checkKeyActivate : null;
43
45
  if (this.props.icon.startsWith(":/")) {
44
46
  var assetsPath = ConfigUtils.getAssetsPath();
45
47
  var src = assetsPath + this.props.icon.substr(1);
@@ -48,10 +50,12 @@ var Icon = /*#__PURE__*/function (_React$Component) {
48
50
  className: classes,
49
51
  onClick: this.props.disabled ? null : this.props.onClick,
50
52
  onContextMenu: MiscUtils.killEvent,
53
+ onKeyDown: onKeyDown,
51
54
  onMouseDown: this.props.onMouseDown,
52
55
  onMouseUp: this.props.onMouseUp,
53
56
  onPointerDown: this.props.onPointerDown,
54
57
  src: src,
58
+ tabIndex: tabIndex,
55
59
  title: this.props.title || undefined
56
60
  });
57
61
  } else {
@@ -59,9 +63,11 @@ var Icon = /*#__PURE__*/function (_React$Component) {
59
63
  className: classes,
60
64
  onClick: this.props.disabled ? null : this.props.onClick,
61
65
  onContextMenu: MiscUtils.killEvent,
66
+ onKeyDown: onKeyDown,
62
67
  onMouseDown: this.props.onMouseDown,
63
68
  onMouseUp: this.props.onMouseUp,
64
69
  onPointerDown: this.props.onPointerDown,
70
+ tabIndex: tabIndex,
65
71
  title: this.props.title || undefined
66
72
  });
67
73
  }
@@ -39,7 +39,7 @@ import isEmpty from 'lodash.isempty';
39
39
  import { WorkerMessageHandler } from "pdfjs-dist/build/pdf.worker";
40
40
  import Proj4js from 'proj4';
41
41
  import PropTypes from 'prop-types';
42
- import { addLayer, addLayerFeatures, removeLayer, replacePlaceholderLayer } from '../actions/layers';
42
+ import { addLayer, addLayerFeatures } from '../actions/layers';
43
43
  import EditableSelect from '../components/widgets/EditableSelect';
44
44
  import ConfigUtils from '../utils/ConfigUtils';
45
45
  import CoordinatesUtils from '../utils/CoordinatesUtils';
@@ -683,9 +683,7 @@ var ImportLayer = /*#__PURE__*/function (_React$Component) {
683
683
  layerList = /*#__PURE__*/React.createElement(LayerCatalogWidget, {
684
684
  addLayer: this.props.addLayer,
685
685
  catalog: this.state.serviceLayers,
686
- pendingRequests: this.state.pendingRequests,
687
- removeLayer: this.props.removeLayer,
688
- replacePlaceholderLayer: this.props.replacePlaceholderLayer
686
+ pendingRequests: this.state.pendingRequests
689
687
  });
690
688
  }
691
689
  var disableLocal = ConfigUtils.getConfigProp("disableImportingLocalLayers", this.props.theme);
@@ -716,8 +714,6 @@ _defineProperty(ImportLayer, "propTypes", {
716
714
  addLayer: PropTypes.func,
717
715
  addLayerFeatures: PropTypes.func,
718
716
  mapCrs: PropTypes.string,
719
- removeLayer: PropTypes.func,
720
- replacePlaceholderLayer: PropTypes.func,
721
717
  theme: PropTypes.object,
722
718
  themes: PropTypes.object
723
719
  });
@@ -728,7 +724,5 @@ export default connect(function (state) {
728
724
  };
729
725
  }, {
730
726
  addLayer: addLayer,
731
- addLayerFeatures: addLayerFeatures,
732
- removeLayer: removeLayer,
733
- replacePlaceholderLayer: replacePlaceholderLayer
727
+ addLayerFeatures: addLayerFeatures
734
728
  })(ImportLayer);
@@ -117,8 +117,7 @@ var LayerInfoWindow = /*#__PURE__*/function (_React$Component) {
117
117
  onClose: this.onClose,
118
118
  title: LocaleUtils.tr("layerinfo.title")
119
119
  }, /*#__PURE__*/React.createElement("div", {
120
- className: "layer-info-window-body",
121
- role: "body"
120
+ className: "layer-info-window-body"
122
121
  }, /*#__PURE__*/React.createElement("h4", {
123
122
  className: "layer-info-window-title"
124
123
  }, this.props.sublayer.title), /*#__PURE__*/React.createElement("div", {
@@ -68,6 +68,7 @@ var MapButton = /*#__PURE__*/function (_React$Component) {
68
68
  }, /*#__PURE__*/React.createElement("button", {
69
69
  className: "".concat(className, " ").concat(this.props.className || ""),
70
70
  onClick: this.props.onClick,
71
+ ref: this.props.buttonRef,
71
72
  title: this.props.tooltip
72
73
  }, this.props.busy ? /*#__PURE__*/React.createElement(Spinner, null) : /*#__PURE__*/React.createElement(Icon, {
73
74
  icon: this.props.icon,
@@ -80,6 +81,7 @@ _defineProperty(MapButton, "contextType", MapButtonPortalContext);
80
81
  _defineProperty(MapButton, "propTypes", {
81
82
  active: PropTypes.bool,
82
83
  busy: PropTypes.bool,
84
+ buttonRef: PropTypes.func,
83
85
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
84
86
  className: PropTypes.string,
85
87
  disabled: PropTypes.bool,
@@ -332,8 +332,7 @@ var NumericInputWindow = /*#__PURE__*/function (_React$Component) {
332
332
  scrollable: true,
333
333
  title: LocaleUtils.tr("numericinput.windowtitle")
334
334
  }, /*#__PURE__*/React.createElement("div", {
335
- className: "numeric-input-widget-body",
336
- role: "body"
335
+ className: "numeric-input-widget-body"
337
336
  }, body));
338
337
  }
339
338
  }], [{
@@ -260,7 +260,7 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
260
260
  var key = (entry.mapName || "") + "." + entry.layer + ":" + entry.feature.id;
261
261
  return /*#__PURE__*/React.createElement("div", {
262
262
  key: key,
263
- onClickCapture: function onClickCapture() {
263
+ onClick: function onClick() {
264
264
  return _this3.props.featurePicked(entry.layer, entry.feature, entry.mapName);
265
265
  },
266
266
  onMouseOut: function onMouseOut() {