qwc2 2026.9.10 → 2026.9.17

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 (73) hide show
  1. package/components/AttributeForm.js +59 -86
  2. package/components/AutoEditForm.js +18 -37
  3. package/components/EditUploadField.js +0 -2
  4. package/components/LinkFeatureForm.js +23 -3
  5. package/components/PluginsContainer.js +9 -2
  6. package/components/QtDesignerForm.js +72 -31
  7. package/components/ResizeableWindow.js +2 -0
  8. package/components/SideBar.js +7 -4
  9. package/components/StandardApp.js +25 -11
  10. package/components/map/OlMap.js +18 -7
  11. package/components/style/App.css +68 -57
  12. package/components/style/AttributeTableWidget.css +2 -2
  13. package/components/style/AutoEditForm.css +2 -40
  14. package/components/style/PluginsContainer.css +1 -0
  15. package/components/style/QtDesignerForm.css +5 -3
  16. package/components/widgets/ColorButton.js +4 -2
  17. package/components/widgets/FeaturesTable.js +5 -4
  18. package/components/widgets/ModalDialog.js +9 -14
  19. package/components/widgets/PopupMenu.js +17 -16
  20. package/components/widgets/TextInput.js +10 -7
  21. package/components/widgets/style/ColorButton.css +1 -1
  22. package/components/widgets/style/ModalDialog.css +1 -1
  23. package/icons/triangle.svg +7 -0
  24. package/package.json +1 -1
  25. package/plugins/Editing.js +1 -1
  26. package/plugins/GeometryDigitizer.js +2 -2
  27. package/plugins/Help.js +53 -14
  28. package/plugins/MapCompare.js +4 -2
  29. package/plugins/Redlining.js +18 -5
  30. package/plugins/ThemeBrowser.css +1 -1
  31. package/plugins/ThemeBrowser.js +5 -4
  32. package/plugins/TimeManager.js +7 -3
  33. package/plugins/ValueTool.js +1 -1
  34. package/plugins/View3D.js +2 -3
  35. package/plugins/map/EditingSupport.js +50 -10
  36. package/plugins/map3d/Draw3D.js +3 -3
  37. package/plugins/style/CookiePopup.css +1 -1
  38. package/plugins/style/MapDropImport.css +1 -1
  39. package/plugins/style/NewsPopup.css +1 -1
  40. package/plugins/style/Portal.css +3 -3
  41. package/plugins/style/SensorThingsTool.css +1 -1
  42. package/static/translations/bg-BG.json +6 -7
  43. package/static/translations/ca-ES.json +6 -7
  44. package/static/translations/cs-CZ.json +6 -7
  45. package/static/translations/de-CH.json +6 -7
  46. package/static/translations/de-DE.json +6 -7
  47. package/static/translations/en-US.json +6 -7
  48. package/static/translations/es-ES.json +6 -7
  49. package/static/translations/fi-FI.json +6 -7
  50. package/static/translations/fr-FR.json +6 -7
  51. package/static/translations/hu-HU.json +6 -7
  52. package/static/translations/it-IT.json +7 -8
  53. package/static/translations/ja-JP.json +6 -7
  54. package/static/translations/nl-NL.json +6 -7
  55. package/static/translations/no-NO.json +6 -7
  56. package/static/translations/pl-PL.json +6 -7
  57. package/static/translations/pt-BR.json +6 -7
  58. package/static/translations/pt-PT.json +6 -7
  59. package/static/translations/ro-RO.json +6 -7
  60. package/static/translations/ru-RU.json +6 -7
  61. package/static/translations/sv-SE.json +6 -7
  62. package/static/translations/tr-TR.json +6 -7
  63. package/static/translations/tsconfig.json +5 -7
  64. package/static/translations/uk-UA.json +6 -7
  65. package/stores/StandardStore.js +10 -0
  66. package/utils/ConfigUtils.js +2 -5
  67. package/utils/EditingUtils.js +4 -4
  68. package/utils/FeatureStyles.js +6 -1
  69. package/utils/IdentifyUtils.js +2 -1
  70. package/utils/ImageEditor.js +5 -4
  71. package/utils/LocaleUtils.js +5 -5
  72. package/utils/MiscUtils.js +10 -3
  73. package/utils/PermaLinkUtils.js +37 -15
