qwc2 2025.8.21 → 2025.8.25

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.
@@ -9,4 +9,4 @@ var CAMERA_FOV=50;var MapControls3D=/*#__PURE__*/function(_React$Component){func
9
9
  if(!el){_this.controls.removeEventListener("change",_this.updateControlsTarget);_this.fpcontrols.removeEventListener("change",_this.updateFpUrlParams);if(_this.state.firstPerson){_this.fpcontrols.disconnect()}else{_this.controls.disconnect()}_this.props.sceneContext.scene.domElement.removeEventListener("dblclick",_this.switchToFirstPersonView)}});_defineProperty(_this,"switchToFirstPersonView",function(ev){// Don't do anything if a task is set, may interfere
10
10
  if(!_this.props.currentTask&&!_this.state.firstPerson){_this.setupFirstPerson(ev)}});_defineProperty(_this,"toggleFirstPersonControls",function(){if(_this.state.firstPerson){_this.leaveFirstPerson()}else if(_this.state.pickingFirstPerson){_this.props.sceneContext.scene.domElement.removeEventListener("click",_this.setupFirstPerson);_this.props.sceneContext.scene.domElement.style.cursor="";_this.setState({pickingFirstPerson:false})}else{_this.props.sceneContext.scene.domElement.addEventListener("click",_this.setupFirstPerson,{once:true});var cursor=ConfigUtils.getAssetsPath()+"/img/person.svg";_this.props.sceneContext.scene.domElement.style.cursor="url(".concat(cursor,"), pointer");_this.setState({pickingFirstPerson:true})}});_defineProperty(_this,"setupFirstPerson",function(ev){_this.props.sceneContext.scene.domElement.style.cursor="";var rect=ev.target.getBoundingClientRect();var mouseX=(ev.clientX-rect.left)/rect.width*2-1;var mouseY=-((ev.clientY-rect.top)/rect.height)*2+1;var intersection=_this.props.sceneContext.getSceneIntersection(mouseX,mouseY,false);if(!intersection){return}var pos=intersection.point;_this.props.sceneContext.getTerrainHeightFromDTM([pos.x,pos.y]).then(function(z){var camerapos=new Vector3(pos.x,pos.y,z+_this.fpcontrols.personHeight);var targetpos=new Vector3(pos.x,pos.y+300,z+_this.fpcontrols.personHeight);_this.controls.animateTo(camerapos,targetpos,0,function(){_this.controls.disconnect();_this.fpcontrols.connect(_this.props.sceneContext);_this.fpcontrols.setView(camerapos,new Vector3(0,1,0));_this.setState({firstPerson:true,pickingFirstPerson:false})})})});_defineProperty(_this,"leaveFirstPerson",function(){if(_this.state.firstPerson){_this.setState({firstPerson:false},function(){// Need to ensure this.state.firstPerson is false to avoid endless loop
11
11
  var camerapos=_this.props.sceneContext.scene.view.camera.position;_this.fpcontrols.disconnect();_this.controls.connect(_this.props.sceneContext);_this.controls.setView(camerapos,new Vector3().addVectors(camerapos,_this.fpcontrols.lookAt));var bounds=[camerapos.x-750,camerapos.y-750,camerapos.x+750,camerapos.y+750];_this.setViewToExtent(bounds)})}});_defineProperty(_this,"home",function(){var extent=_this.props.sceneContext.map.extent;var bounds=[extent.west,extent.south,extent.east,extent.north];_this.setViewToExtent(bounds)});_defineProperty(_this,"setViewToExtent",function(bounds){var angle=arguments.length>1&&arguments[1]!==undefined?arguments[1]:0;_this.leaveFirstPerson();var fov=CAMERA_FOV/180*Math.PI;var cameraHeight=(bounds[2]-bounds[0])/(2*Math.tan(fov/2));var center={x:0.5*(bounds[0]+bounds[2]),y:0.5*(bounds[1]+bounds[3])};var camerapos=new Vector3(center.x,center.y,cameraHeight);var target=new Vector3(center.x,center.y,0);var h=_this.props.sceneContext.getTerrainHeightFromMap([center.x,center.y]);// Fall back to getTerrainHeightFromDTM if map is not yet loaded
12
- if(h===undefined){_this.props.sceneContext.getTerrainHeightFromDTM([center.x,center.y]).then(function(h2){camerapos.z+=h2;target.z+=h2;_this.controls.animateTo(camerapos,target,angle)})}else{camerapos.z+=h;target.z+=h;_this.controls.animateTo(camerapos,target,angle)}});_defineProperty(_this,"pan",function(ev,dx,dy){var panInterval=setInterval(function(){_this.props.sceneContext.scene.view.controls.panView(dx,dy)},50);ev.view.addEventListener("pointerup",function(){clearInterval(panInterval)},{once:true})});_defineProperty(_this,"tilt",function(ev,azimuth,polar){var tiltInterval=setInterval(function(){_this.props.sceneContext.scene.view.controls.tiltView(azimuth,polar)},50);ev.view.addEventListener("pointerup",function(){clearInterval(tiltInterval)},{once:true})});_defineProperty(_this,"resetTilt",function(){var camerapos=_this.props.sceneContext.scene.view.camera.position;if(_this.state.firstPerson){var newLookAt=_this.fpcontrols.lookAt.clone();newLookAt.z=0;_this.fpcontrols.setView(camerapos,newLookAt.normalize())}else{var target=_this.controls.target;var newcamerapos=new Vector3(target.x,target.y,target.distanceTo(camerapos));_this.controls.animateTo(newcamerapos,target,0)}});_defineProperty(_this,"zoom",function(ev,delta){var zoomInterval=setInterval(function(){var camerapos=_this.props.sceneContext.scene.view.camera.position;var target=_this.controls.target;var k=Math.min(150,Math.sqrt(target.distanceTo(camerapos)));_this.props.sceneContext.scene.view.controls.zoomView(delta*k)},50);ev.view.addEventListener("pointerup",function(){clearInterval(zoomInterval)},{once:true})});_defineProperty(_this,"updateUrlParams",function(){var cpos=_this.props.sceneContext.scene.view.camera.position;var tpos=_this.controls.target;UrlParams.updateParams({v3d:[cpos.x,cpos.y,cpos.z,tpos.x,tpos.y,tpos.z,0].map(function(v){return v.toFixed(1)}).join(",")});_this.props.onCameraChanged([tpos.x,tpos.y,tpos.z],[cpos.x,cpos.y,cpos.z],CAMERA_FOV)});_defineProperty(_this,"updateFpUrlParams",function(){var cpos=_this.fpcontrols.target;var lkat=_this.fpcontrols.lookAt;var h=_this.fpcontrols.personHeight;UrlParams.updateParams({v3d:[cpos.x,cpos.y,cpos.z,lkat.x,lkat.y,lkat.z,h].map(function(v){return v.toFixed(1)}).join(",")});_this.props.onCameraChanged([cpos.x,cpos.y,cpos.z],null)});_defineProperty(_this,"restoreView",function(viewState){if(viewState.camera&&viewState.target){var camera=_construct(Vector3,_toConsumableArray(viewState.camera));var target=_construct(Vector3,_toConsumableArray(viewState.target));if(viewState.personHeight>0){_this.controls.disconnect();_this.fpcontrols.connect(_this.props.sceneContext);_this.fpcontrols.setView(camera,target,viewState.personHeight);_this.setState({firstPerson:true})}else{_this.controls.setView(camera,target)}}});var sceneElement=props.sceneContext.scene.domElement;sceneElement.tabIndex=0;_this.controls=new OrbitControls3D(props.sceneContext.scene.view.camera);_this.fpcontrols=new FirstPersonControls3D(props.sceneContext.scene.view.camera);_this.controls.connect(props.sceneContext);var targetPos=props.sceneContext.scene.view.camera.position.clone();targetPos.z=0;_this.controls.target=targetPos;_this.controls.addEventListener("change",_this.updateUrlParams);_this.fpcontrols.addEventListener("change",_this.updateFpUrlParams);sceneElement.addEventListener("dblclick",_this.switchToFirstPersonView);props.onControlsSet(_this);_this.updateUrlParams();return _this}_inherits(MapControls3D,_React$Component);return _createClass(MapControls3D,[{key:"render",value:function render(){var _this2=this;var firstPersonButtonClasses=classNames({"map3d-firstperson-button":true,"map3d-firstperson-button-active":this.state.firstPerson});return[this.props.children,/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-pan","data-slot":0,key:"MapControlsPan",style:{order:1000}},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-up",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,0,1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-left",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,-1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"home",onClick:function onClick(){return _this2.home()}}),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-right",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-down",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,0,-1)}}),/*#__PURE__*/React.createElement("span",null)),this.context),/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-rotate","data-slot":0,key:"MapControlsRotate",style:{order:999}},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-up",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0,0.1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-left",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0.1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"point",onClick:function onClick(){return _this2.resetTilt()}}),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-right",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,-0.1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-down",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0,-0.1)}}),/*#__PURE__*/React.createElement("span",null)),this.context),/*#__PURE__*/ReactDOM.createPortal(!this.state.firstPerson?/*#__PURE__*/React.createElement("div",{className:"map3d-nav-zoom","data-slot":0,key:"MapControlsSpacerZoom",style:{order:998}},/*#__PURE__*/React.createElement("div",{onPointerDown:function onPointerDown(ev){return _this2.zoom(ev,+1)}},/*#__PURE__*/React.createElement(Icon,{icon:"plus"})),/*#__PURE__*/React.createElement("div",{onPointerDown:function onPointerDown(ev){return _this2.zoom(ev,-1)}},/*#__PURE__*/React.createElement(Icon,{icon:"minus"}))):null,this.context),/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:firstPersonButtonClasses,"data-slot":0,key:"MapControlsFirstPerson",onClick:this.toggleFirstPersonControls,style:{order:997}},/*#__PURE__*/React.createElement(Icon,{icon:"person"})),this.context),this.props.controlsPosition!=="bottom"?/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-spacer",key:"MapControlsSpacer",style:{order:997}}),this.context):null]}}])}(React.Component);_defineProperty(MapControls3D,"contextType",MapButtonPortalContext);_defineProperty(MapControls3D,"propTypes",{children:PropTypes.oneOfType([PropTypes.node,PropTypes.func]),controlsPosition:PropTypes.string,currentTask:PropTypes.string,onCameraChanged:PropTypes.func,onControlsSet:PropTypes.func,sceneContext:PropTypes.object});export default connect(function(state){return{currentTask:state.task.id}},{})(MapControls3D);
12
+ if(h===undefined){_this.props.sceneContext.getTerrainHeightFromDTM([center.x,center.y]).then(function(h2){camerapos.z+=h2;target.z+=h2;_this.controls.animateTo(camerapos,target,angle)})}else{camerapos.z+=h;target.z+=h;_this.controls.animateTo(camerapos,target,angle)}});_defineProperty(_this,"pan",function(ev,dx,dy){var panInterval=setInterval(function(){_this.props.sceneContext.scene.view.controls.panView(dx,dy)},50);ev.view.addEventListener("pointerup",function(){clearInterval(panInterval)},{once:true})});_defineProperty(_this,"tilt",function(ev,azimuth,polar){var tiltInterval=setInterval(function(){_this.props.sceneContext.scene.view.controls.tiltView(azimuth,polar)},50);ev.view.addEventListener("pointerup",function(){clearInterval(tiltInterval)},{once:true})});_defineProperty(_this,"resetTilt",function(){var camerapos=_this.props.sceneContext.scene.view.camera.position;if(_this.state.firstPerson){var newLookAt=_this.fpcontrols.lookAt.clone();newLookAt.z=0;_this.fpcontrols.setView(camerapos,newLookAt.normalize())}else{var target=_this.controls.target;var newcamerapos=new Vector3(target.x,target.y,target.distanceTo(camerapos));_this.controls.animateTo(newcamerapos,target,0)}});_defineProperty(_this,"zoom",function(ev,delta){var zoomInterval=setInterval(function(){var camerapos=_this.props.sceneContext.scene.view.camera.position;var target=_this.controls.target;var k=Math.min(150,Math.sqrt(target.distanceTo(camerapos)));_this.props.sceneContext.scene.view.controls.zoomView(delta*k)},50);ev.view.addEventListener("pointerup",function(){clearInterval(zoomInterval)},{once:true})});_defineProperty(_this,"updateUrlParams",function(){var cpos=_this.props.sceneContext.scene.view.camera.position;var tpos=_this.controls.target;UrlParams.updateParams({v3d:[cpos.x,cpos.y,cpos.z,tpos.x,tpos.y,tpos.z,0].map(function(v){return v.toFixed(1)}).join(",")});_this.props.onCameraChanged([tpos.x,tpos.y,tpos.z],[cpos.x,cpos.y,cpos.z],CAMERA_FOV)});_defineProperty(_this,"updateFpUrlParams",function(){var cpos=_this.fpcontrols.target;var lkat=_this.fpcontrols.lookAt;var h=_this.fpcontrols.personHeight;UrlParams.updateParams({v3d:[cpos.x,cpos.y,cpos.z,lkat.x,lkat.y,lkat.z,h].map(function(v){return v.toFixed(1)}).join(",")});_this.props.onCameraChanged([cpos.x,cpos.y,cpos.z],null)});_defineProperty(_this,"restoreView",function(viewState){if(viewState.camera&&viewState.target){var camera=_construct(Vector3,_toConsumableArray(viewState.camera));var target=_construct(Vector3,_toConsumableArray(viewState.target));if(viewState.personHeight>0){_this.controls.disconnect();_this.fpcontrols.connect(_this.props.sceneContext);_this.fpcontrols.setView(camera,target,viewState.personHeight);_this.setState({firstPerson:true})}else{_this.controls.setView(camera,target)}}});var sceneElement=props.sceneContext.scene.domElement;sceneElement.tabIndex=0;_this.controls=new OrbitControls3D(props.sceneContext.scene.view.camera);_this.fpcontrols=new FirstPersonControls3D(props.sceneContext.scene.view.camera);_this.controls.connect(props.sceneContext);var targetPos=props.sceneContext.scene.view.camera.position.clone();targetPos.z=0;_this.controls.target=targetPos;_this.controls.addEventListener("change",_this.updateUrlParams);_this.fpcontrols.addEventListener("change",_this.updateFpUrlParams);sceneElement.addEventListener("dblclick",_this.switchToFirstPersonView);props.onControlsSet(_this);_this.updateUrlParams();return _this}_inherits(MapControls3D,_React$Component);return _createClass(MapControls3D,[{key:"render",value:function render(){var _this2=this;var firstPersonButtonClasses=classNames({"map3d-firstperson-button":true,"map3d-firstperson-button-active":this.state.firstPerson});return[this.props.children,/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-pan","data-slot":0,key:"MapControlsPan",style:{order:1000}},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-up",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,0,1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-left",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,-1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"home",onClick:function onClick(){return _this2.home()}}),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-right",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"chevron-down",onPointerDown:function onPointerDown(ev){return _this2.pan(ev,0,-1)}}),/*#__PURE__*/React.createElement("span",null)),this.context),/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-rotate","data-slot":0,key:"MapControlsRotate",style:{order:999}},/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-up",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0,0.1)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-left",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0.1,0)}}),/*#__PURE__*/React.createElement(Icon,{icon:"point",onClick:function onClick(){return _this2.resetTilt()}}),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-right",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,-0.1,0)}}),/*#__PURE__*/React.createElement("span",null),/*#__PURE__*/React.createElement(Icon,{icon:"tilt-down",onPointerDown:function onPointerDown(ev){return _this2.tilt(ev,0,-0.1)}}),/*#__PURE__*/React.createElement("span",null)),this.context),/*#__PURE__*/ReactDOM.createPortal(!this.state.firstPerson?/*#__PURE__*/React.createElement("div",{className:"map3d-nav-zoom","data-slot":0,key:"MapControlsSpacerZoom",style:{order:998}},/*#__PURE__*/React.createElement("div",{onPointerDown:function onPointerDown(ev){return _this2.zoom(ev,+1)}},/*#__PURE__*/React.createElement(Icon,{icon:"plus"})),/*#__PURE__*/React.createElement("div",{onPointerDown:function onPointerDown(ev){return _this2.zoom(ev,-1)}},/*#__PURE__*/React.createElement(Icon,{icon:"minus"}))):null,this.context),/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:firstPersonButtonClasses,"data-slot":0,key:"MapControlsFirstPerson",onClick:this.toggleFirstPersonControls,style:{order:997}},/*#__PURE__*/React.createElement(Icon,{icon:"person"})),this.context),this.props.controlsPosition!=="bottom"?/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div",{className:"map3d-nav-spacer",key:"MapControlsSpacer",style:{order:996}}),this.context):null]}}])}(React.Component);_defineProperty(MapControls3D,"contextType",MapButtonPortalContext);_defineProperty(MapControls3D,"propTypes",{children:PropTypes.oneOfType([PropTypes.node,PropTypes.func]),controlsPosition:PropTypes.string,currentTask:PropTypes.string,onCameraChanged:PropTypes.func,onControlsSet:PropTypes.func,sceneContext:PropTypes.object});export default connect(function(state){return{currentTask:state.task.id}},{})(MapControls3D);
@@ -6,4 +6,4 @@ function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */import React from"react";import classNames from"classnames";import PropTypes from"prop-types";import Icon from"../Icon";import"./style/NumberInput.css";var NumberInput=/*#__PURE__*/function(_React$Component){function NumberInput(){var _this;_classCallCheck(this,NumberInput);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}_this=_callSuper(this,NumberInput,[].concat(args));_defineProperty(_this,"state",{propValue:"",value:"",changed:false,valid:false});_defineProperty(_this,"onChange",function(ev){var len=ev.target.value.length;var value=ev.target.value.substring(_this.props.prefix.length,len-_this.props.suffix.length);_this.setState({value:value,changed:true})});_defineProperty(_this,"currentFloatValue",function(){var floatValue=parseFloat(_this.state.value);return isNaN(floatValue)?null:floatValue});_defineProperty(_this,"startStep",function(delta){if(_this.props.disabled||_this.props.readOnly){return}_this.props.onChange(_this.constrainValue(_this.currentFloatValue()+delta));var stepInterval=null;var stepTimeout=setTimeout(function(){stepInterval=setInterval(function(){_this.props.onChange(_this.constrainValue(_this.currentFloatValue()+delta))},50)},500);document.addEventListener("pointerup",function(){clearTimeout(stepTimeout);clearInterval(stepInterval)},{once:true})});_defineProperty(_this,"onKeyDown",function(ev){if(ev.key==="Enter"){_this.commit()}// Ensure prefix/suffix isn't changed
8
8
  var selStart=ev.target.selectionStart;var selEnd=ev.target.selectionEnd;var len=ev.target.value.length;var startOffset=ev.key==="Backspace"&&selStart===selEnd?1:0;var endOffset=ev.key==="Delete"&&selStart===selEnd?1:0;if(selStart<_this.props.prefix.length+startOffset||selEnd>len-_this.props.suffix.length-endOffset){ev.preventDefault()}});_defineProperty(_this,"commit",function(){if(_this.state.changed){var value=_this.constrainValue(_this.currentFloatValue());_this.setState({value:value===null?"":value.toFixed(_this.props.decimals)});_this.props.onChange(value)}});_defineProperty(_this,"constrainValue",function(value){if(value===null){return null}if(_this.props.min!==undefined){value=Math.max(_this.props.min,value)}if(_this.props.max!==undefined){value=Math.min(_this.props.max,value)}var k=Math.pow(10,_this.props.decimals);return Math.round(value*k)/k});_defineProperty(_this,"setupSelectionListener",function(event){var input=event.target;var selectionHandler=function selectionHandler(ev){if(ev.target===input){// Ensure prefix/suffix isn't selected
9
- var len=input.value.length;var prefixLen=_this.props.prefix.length;var suffixLen=_this.props.suffix.length;var selStart=Math.min(Math.max(input.selectionStart,prefixLen),len-suffixLen);var selEnd=Math.max(Math.min(input.selectionEnd,len-suffixLen),prefixLen);if(selStart!==input.selectionStart||selEnd!==input.selectionEnd){input.setSelectionRange(selStart,selEnd)}}};document.addEventListener("selectionchange",selectionHandler);input.addEventListener("blur",function(){document.removeEventListener("selectionchange",selectionHandler)},{once:true})});return _this}_inherits(NumberInput,_React$Component);return _createClass(NumberInput,[{key:"render",value:function render(){var _this$props$step,_this2=this;var className=classNames({"number-input":true,"number-input-mobile":this.props.mobile,"number-input-normal":!this.props.mobile,"number-input-disabled":this.props.disabled||this.props.readOnly,"number-input-invalid":this.props.required&&!this.state.value});var style={};if(!this.props.fitParent){var paddingLength=(this.props.mobile?4:1.5)+"em";var prefixSuffixLength=this.props.prefix.length+this.props.suffix.length+"ch";var numberLength=2+Math.max((this.props.min||0).toFixed(this.props.decimals).length,(this.props.max||0).toFixed(this.props.decimals).length)+"ch";style.minWidth="calc(".concat(paddingLength," + ").concat(prefixSuffixLength," + ").concat(numberLength,")")}var step=(_this$props$step=this.props.step)!==null&&_this$props$step!==void 0?_this$props$step:Math.pow(10,-this.props.decimals);var plusIcon=this.props.mobile?"plus":"chevron-up";var minusIcon=this.props.mobile?"minus":"chevron-down";return/*#__PURE__*/React.createElement("div",{className:className+" "+this.props.className},/*#__PURE__*/React.createElement("input",{disabled:this.props.disabled,inputMode:"numeric",onBlur:this.commit,onChange:this.onChange,onFocus:this.setupSelectionListener,onKeyDown:this.onKeyDown,placeholder:this.props.placeholder,readOnly:this.props.readOnly,required:this.props.required,style:style,type:"text",value:this.props.prefix+this.state.value+this.props.suffix}),/*#__PURE__*/React.createElement("input",{name:this.props.name,required:this.props.required,type:"hidden",value:this.state.value}),/*#__PURE__*/React.createElement(Icon,{icon:plusIcon,onPointerDown:function onPointerDown(){return _this2.startStep(+step)}}),/*#__PURE__*/React.createElement(Icon,{icon:minusIcon,onPointerDown:function onPointerDown(){return _this2.startStep(-step)}}))}}],[{key:"getDerivedStateFromProps",value:function getDerivedStateFromProps(nextProps,state){if(state.propValue!==nextProps.value){return{propValue:nextProps.value,value:typeof nextProps.value==="number"?nextProps.value.toFixed(nextProps.decimals):"",changed:false}}return null}}])}(React.Component);_defineProperty(NumberInput,"propTypes",{className:PropTypes.string,decimals:PropTypes.number,disabled:PropTypes.bool,fitParent:PropTypes.bool,max:PropTypes.number,min:PropTypes.number,mobile:PropTypes.bool,name:PropTypes.string,onChange:PropTypes.func,placeholder:PropTypes.string,prefix:PropTypes.string,readOnly:PropTypes.bool,required:PropTypes.bool,step:PropTypes.number,style:PropTypes.object,suffix:PropTypes.string,value:PropTypes.number});_defineProperty(NumberInput,"defaultProps",{className:"",decimals:0,mobile:false,prefix:"",suffix:""});export{NumberInput as default};
9
+ var len=input.value.length;var prefixLen=_this.props.prefix.length;var suffixLen=_this.props.suffix.length;var selStart=Math.min(Math.max(input.selectionStart,prefixLen),len-suffixLen);var selEnd=Math.max(Math.min(input.selectionEnd,len-suffixLen),prefixLen);if(selStart!==input.selectionStart||selEnd!==input.selectionEnd){input.setSelectionRange(selStart,selEnd)}}};document.addEventListener("selectionchange",selectionHandler);input.addEventListener("blur",function(){document.removeEventListener("selectionchange",selectionHandler)},{once:true})});return _this}_inherits(NumberInput,_React$Component);return _createClass(NumberInput,[{key:"render",value:function render(){var _this$props$step,_this2=this;var className=classNames({"number-input":true,"number-input-mobile":this.props.mobile,"number-input-normal":!this.props.mobile,"number-input-disabled":this.props.disabled||this.props.readOnly,"number-input-invalid":this.props.required&&!this.state.value});var style={};if(!this.props.fitParent){var paddingLength=(this.props.mobile?4:1.5)+"em";var prefixSuffixLength=this.props.prefix.length+this.props.suffix.length+"ch";var numberLength=2+Math.max((this.props.min||0).toFixed(this.props.decimals).length,(this.props.max||0).toFixed(this.props.decimals).length)+"ch";style.minWidth="calc(".concat(paddingLength," + ").concat(prefixSuffixLength," + ").concat(numberLength,")")}var step=(_this$props$step=this.props.step)!==null&&_this$props$step!==void 0?_this$props$step:Math.pow(10,-this.props.decimals);var plusIcon=this.props.mobile?"plus":"chevron-up";var minusIcon=this.props.mobile?"minus":"chevron-down";return/*#__PURE__*/React.createElement("div",{className:className+" "+this.props.className},/*#__PURE__*/React.createElement("input",{disabled:this.props.disabled,inputMode:"numeric",onBlur:this.commit,onChange:this.onChange,onFocus:this.setupSelectionListener,onKeyDown:this.onKeyDown,placeholder:this.props.placeholder,readOnly:this.props.readOnly,required:this.props.required,style:style,type:"text",value:this.props.prefix+this.state.value+this.props.suffix}),/*#__PURE__*/React.createElement("input",{name:this.props.name,required:this.props.required,type:"hidden",value:this.state.value}),this.props.hideArrows?[/*#__PURE__*/React.createElement(Icon,{icon:plusIcon,key:"ArrowPlus",onPointerDown:function onPointerDown(){return _this2.startStep(+step)}}),/*#__PURE__*/React.createElement(Icon,{icon:minusIcon,key:"ArrowMinus",onPointerDown:function onPointerDown(){return _this2.startStep(-step)}})]:null)}}],[{key:"getDerivedStateFromProps",value:function getDerivedStateFromProps(nextProps,state){if(state.propValue!==nextProps.value){return{propValue:nextProps.value,value:typeof nextProps.value==="number"?nextProps.value.toFixed(nextProps.decimals):"",changed:false}}return null}}])}(React.Component);_defineProperty(NumberInput,"propTypes",{className:PropTypes.string,decimals:PropTypes.number,disabled:PropTypes.bool,fitParent:PropTypes.bool,hideArrows:PropTypes.bool,max:PropTypes.number,min:PropTypes.number,mobile:PropTypes.bool,name:PropTypes.string,onChange:PropTypes.func,placeholder:PropTypes.string,prefix:PropTypes.string,readOnly:PropTypes.bool,required:PropTypes.bool,step:PropTypes.number,style:PropTypes.object,suffix:PropTypes.string,value:PropTypes.number});_defineProperty(NumberInput,"defaultProps",{className:"",decimals:0,mobile:false,prefix:"",suffix:""});export{NumberInput as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2025.08.21",
3
+ "version": "2025.08.25",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -4,7 +4,7 @@ function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
6
6
  * LICENSE file in the root directory of this source tree.
7
- */import React from"react";import{connect}from"react-redux";import ol from"openlayers";import PropTypes from"prop-types";import{changeZoomLevel,setDisplayCrs}from"../actions/map";import{openExternalUrl,setBottombarHeight}from"../actions/windows";import CoordinateDisplayer from"../components/CoordinateDisplayer";import InputContainer from"../components/widgets/InputContainer";import CoordinatesUtils from"../utils/CoordinatesUtils";import LocaleUtils from"../utils/LocaleUtils";import MapUtils from"../utils/MapUtils";import"./style/BottomBar.css";/**
7
+ */import React from"react";import{connect}from"react-redux";import ol from"openlayers";import PropTypes from"prop-types";import{changeZoomLevel,setDisplayCrs}from"../actions/map";import{openExternalUrl,setBottombarHeight}from"../actions/windows";import CoordinateDisplayer from"../components/CoordinateDisplayer";import InputContainer from"../components/widgets/InputContainer";import NumberInput from"../components/widgets/NumberInput";import CoordinatesUtils from"../utils/CoordinatesUtils";import LocaleUtils from"../utils/LocaleUtils";import MapUtils from"../utils/MapUtils";import"./style/BottomBar.css";/**
8
8
  * Bottom bar, displaying mouse coordinate, scale, etc.
9
9
  */var BottomBar=/*#__PURE__*/function(_React$Component){function BottomBar(){var _this;_classCallCheck(this,BottomBar);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}_this=_callSuper(this,BottomBar,[].concat(args));_defineProperty(_this,"state",{scale:0});_defineProperty(_this,"renderLink",function(entry){var _entry$labelMsgId;return/*#__PURE__*/React.createElement("a",{href:entry.url,key:(_entry$labelMsgId=entry.labelMsgId)!==null&&_entry$labelMsgId!==void 0?_entry$labelMsgId:entry.label,onClick:function onClick(ev){return _this.openUrl(ev,entry.url,entry.urlTarget,entry.labelMsgId?LocaleUtils.tr(entry.labelMsgId):entry.label,entry.icon)}},/*#__PURE__*/React.createElement("span",{className:"extra_label"},entry.labelMsgId?LocaleUtils.tr(entry.labelMsgId):entry.label))});_defineProperty(_this,"initScaleBar",function(el){_this.scalebar=new ol.control.ScaleLine(_objectSpread({className:"bottombar-scalebar",target:el,minWidth:64,units:"metric"},_this.props.scalebarOptions));MapUtils.getHook(MapUtils.GET_MAP).addControl(_this.scalebar)});_defineProperty(_this,"openUrl",function(ev,url,target,title,icon){if(target==="iframe"){target=":iframedialog:externallinkiframe"}_this.props.openExternalUrl(url,target,{title:title,icon:icon});ev.preventDefault()});_defineProperty(_this,"setScale",function(value){var scale=parseInt(value,10);if(!isNaN(scale)){var zoom=MapUtils.computeZoom(_this.props.map.scales,scale);_this.props.changeZoomLevel(zoom)}else{_this.props.changeZoomLevel(_this.props.map.zoom)}});_defineProperty(_this,"storeHeight",function(el){if(el){_this.props.setBottombarHeight(el.clientHeight)}});return _this}_inherits(BottomBar,_React$Component);return _createClass(BottomBar,[{key:"componentWillUnmount",value:function componentWillUnmount(){if(this.scalebar){var _MapUtils$getHook,_MapUtils$getHook$rem;(_MapUtils$getHook=MapUtils.getHook(MapUtils.GET_MAP))===null||_MapUtils$getHook===void 0||(_MapUtils$getHook$rem=_MapUtils$getHook.removeControl)===null||_MapUtils$getHook$rem===void 0||_MapUtils$getHook$rem.call(_MapUtils$getHook,this.scalebar)}}},{key:"componentDidUpdate",value:function componentDidUpdate(prevProps){if(this.props.map!==prevProps.map){this.setState({scale:Math.round(MapUtils.computeForZoom(this.props.map.scales,this.props.map.zoom))})}}},{key:"render",value:function render(){var _this2=this;if(this.props.fullscreen){return null}var leftBottomLinks=(this.props.additionalBottomBarLinks||[]).filter(function(entry){return entry.side==="left"}).map(this.renderLink);var rightBottomLinks=(this.props.additionalBottomBarLinks||[]).filter(function(entry){return entry.side!=="left"}).map(this.renderLink);if(this.props.viewertitleUrl){var entry={url:this.props.viewertitleUrl,urlTarget:this.props.viewertitleUrlTarget,label:LocaleUtils.tr("bottombar.viewertitle_label"),icon:this.props.viewertitleUrlIcon};rightBottomLinks.push(this.renderLink(entry))}if(this.props.termsUrl){var _entry={url:this.props.termsUrl,urlTarget:this.props.termsUrlTarget,label:LocaleUtils.tr("bottombar.terms_label"),icon:this.props.termsUrlIcon};rightBottomLinks.push(this.renderLink(_entry))}var enabledMouseCrs=[].concat(_toConsumableArray(this.props.additionalMouseCrs||[]),[this.props.map.projection,"EPSG:4326"]);// eslint-disable-next-line no-unused-vars
10
- var availableCRS=Object.fromEntries(Object.entries(CoordinatesUtils.getAvailableCRS()).filter(function(_ref){var _ref2=_slicedToArray(_ref,2),key=_ref2[0],value=_ref2[1];return enabledMouseCrs.includes(key)}));var scalebar=null;if(this.props.displayScalebar){scalebar=/*#__PURE__*/React.createElement("div",{className:"bottombar-scalebar-container",ref:this.initScaleBar})}var coordinates=null;if(this.props.displayCoordinates){coordinates=/*#__PURE__*/React.createElement("div",{className:"controlgroup"},/*#__PURE__*/React.createElement("span",{className:"bottombar-mousepos-label"},LocaleUtils.tr("bottombar.mousepos_label"),":\xA0"),/*#__PURE__*/React.createElement(CoordinateDisplayer,{className:"bottombar-mousepos",coordinateFormatter:this.props.coordinateFormatter,displayCrs:this.props.map.displayCrs,mapCrs:this.props.map.projection}),/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this2.props.setDisplayCrs(ev.target.value)},value:this.props.map.displayCrs},Object.keys(availableCRS).map(function(crs){return/*#__PURE__*/React.createElement("option",{key:crs,value:crs},availableCRS[crs].label)})))}var scales=null;if(this.props.displayScales){scales=/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"bottombar-scales-label"},LocaleUtils.tr("bottombar.scale_label"),":\xA0"),/*#__PURE__*/React.createElement(InputContainer,{className:"bottombar-scale-combo"},/*#__PURE__*/React.createElement("span",{className:"bottombar-scale-combo-prefix",role:"prefix"}," 1 : "),/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this2.props.changeZoomLevel(parseInt(ev.target.value,10))},role:"input",value:Math.round(this.props.map.zoom)},this.props.map.scales.map(function(item,index){return/*#__PURE__*/React.createElement("option",{key:index,value:index},LocaleUtils.toLocaleFixed(item,0))})),/*#__PURE__*/React.createElement("input",{onBlur:function onBlur(ev){return _this2.setScale(ev.target.value)},onChange:function onChange(ev){return _this2.setState({scale:ev.target.value})},onKeyUp:function onKeyUp(ev){if(ev.key==="Enter")_this2.setScale(ev.target.value)},role:"input",type:"text",value:LocaleUtils.toLocaleFixed(this.state.scale,0)})))}var style={marginLeft:this.props.mapMargins.outerLeft+"px",marginRight:this.props.mapMargins.outerRight+"px"};return/*#__PURE__*/React.createElement("div",{id:"BottomBar",ref:this.storeHeight,style:style},scalebar,/*#__PURE__*/React.createElement("span",{className:"bottombar-links"},leftBottomLinks),/*#__PURE__*/React.createElement("span",{className:"bottombar-spacer"}),coordinates,scales,/*#__PURE__*/React.createElement("span",{className:"bottombar-spacer"}),/*#__PURE__*/React.createElement("span",{className:"bottombar-links"},rightBottomLinks))}}])}(React.Component);_defineProperty(BottomBar,"propTypes",{/** Additional bottombar links.`side` can be `left` or `right` (default). */additionalBottomBarLinks:PropTypes.arrayOf(PropTypes.shape({label:PropTypes.string,labelMsgId:PropTypes.string,side:PropTypes.string,url:PropTypes.string,urlTarget:PropTypes.string,icon:PropTypes.string})),additionalMouseCrs:PropTypes.array,changeZoomLevel:PropTypes.func,/** Custom coordinate formatter, as `(coordinate, crs) => string`. */coordinateFormatter:PropTypes.func,/** Whether to display the coordinates in the bottom bar. */displayCoordinates:PropTypes.bool,/** Whether to display the scalebar in the bottom bar. */displayScalebar:PropTypes.bool,/** Whether to display the scale in the bottom bar. */displayScales:PropTypes.bool,fullscreen:PropTypes.bool,map:PropTypes.object,mapMargins:PropTypes.object,openExternalUrl:PropTypes.func,/** See [OpenLayers API doc](https://openlayers.org/en/latest/apidoc/module-ol_control_ScaleLine-ScaleLine.html) */scalebarOptions:PropTypes.object,setBottombarHeight:PropTypes.func,setDisplayCrs:PropTypes.func,/** The URL of the terms label anchor. */termsUrl:PropTypes.string,/** Icon of the terms inline window. Relevant only when `termsUrlTarget` is `iframe`. */termsUrlIcon:PropTypes.string,/** The target where to open the terms URL. If `iframe`, it will be displayed in an inline window, otherwise in a new tab. You can also use the `:iframedialog:<dialogname>:<options>` syntax to set up the inline window. */termsUrlTarget:PropTypes.string,/** The URL of the viewer title label anchor. */viewertitleUrl:PropTypes.string,/** Icon of the viewer title inline window. Relevant only when `viewertitleUrl` is `iframe`. */viewertitleUrlIcon:PropTypes.string,/** The target where to open the viewer title URL. If `iframe`, it will be displayed in an inline window, otherwise in a new tab. You can also use the `:iframedialog:<dialogname>:<options>` syntax to set up the inline window. */viewertitleUrlTarget:PropTypes.string});_defineProperty(BottomBar,"defaultProps",{displayCoordinates:true,displayScalebar:true,displayScales:true});export default connect(function(state){var _state$display,_state$theme$current$,_state$theme$current;return{map:state.map,fullscreen:(_state$display=state.display)===null||_state$display===void 0?void 0:_state$display.fullscreen,mapMargins:state.windows.mapMargins,additionalMouseCrs:(_state$theme$current$=(_state$theme$current=state.theme.current)===null||_state$theme$current===void 0?void 0:_state$theme$current.additionalMouseCrs)!==null&&_state$theme$current$!==void 0?_state$theme$current$:[]}},{changeZoomLevel:changeZoomLevel,openExternalUrl:openExternalUrl,setBottombarHeight:setBottombarHeight,setDisplayCrs:setDisplayCrs})(BottomBar);
10
+ var availableCRS=Object.fromEntries(Object.entries(CoordinatesUtils.getAvailableCRS()).filter(function(_ref){var _ref2=_slicedToArray(_ref,2),key=_ref2[0],value=_ref2[1];return enabledMouseCrs.includes(key)}));var scalebar=null;if(this.props.displayScalebar){scalebar=/*#__PURE__*/React.createElement("div",{className:"bottombar-scalebar-container",ref:this.initScaleBar})}var coordinates=null;if(this.props.displayCoordinates){coordinates=/*#__PURE__*/React.createElement("div",{className:"controlgroup"},/*#__PURE__*/React.createElement("span",{className:"bottombar-mousepos-label"},LocaleUtils.tr("bottombar.mousepos_label"),":\xA0"),/*#__PURE__*/React.createElement(CoordinateDisplayer,{className:"bottombar-mousepos",coordinateFormatter:this.props.coordinateFormatter,displayCrs:this.props.map.displayCrs,mapCrs:this.props.map.projection}),/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this2.props.setDisplayCrs(ev.target.value)},value:this.props.map.displayCrs},Object.keys(availableCRS).map(function(crs){return/*#__PURE__*/React.createElement("option",{key:crs,value:crs},availableCRS[crs].label)})))}var scales=null;if(this.props.displayScales){scales=/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"bottombar-scales-label"},LocaleUtils.tr("bottombar.scale_label"),":\xA0"),/*#__PURE__*/React.createElement(InputContainer,{className:"bottombar-scale-combo"},/*#__PURE__*/React.createElement("span",{className:"bottombar-scale-combo-prefix",role:"prefix"}," 1 : "),/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this2.props.changeZoomLevel(parseInt(ev.target.value,10))},role:"input",value:Math.round(this.props.map.zoom)},this.props.map.scales.map(function(item,index){return/*#__PURE__*/React.createElement("option",{key:index,value:index},LocaleUtils.toLocaleFixed(item,0))})),/*#__PURE__*/React.createElement(NumberInput,{decimals:0,onChange:this.setScale,role:"input",value:this.state.scale})))}var style={marginLeft:this.props.mapMargins.outerLeft+"px",marginRight:this.props.mapMargins.outerRight+"px"};return/*#__PURE__*/React.createElement("div",{id:"BottomBar",ref:this.storeHeight,style:style},scalebar,/*#__PURE__*/React.createElement("span",{className:"bottombar-links"},leftBottomLinks),/*#__PURE__*/React.createElement("span",{className:"bottombar-spacer"}),coordinates,scales,/*#__PURE__*/React.createElement("span",{className:"bottombar-spacer"}),/*#__PURE__*/React.createElement("span",{className:"bottombar-links"},rightBottomLinks))}}])}(React.Component);_defineProperty(BottomBar,"propTypes",{/** Additional bottombar links.`side` can be `left` or `right` (default). */additionalBottomBarLinks:PropTypes.arrayOf(PropTypes.shape({label:PropTypes.string,labelMsgId:PropTypes.string,side:PropTypes.string,url:PropTypes.string,urlTarget:PropTypes.string,icon:PropTypes.string})),additionalMouseCrs:PropTypes.array,changeZoomLevel:PropTypes.func,/** Custom coordinate formatter, as `(coordinate, crs) => string`. */coordinateFormatter:PropTypes.func,/** Whether to display the coordinates in the bottom bar. */displayCoordinates:PropTypes.bool,/** Whether to display the scalebar in the bottom bar. */displayScalebar:PropTypes.bool,/** Whether to display the scale in the bottom bar. */displayScales:PropTypes.bool,fullscreen:PropTypes.bool,map:PropTypes.object,mapMargins:PropTypes.object,openExternalUrl:PropTypes.func,/** See [OpenLayers API doc](https://openlayers.org/en/latest/apidoc/module-ol_control_ScaleLine-ScaleLine.html) */scalebarOptions:PropTypes.object,setBottombarHeight:PropTypes.func,setDisplayCrs:PropTypes.func,/** The URL of the terms label anchor. */termsUrl:PropTypes.string,/** Icon of the terms inline window. Relevant only when `termsUrlTarget` is `iframe`. */termsUrlIcon:PropTypes.string,/** The target where to open the terms URL. If `iframe`, it will be displayed in an inline window, otherwise in a new tab. You can also use the `:iframedialog:<dialogname>:<options>` syntax to set up the inline window. */termsUrlTarget:PropTypes.string,/** The URL of the viewer title label anchor. */viewertitleUrl:PropTypes.string,/** Icon of the viewer title inline window. Relevant only when `viewertitleUrl` is `iframe`. */viewertitleUrlIcon:PropTypes.string,/** The target where to open the viewer title URL. If `iframe`, it will be displayed in an inline window, otherwise in a new tab. You can also use the `:iframedialog:<dialogname>:<options>` syntax to set up the inline window. */viewertitleUrlTarget:PropTypes.string});_defineProperty(BottomBar,"defaultProps",{displayCoordinates:true,displayScalebar:true,displayScales:true});export default connect(function(state){var _state$display,_state$theme$current$,_state$theme$current;return{map:state.map,fullscreen:(_state$display=state.display)===null||_state$display===void 0?void 0:_state$display.fullscreen,mapMargins:state.windows.mapMargins,additionalMouseCrs:(_state$theme$current$=(_state$theme$current=state.theme.current)===null||_state$theme$current===void 0?void 0:_state$theme$current.additionalMouseCrs)!==null&&_state$theme$current$!==void 0?_state$theme$current$:[]}},{changeZoomLevel:changeZoomLevel,openExternalUrl:openExternalUrl,setBottombarHeight:setBottombarHeight,setDisplayCrs:setDisplayCrs})(BottomBar);
@@ -54,13 +54,17 @@
54
54
  color: var(--text-color);
55
55
  }
56
56
 
57
- #BottomBar div.bottombar-scale-combo > input {
57
+ #BottomBar div.bottombar-scale-combo > div.number-input {
58
58
  position: absolute;
59
59
  top: 0;
60
60
  left: 2em;
61
61
  width: 6em;
62
62
  }
63
63
 
64
+ #BottomBar div.bottombar-scale-combo > div.number-input > input {
65
+ text-align: left;
66
+ }
67
+
64
68
  #BottomBar span.bottombar-spacer {
65
69
  flex: 1 1 auto;
66
70
  }