@@ -223,6 +223,15 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
223
223
  _defineProperty(_this, "setRelationTables", function (relationTables) {
224
224
  _this.setState({
225
225
  relationTables: relationTables
226
+ }, function () {
227
+ if (_this.needRelationValueReload) {
228
+ _this.needRelationValueReload = false;
229
+ _this.loadRelationValues(_this.props.editContext.feature, function (newFeature) {
230
+ _this.props.setEditContext(_this.props.editContext.id, {
231
+ feature: newFeature
232
+ });
233
+ });
234
+ }
226
235
  });
227
236
  });
228
237
  _defineProperty(_this, "loadRelationValues", function (feature, callback) {
@@ -255,6 +264,8 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
255
264
  });
256
265
  callback(newFeature);
257
266
  }
267
+ } else {
268
+ callback(feature);
258
269
  }
259
270
  });
260
271
  _defineProperty(_this, "addRelationRecord", function (dataset) {
@@ -290,9 +301,10 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
290
301
  childEdit: childEdit
291
302
  });
292
303
  } else {
304
+ var _newRelationValues$da;
293
305
  var newRelationValues = _objectSpread({}, _this.props.editContext.feature.relationValues);
294
306
  newRelationValues[dataset] = _objectSpread({}, newRelationValues[dataset]);
295
- newRelationValues[dataset].features = newRelationValues[dataset].features.concat([newRelFeature]);
307
+ newRelationValues[dataset].features = ((_newRelationValues$da = newRelationValues[dataset].features) !== null && _newRelationValues$da !== void 0 ? _newRelationValues$da : []).concat([newRelFeature]);
296
308
  var newFeature = _objectSpread(_objectSpread({}, _this.props.editContext.feature), {}, {
297
309
  relationValues: newRelationValues
298
310
  });
@@ -389,24 +401,12 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
389
401
  var idx = (_this$state$childEdit = _this.state.childEdit.idx) !== null && _this$state$childEdit !== void 0 ? _this$state$childEdit : newRelationValues[dataset].features.length;
390
402
  newRelationValues[dataset] = _objectSpread({}, newRelationValues[dataset]);
391
403
  newRelationValues[dataset].features = newRelationValues[dataset].features.slice(0);
392
- newRelationValues[dataset].features[idx] = _objectSpread(_objectSpread({}, feature), {}, {
393
- __status__: "changed"
394
- });
395
- // If feature id is known, i.e. not when drawing new feature, set foreign key
396
- var changed = _this.props.editContext.changed;
397
- var relTable = _this.state.relationTables[dataset];
398
- var fkVal = relTable.pkField ? _this.props.editContext.feature.properties[relTable.pkField] : _this.props.editContext.feature.id;
399
- var fkField = _this.state.relationTables[dataset].fkField;
400
- if (_this.props.editContext.action !== "Draw" && feature.properties[fkField] !== fkVal) {
401
- newRelationValues[dataset].features[idx].properties = _objectSpread(_objectSpread({}, newRelationValues[dataset].features[idx].properties), {}, _defineProperty({}, fkField, fkVal));
402
- changed = true;
403
- }
404
+ newRelationValues[dataset].features[idx] = feature;
404
405
  var newFeature = _objectSpread(_objectSpread({}, _this.props.editContext.feature), {}, {
405
406
  relationValues: newRelationValues
406
407
  });
407
408
  _this.props.setEditContext(_this.props.editContext.id, {
408
- feature: newFeature,
409
- changed: changed
409
+ feature: newFeature
410
410
  });
411
411
  }
412
412
  _this.setState({
@@ -426,20 +426,13 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
426
426
  _this.setState({
427
427
  busy: false
428
428
  });
429
- if (!isEmpty(_this.state.relationTables)) {
430
- // Re-load relation values
431
- _this.loadRelationValues(feature, function (newFeature) {
432
- _this.props.setEditContext(_this.props.editContext.id, {
433
- feature: newFeature,
434
- changed: false
435
- });
436
- });
437
- } else {
429
+ // Re-load relation values
430
+ _this.loadRelationValues(feature, function (newFeature) {
438
431
  _this.props.setEditContext(_this.props.editContext.id, {
439
- feature: feature,
432
+ feature: newFeature,
440
433
  changed: false
441
434
  });
442
- }
435
+ });
443
436
  });
444
437
  } else {
445
438
  var featureSkel = {
@@ -754,27 +747,44 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
754
747
  }
755
748
  }
756
749
  });
757
- _defineProperty(_this, "featureCommited", function (success, result) {
758
- if (!success) {
759
- _this.commitFinished(false, result);
760
- return;
761
- }
762
- // Check for relation records which failed to commit
763
- var relationValueErrors = Object.values(result.relationValues || []).find(function (entry) {
764
- return (entry.features || []).find(function (f) {
765
- return f.error;
766
- });
767
- }) !== undefined;
768
- if (relationValueErrors) {
769
- // Relation values commit failed, switch to pick to avoid adding feature again on next attempt
770
- _this.commitFinished(false, LocaleUtils.tr("editing.relationcommitfailed"));
771
- _this.props.setEditContext(_this.props.editContext.id, {
772
- action: "Pick",
773
- feature: result,
774
- changed: true
750
+ _defineProperty(_this, "featureCommited", function (success, featureOrErrmsg) {
751
+ _this.setState({
752
+ busy: false
753
+ });
754
+ if (success) {
755
+ _this.props.refreshLayer(function (layer) {
756
+ return layer.wms_name === _this.props.editContext.mapPrefix;
775
757
  });
758
+ _this.props.setCurrentTaskBlocked(false);
759
+ // Check for relation records which failed to commit
760
+ var relationValueErrors = Object.values(featureOrErrmsg.relationValues || []).find(function (entry) {
761
+ return (entry.features || []).find(function (f) {
762
+ return f.error;
763
+ });
764
+ }) !== undefined;
765
+ if (relationValueErrors) {
766
+ // eslint-disable-next-line
767
+ alert(LocaleUtils.tr("editing.relationcommitfailed"));
768
+ // Switch to Pick mode to avoid recommitting new feature
769
+ _this.props.setEditContext(_this.props.editContext.id, {
770
+ action: 'Pick',
771
+ feature: featureOrErrmsg,
772
+ changed: true
773
+ });
774
+ } else {
775
+ _this.loadRelationValues(featureOrErrmsg, function (newFeature) {
776
+ var _this$props$onCommit, _this$props;
777
+ _this.props.setEditContext(_this.props.editContext.id, {
778
+ action: 'Pick',
779
+ feature: newFeature,
780
+ changed: false
781
+ });
782
+ (_this$props$onCommit = (_this$props = _this.props).onCommit) === null || _this$props$onCommit === void 0 || _this$props$onCommit.call(_this$props, newFeature);
783
+ });
784
+ }
776
785
  } else {
777
- _this.commitFinished(true, result);
786
+ // eslint-disable-next-line
787
+ alert(featureOrErrmsg);
778
788
  }
779
789
  });
780
790
  _defineProperty(_this, "deleteClicked", function () {
@@ -800,38 +810,6 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
800
810
  _this.props.setCurrentTaskBlocked(false);
801
811
  }
802
812
  });
803
- _defineProperty(_this, "commitFinished", function (success, result) {
804
- _this.setState({
805
- busy: false
806
- });
807
- if (success) {
808
- _this.props.refreshLayer(function (layer) {
809
- return layer.wms_name === _this.props.editContext.mapPrefix;
810
- });
811
- _this.props.setCurrentTaskBlocked(false);
812
- if (!_this.props.onCommit || !_this.props.onCommit(result)) {
813
- if (!isEmpty(_this.state.relationTables)) {
814
- // Re-load relation values
815
- _this.loadRelationValues(result, function (newFeature) {
816
- _this.props.setEditContext(_this.props.editContext.id, {
817
- action: 'Pick',
818
- feature: newFeature,
819
- changed: false
820
- });
821
- });
822
- } else {
823
- _this.props.setEditContext(_this.props.editContext.id, {
824
- action: 'Pick',
825
- feature: result,
826
- changed: false
827
- });
828
- }
829
- }
830
- } else {
831
- // eslint-disable-next-line
832
- alert(result);
833
- }
834
- });
835
813
  _defineProperty(_this, "deleteFinished", function (success, result) {
836
814
  _this.setState({
837
815
  busy: false
@@ -897,13 +875,14 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
897
875
  });
898
876
  });
899
877
  _this.form = null;
878
+ _this.needRelationValueReload = false;
900
879
  return _this;
901
880
  }
902
881
  _inherits(AttributeForm, _React$Component);
903
882
  return _createClass(AttributeForm, [{
904
883
  key: "componentDidUpdate",
905
884
  value: function componentDidUpdate(prevProps, prevState) {
906
- var _this2 = this;
885
+ var _prevProps$editContex;
907
886
  if (prevProps.editContext.changed !== this.props.editContext.changed) {
908
887
  this.props.setCurrentTaskBlocked(this.props.editContext.changed === true, LocaleUtils.tr("editing.unsavedchanged"));
909
888
  }
@@ -913,14 +892,8 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
913
892
  });
914
893
  }
915
894
  // Reload relation values if necessary
916
- var feature = this.props.editContext.feature;
917
- var prevFeature = prevProps.editContext.feature;
918
- if ((!this.props.editContext.changed || !feature.relationValues) && (this.state.relationTables !== prevState.relationTables || feature.id !== (prevFeature || {}).id)) {
919
- this.loadRelationValues(this.props.editContext.feature, function (newFeature) {
920
- _this2.props.setEditContext(_this2.props.editContext.id, {
921
- feature: newFeature
922
- });
923
- });
895
+ if (this.props.editContext.feature !== ((_prevProps$editContex = prevProps.editContext.feature) === null || _prevProps$editContex === void 0 ? void 0 : _prevProps$editContex.id)) {
896
+ this.needRelationValueReload = true;
924
897
  }
925
898
  if (this.props.editContext.feature !== prevProps.editContext.feature) {
926
899
  this.validateForm(this.props.editContext.feature);
@@ -35,6 +35,7 @@ import PropTypes from 'prop-types';
35
35
  import EditComboField from './EditComboField';
36
36
  import EditUploadField from './EditUploadField';
37
37
  import NumberInput from './widgets/NumberInput';
38
+ import TextInput from './widgets/TextInput';
38
39
  import ToggleSwitch from './widgets/ToggleSwitch';
39
40
  import './style/AutoEditForm.css';
40
41
  var AutoEditForm = /*#__PURE__*/function (_React$Component) {
@@ -85,9 +86,7 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
85
86
  _constraints$keyvalre2 = _slicedToArray(_constraints$keyvalre, 2),
86
87
  mapPrefix = _constraints$keyvalre2[0],
87
88
  keyvalrel = _constraints$keyvalre2[1];
88
- input = /*#__PURE__*/React.createElement("span", {
89
- className: "input-frame"
90
- }, /*#__PURE__*/React.createElement(EditComboField, {
89
+ input = /*#__PURE__*/React.createElement(EditComboField, {
91
90
  editIface: _this.props.iface,
92
91
  fieldId: field.id,
93
92
  keyvalrel: keyvalrel,
@@ -98,7 +97,7 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
98
97
  updateField: _this.props.updateField,
99
98
  value: value,
100
99
  values: constraints.values
101
- }));
100
+ });
102
101
  } else if (field.type === "number") {
103
102
  var precision = constraints.step > 0 ? Math.ceil(-Math.log10(constraints.step)) : 0;
104
103
  input = /*#__PURE__*/React.createElement(NumberInput, {
@@ -116,42 +115,26 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
116
115
  } else if (field.type === "date") {
117
116
  // Truncate time portion of ISO date string
118
117
  value = value.substr(0, 10);
119
- input = /*#__PURE__*/React.createElement("span", {
120
- className: "input-frame"
121
- }, /*#__PURE__*/React.createElement("input", _extends({
118
+ input = /*#__PURE__*/React.createElement("input", _extends({
122
119
  name: field.id,
123
- type: field.type
120
+ type: "date"
124
121
  }, constraints, {
125
122
  onChange: function onChange(ev) {
126
123
  return _this.props.updateField(field.id, ev.target.value);
127
124
  },
128
125
  value: value
129
- })));
126
+ }));
130
127
  } else if (field.type === "text") {
131
- if (multiline) {
132
- input = /*#__PURE__*/React.createElement("textarea", {
133
- name: field.id,
134
- onChange: function onChange(ev) {
135
- return _this.props.updateField(field.id, ev.target.value);
136
- },
137
- readOnly: readOnly,
138
- required: constraints.required,
139
- value: value
140
- });
141
- } else {
142
- input = /*#__PURE__*/React.createElement("span", {
143
- className: "input-frame"
144
- }, /*#__PURE__*/React.createElement("input", {
145
- name: field.id,
146
- onChange: function onChange(ev) {
147
- return _this.props.updateField(field.id, ev.target.value);
148
- },
149
- readOnly: readOnly,
150
- required: constraints.required,
151
- type: field.type,
152
- value: value
153
- }));
154
- }
128
+ input = /*#__PURE__*/React.createElement(TextInput, {
129
+ multiline: multiline,
130
+ name: field.id,
131
+ onChange: function onChange(text) {
132
+ return _this.props.updateField(field.id, text);
133
+ },
134
+ readOnly: readOnly,
135
+ required: constraints.required,
136
+ value: value
137
+ });
155
138
  } else if (field.type === "file") {
156
139
  input = /*#__PURE__*/React.createElement(EditUploadField, {
157
140
  constraints: constraints,
@@ -163,9 +146,7 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
163
146
  value: value
164
147
  });
165
148
  } else {
166
- input = /*#__PURE__*/React.createElement("span", {
167
- className: "input-frame"
168
- }, /*#__PURE__*/React.createElement("input", _extends({
149
+ input = /*#__PURE__*/React.createElement("input", _extends({
169
150
  name: field.id,
170
151
  type: field.type
171
152
  }, constraints, {
@@ -173,7 +154,7 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
173
154
  return _this.props.updateField(field.id, ev.target.value);
174
155
  },
175
156
  value: value
176
- })));
157
+ }));
177
158
  }
178
159
  return /*#__PURE__*/React.createElement("tr", {
179
160
  key: field.id
@@ -195,8 +195,6 @@ var EditUploadField = /*#__PURE__*/function (_React$Component) {
195
195
  });
196
196
  _this.cameraStream = null;
197
197
  _this.videoElement = null;
198
- _this.portal = document.createElement("div");
199
- document.body.appendChild(_this.portal);
200
198
  return _this;
201
199
  }
202
200
  _inherits(EditUploadField, _React$Component);
@@ -68,7 +68,7 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
68
68
  });
69
69
  _defineProperty(_this, "close", function () {
70
70
  var editContext = _this.props.editing.contexts[_this.props.editContextId];
71
- _this.props.finished(editContext.action === 'Draw' ? null : editContext.feature);
71
+ _this.props.finished(editContext.action === 'Pick' ? editContext.feature : null);
72
72
  });
73
73
  _defineProperty(_this, "hoverFeature", function (feature) {
74
74
  var layer = {
@@ -99,8 +99,13 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
99
99
  }
100
100
  }
101
101
  });
102
+ _defineProperty(_this, "onCommit", function (result) {
103
+ _this.props.finished(result);
104
+ return true;
105
+ });
102
106
  _defineProperty(_this, "onDiscard", function () {
103
107
  _this.props.finished(null);
108
+ return true;
104
109
  });
105
110
  return _this;
106
111
  }
@@ -133,14 +138,15 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
133
138
  }
134
139
  });
135
140
  }
136
- } else if (this.props.action === 'Create') {
141
+ } else if (this.props.action === 'Create' || this.props.action === 'PickGeometry') {
137
142
  var featureSkel = _objectSpread({
138
143
  type: "Feature",
139
144
  properties: {}
140
145
  }, this.props.feature);
146
+ var editAction = this.props.action === 'Create' ? 'Draw' : this.props.action;
141
147
  getFeatureTemplate(this.props.editConfig, featureSkel, this.props.iface, this.props.mapPrefix, this.props.map.projection, function (feature) {
142
148
  _this2.props.setEditContext(_this2.props.editContextId, {
143
- action: 'Draw',
149
+ action: editAction,
144
150
  geomType: _this2.props.editConfig.geomType,
145
151
  feature: feature,
146
152
  editConfig: _this2.props.editConfig,
@@ -203,6 +209,19 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
203
209
  }, /*#__PURE__*/React.createElement(Icon, {
204
210
  icon: "remove"
205
211
  }), LocaleUtils.tr("common.close"))));
212
+ } else if (editContext.action === 'PickGeometry') {
213
+ return /*#__PURE__*/React.createElement("div", {
214
+ className: "link-feature-form"
215
+ }, /*#__PURE__*/React.createElement("div", {
216
+ className: "link-feature-form-hint"
217
+ }, /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("linkfeatureform.pickhint"))), /*#__PURE__*/React.createElement("div", {
218
+ className: "link-feature-form-close"
219
+ }, /*#__PURE__*/React.createElement("button", {
220
+ className: "button",
221
+ onClick: this.close
222
+ }, /*#__PURE__*/React.createElement(Icon, {
223
+ icon: "remove"
224
+ }), LocaleUtils.tr("common.cancel"))));
206
225
  } else if (editContext.feature) {
207
226
  var drawing = editContext.action === 'Draw' && !editContext.feature.geometry && this.props.editConfig.geomType;
208
227
  return /*#__PURE__*/React.createElement("div", {
@@ -214,6 +233,7 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
214
233
  hideDelete: this.props.hideDelete,
215
234
  iface: this.props.iface,
216
235
  nested: true,
236
+ onCommit: this.onCommit,
217
237
  onDiscard: this.onDiscard,
218
238
  readOnly: this.props.readOnly,
219
239
  translations: this.props.translations
@@ -37,6 +37,7 @@ import PluginStore from '../utils/PluginStore';
37
37
  import ProcessNotifications from './ProcessNotifications';
38
38
  import WindowManager from './WindowManager';
39
39
  import './style/PluginsContainer.css';
40
+ export var AppRootPortalContext = /*#__PURE__*/React.createContext(null);
40
41
  export var MapButtonPortalContext = /*#__PURE__*/React.createContext(null);
41
42
  export var MapContainerPortalContext = /*#__PURE__*/React.createContext(null);
42
43
  export var AppInfosPortalContext = /*#__PURE__*/React.createContext(null);
@@ -50,6 +51,7 @@ var PluginsContainer = /*#__PURE__*/function (_React$Component) {
50
51
  }
51
52
  _this = _callSuper(this, PluginsContainer, [].concat(args));
52
53
  _defineProperty(_this, "state", {
54
+ rootRef: null,
53
55
  mapButtonsContainerRef: null,
54
56
  mapContainerRef: null,
55
57
  appInfosContainerRef: null,
@@ -76,6 +78,9 @@ var PluginsContainer = /*#__PURE__*/function (_React$Component) {
76
78
  });
77
79
  });
78
80
  _defineProperty(_this, "setupTouchEvents", function (el) {
81
+ _this.setState({
82
+ rootRef: el
83
+ });
79
84
  if (el) {
80
85
  el.addEventListener('touchstart', function (ev) {
81
86
  _this.touchY = ev.targetTouches[0].clientY;
@@ -245,10 +250,12 @@ var PluginsContainer = /*#__PURE__*/function (_React$Component) {
245
250
  right: 'calc(' + right + 'px)',
246
251
  bottom: 'calc(var(--bottombar-height) + ' + bottom + 'px)'
247
252
  };
248
- var haveRefs = this.state.mapButtonsContainerRef && this.state.mapContainerRef && this.state.appInfosContainerRef && this.state.bottomToolContainerRef;
253
+ var haveRefs = this.state.rootRef && this.state.mapButtonsContainerRef && this.state.mapContainerRef && this.state.appInfosContainerRef && this.state.bottomToolContainerRef;
249
254
  return /*#__PURE__*/React.createElement("div", {
250
255
  className: "plugins-container " + ((_this$props$className = this.props.className) !== null && _this$props$className !== void 0 ? _this$props$className : ""),
251
256
  ref: this.setupTouchEvents
257
+ }, /*#__PURE__*/React.createElement(AppRootPortalContext.Provider, {
258
+ value: this.state.rootRef
252
259
  }, /*#__PURE__*/React.createElement(AppInfosPortalContext.Provider, {
253
260
  value: this.state.appInfosContainerRef
254
261
  }, /*#__PURE__*/React.createElement(MapButtonPortalContext.Provider, {
@@ -257,7 +264,7 @@ var PluginsContainer = /*#__PURE__*/function (_React$Component) {
257
264
  value: this.state.mapContainerRef
258
265
  }, /*#__PURE__*/React.createElement(BottomToolPortalContext.Provider, {
259
266
  value: this.state.bottomToolContainerRef
260
- }, haveRefs ? this.renderPlugins() : null, haveRefs ? this.props.children : null)))), /*#__PURE__*/React.createElement(WindowManager, null), /*#__PURE__*/React.createElement("div", {
267
+ }, haveRefs ? this.renderPlugins() : null, haveRefs ? this.props.children : null))))), /*#__PURE__*/React.createElement(WindowManager, null), /*#__PURE__*/React.createElement("div", {
261
268
  className: "map-buttons-container",
262
269
  ref: this.setButtonContainerRef,
263
270
  style: mapContainerStyle