@nadir2k/google-maps-input
Version:
Sanity plugin providing input handlers for geo-related input types using Google Maps
2 lines (1 loc) • 18.1 kB
JavaScript
var e,t,n,o,r;function a(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){s(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var o=n.call(e,t||"default");if("object"!=typeof o)return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsxs as c,jsx as d,Fragment as p}from"react/jsx-runtime";import*as h from"react";import u,{useState as g,useEffect as m}from"react";import{uniqueId as f}from"lodash";import{Card as y,Box as v,Text as w,Code as C,TextInput as k,Grid as P,Button as b,Dialog as M}from"@sanity/ui";import{EditIcon as O,TrashIcon as x}from"@sanity/icons";import{setIfMissing as E,set as I,unset as L,ChangeIndicator as T,useUserColor as A,getAnnotationAtPath as H,DiffTooltip as S,definePlugin as j}from"sanity";import R from"styled-components";const D="___sanity_googleMapsApiCallback",z="gm_authFailure";let B=class extends Error{};function V(e){return new Promise(((t,n)=>{window[z]=()=>{n(new B("Authentication error when loading Google Maps API."))},window[D]=()=>{t(window.google.maps)};const o=document.createElement("script");o.onerror=(e,t,o,r,a)=>n(new Error(function(e,t){if(t)return t.message;if("string"==typeof e)return e;return function(e){if("object"!=typeof e||null===e)return!1;if(!("message"in e))return!1;return"string"==typeof e.message}(e)?e.message:"Failed to load Google Maps API"}(e,a))),o.src="https://maps.googleapis.com/maps/api/js?key=".concat(e.apiKey,"&libraries=places").concat(e.drawPolygon?",drawing":"","&callback=").concat(D,"&language=").concat(e.locale),document.getElementsByTagName("head")[0].appendChild(o)})).finally((()=>{delete window[D],delete window[z]}))}let _=null;function F(e){var t;return c(y,{tone:"critical",radius:1,children:[d(v,{as:"header",paddingX:4,paddingTop:4,paddingBottom:1,children:d(w,{as:"h2",weight:"bold",children:"Google Maps failed to load"})}),d(v,{paddingX:4,paddingTop:4,paddingBottom:1,children:e.isAuthError?d(G,{}):c(p,{children:[d(w,{as:"h3",children:"Error details:"}),d("pre",{children:d(C,{size:1,children:"error"in e&&(null==(t=e.error)?void 0:t.message)})})]})})]})}function G(){return c(w,{children:[d("p",{children:"The error appears to be related to authentication"}),d("p",{children:"Common causes include:"}),c("ul",{children:[d("li",{children:"Incorrect API key"}),d("li",{children:"Referer not allowed"}),d("li",{children:"Missing authentication scope"})]}),d("p",{children:"Check the browser developer tools for more information."})]})}const W="undefined"!=typeof window&&window.navigator.language||"en";function N(e){const t=e.defaultLocale||W||"en-US",[n,o]=g({type:"loading"});return m((()=>{(function(e){return _||(_=V(e),_.catch((()=>{_=null})),_)})({locale:t,apiKey:e.apiKey,drawPolygon:e.drawPolygon}).then((e=>o({type:"loaded",api:e})),(e=>o({type:"error",error:{type:e instanceof B?"authError":"loadError",message:e.message}})))}),[t,e.apiKey,e.drawPolygon]),n}function U(e){const t=N(l(l({},e.config),{},{drawPolygon:e.config.drawPolygon||!1}));switch(t.type){case"error":return d(F,{error:t.error,isAuthError:"authError"===t.error.type});case"loading":return d("div",{children:"Loading Google Maps API"});case"loaded":return e.children(t.api);default:return null}}const Z=R.div(e||(e=a(["\n position: absolute;\n right: 10px;\n top: 10px;\n width: 220px;\n"])));class K extends h.PureComponent{constructor(){super(...arguments),this.searchInputRef=h.createRef(),this.handleChange=()=>{this.autoComplete&&(this.props.onChange(this.autoComplete.getPlace()),this.searchInputRef.current&&(this.searchInputRef.current.value=""))}}componentDidMount(){const e=this.searchInputRef.current;if(!e)return;const{api:t,map:n}=this.props,{Circle:o,places:r,event:a}=t,i=new o({center:n.getCenter(),radius:1e3}).getBounds();this.autoComplete=new r.Autocomplete(e,{bounds:i,types:[]}),a.addListener(this.autoComplete,"place_changed",(()=>{var e,t;const o=null==(e=this.autoComplete)?void 0:e.getPlace();(null==(t=null==o?void 0:o.geometry)?void 0:t.location)&&o.geometry.viewport&&(n.fitBounds(o.geometry.viewport),n.panTo(o.geometry.location))}))}render(){return d(Z,{children:d(k,{name:"place",ref:this.searchInputRef,placeholder:"Search for place or address",padding:4})})}}function q(e,t){const n="function"==typeof e.lat?e.lat():e.lat,o="function"==typeof e.lng?e.lng():e.lng,r="function"==typeof t.lat?t.lat():t.lat,a="function"==typeof t.lng?t.lng():t.lng;return n===r&&o===a}const J=R.div(t||(t=a(["\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n"])));class X extends u.PureComponent{constructor(){super(...arguments),this.state={map:void 0,polygon:void 0,deleteButton:void 0,drawingManager:void 0},this.mapRef=u.createRef(),this.mapEl=null,this.attachClickHandler=()=>{const e=this.state.map;if(!e)return;const{api:t,onClick:n}=this.props,{event:o}=t;this.clickHandler&&this.clickHandler.remove(),n&&(this.clickHandler=o.addListener(e,"click",n))},this.setMapElement=e=>{if(e&&e!==this.mapEl){const t=this.constructMap(e);this.setState({map:t},this.attachClickHandler)}this.mapEl=e}}componentDidMount(){this.attachClickHandler()}componentDidUpdate(e){const t=this.state.map;if(!t)return;const{onClick:n,location:o,bounds:r,value:a,drawPolygon:i}=this.props;if(i){if(!Array.isArray(a)||this.state.polygon)return;const e=new google.maps.Polygon({paths:a,strokeColor:"#FF0000",strokeOpacity:.8,strokeWeight:2,fillColor:"#FF0000",fillOpacity:.35});e.setMap(t),this.setState((t=>l(l({},t),{},{polygon:e}))),t.fitBounds(function(e){const t=new google.maps.LatLngBounds;let n;for(n=0;n<e.length;n++)t.extend(e[n]);return t}(a))}e.onClick!==n&&this.attachClickHandler(),q(e.location,o)||t.panTo(this.getCenter()),!r||e.bounds&&r.equals(e.bounds)||t.fitBounds(r)}componentWillUnmount(){this.clickHandler&&this.clickHandler.remove()}getCenter(){const{location:e,api:t}=this.props;return new t.LatLng(e.lat,e.lng)}async deletePolygon(){var e;null==(e=this.state.polygon)||e.setMap(null),this.setState((e=>l(l({},e),{},{polygon:void 0}))),this.props.handleClear&&this.props.handleClear()}async addDeleteControl(e,t){var n;await new Promise((e=>setTimeout(e,2e3)));const o=document.querySelector('[role="menuitemradio"]:not([id])'),r=null==(n=null==o?void 0:o.parentElement)?void 0:n.parentElement;if(!r)return;const a=null==o?void 0:o.cloneNode(!0);a&&(r.appendChild(a),a.querySelector("img").parentElement.innerHTML='<svg data-sanity-icon="close" width="100%" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 7L7 18M7 7L18 18" stroke="#f00" stroke-width="1.2"></path></svg>',this.setState((e=>l(l({},e),{},{deleteButton:a}))),a.addEventListener("click",(()=>this.deletePolygon())))}constructPolygon(e,t){const n=new e.drawing.DrawingManager({drawingMode:google.maps.drawing.OverlayType.POLYGON,drawingControl:!0,drawingControlOptions:{position:google.maps.ControlPosition.TOP_CENTER,drawingModes:[google.maps.drawing.OverlayType.POLYGON]},polygonOptions:{editable:!0,draggable:!0}});return n.setMap(t),this.setState((e=>l(l({},e),{},{drawingManager:n}))),this.addDeleteControl(e,t),e.event.addListener(n,"overlaycomplete",(e=>{var t;this.state.polygon?null==(t=e.overlay)||t.setMap(null):(this.setState((t=>l(l({},t),{},{polygon:e.overlay}))),this.props.handlePolygonDraw&&e.overlay.getPaths().forEach((e=>{this.props.handlePolygonDraw(e.getArray())})))})),n}constructMap(e){const{defaultZoom:t,api:n,mapTypeControl:o,controlSize:r,bounds:a,scrollWheel:i,drawPolygon:l}=this.props,s=new n.Map(e,{zoom:t,center:this.getCenter(),scrollwheel:i,streetViewControl:!1,mapTypeControl:o,controlSize:r});return a&&s.fitBounds(a),l&&this.constructPolygon(n,s),s}render(){const{children:e}=this.props,{map:t}=this.state;return c(p,{children:[d(J,{ref:this.setMapElement}),e&&t?e(t):null]})}}X.defaultProps={defaultZoom:8,scrollWheel:!0};class Y extends h.PureComponent{constructor(){super(...arguments),this.eventHandlers={}}componentDidMount(){const{position:e,api:t,map:n,onMove:o,zIndex:r,opacity:a,label:i,markerRef:l,color:s}=this.props,{Marker:c}=t;let d;s&&(d={path:"M 3.052 3.7 C 1.56 5.293 0.626 7.612 0.663 9.793 C 0.738 14.352 2.793 16.077 6.078 22.351 C 7.263 25.111 8.497 28.032 9.672 32.871 C 9.835 33.584 9.994 34.246 10.069 34.305 C 10.143 34.362 10.301 33.697 10.465 32.983 C 11.639 28.145 12.875 25.226 14.059 22.466 C 17.344 16.192 19.398 14.466 19.474 9.908 C 19.511 7.727 18.574 5.405 17.083 3.814 C 15.379 1.994 12.809 0.649 10.069 0.593 C 7.328 0.536 4.756 1.882 3.052 3.7 Z",fillOpacity:1,fillColor:s.background,strokeColor:s.border,strokeWeight:2,anchor:new t.Point(10,35),labelOrigin:new t.Point(10,11)}),this.marker=new c({draggable:Boolean(o),position:e,map:n,zIndex:r,opacity:a,label:i,icon:d}),l&&(l.current=this.marker),this.attachMoveHandler(),this.attachClickHandler()}componentDidUpdate(e){if(!this.marker)return;const{position:t,onMove:n,label:o,zIndex:r,opacity:a,map:i}=this.props;e.onMove!==n&&this.attachMoveHandler(),q(e.position,t)||this.marker.setPosition(t),e.label!==o&&this.marker.setLabel(o||null),e.zIndex!==r&&this.marker.setZIndex(r||null),e.opacity!==a&&this.marker.setOpacity(a||null),e.map!==i&&this.marker.setMap(i)}componentWillUnmount(){this.eventHandlers.move&&this.eventHandlers.move.remove(),this.marker&&this.marker.setMap(null)}attachMoveHandler(){const{api:e,onMove:t}=this.props;this.eventHandlers.move&&this.eventHandlers.move.remove(),this.marker&&t&&(this.eventHandlers.move=e.event.addListener(this.marker,"dragend",t))}attachClickHandler(){const{api:e,onClick:t}=this.props;this.eventHandlers.click&&this.eventHandlers.click.remove(),this.marker&&t&&(this.eventHandlers.click=e.event.addListener(this.marker,"click",t))}render(){return null}}const Q={lat:40.7058254,lng:-74.1180863};class $ extends u.PureComponent{constructor(){super(...arguments),this.mapRef=u.createRef(),this.handlePlaceChanged=e=>{var t;this.props.drawPolygon||(null==(t=e.geometry)?void 0:t.location)&&this.setValue(e.geometry.location)},this.handleMarkerDragEnd=e=>{this.props.drawPolygon||e.latLng&&this.setValue(e.latLng)},this.handleMapClick=e=>{this.props.drawPolygon||e.latLng&&this.setValue(e.latLng)},this.handlePolygonDraw=e=>{this.setValue(e)}}getCenter(){const{value:e={},defaultLocation:t={}}=this.props;return l(l(l({},Q),t),e)}setValue(e){this.props.onChange&&this.props.onChange(e)}render(){const{api:e,defaultZoom:t,value:n,onChange:o,drawPolygon:r,handleClear:a}=this.props;return d(X,{api:e,location:this.getCenter(),onClick:this.handleMapClick,defaultZoom:t,drawPolygon:r,handlePolygonDraw:this.handlePolygonDraw,value:n,handleClear:a,children:t=>c(p,{children:[d(K,{api:e,map:t,onChange:this.handlePlaceChanged}),n&&!r&&d(Y,{api:e,map:t,position:n,onMove:o?this.handleMarkerDragEnd:void 0})]})})}}$.defaultProps={defaultZoom:8,defaultLocation:{lng:10.74609,lat:59.91273}};const ee=R.img(n||(n=a(["\n width: 100%;\n height: auto;\n vertical-align: top;\n"]))),te=R.div(o||(o=a(["\n height: 40rem;\n width: 50rem;\n"])));let ne;function oe(){return ne}function re(e){ne=e}const ae=(e,t)=>{let n;const o=Array.isArray(e)?"fillcolor:0xFFFF0033|".concat(e.map((e=>"".concat(e.lat,",").concat(e.lng))).join("|"),"|").concat(e[0].lat,",").concat(e[0].lng):"".concat(e.lat,",").concat(e.lng);Array.isArray(e)||(n=o);const r={key:t,scale:2,size:"640x300",center:n};Array.isArray(e)?r.path=o:(r.markers=o,r.zoom=13);const a=Object.keys(r).reduce(((e,t)=>e.concat("".concat(t,"=").concat(encodeURIComponent(r[t])))),[]);return"https://maps.googleapis.com/maps/api/staticmap?".concat(a.join("&"))};class ie extends u.PureComponent{constructor(e){super(e),this._geopointInputId=f("GeopointInput"),this.setEditButton=e=>{this.editButton=e},this.handleToggleModal=()=>{this.setState((e=>({modalOpen:!e.modalOpen})))},this.handleCloseModal=()=>{this.setState({modalOpen:!1})},this.handleChange=e=>{const{schemaType:t,onChange:n,id:o}=this.props;Array.isArray(e)?n([E({_type:t.name}),I(e.map(((e,t)=>({lat:e.lat(),lng:e.lng(),_key:t+1}))))]):n([E({_type:t.name}),I(e.lat(),["lat"]),I(e.lng(),["lng"])])},this.handleClear=()=>{const{onChange:e}=this.props;e(L())},this.state={modalOpen:!1}}focus(){this.editButton&&this.editButton.focus()}render(){const{value:e,readOnly:t,geoConfig:n,path:o,changed:r,focused:a}=this.props,{modalOpen:i}=this.state;return n&&n.apiKey?c(p,{children:[e&&d(T,{path:o,isChanged:r,hasFocus:!!a,children:d(ee,{src:ae(e,n.apiKey),alt:"Map location"})}),!t&&d(v,{marginTop:4,children:c(P,{columns:2,gap:2,children:[d(b,{mode:"ghost",icon:e&&O,padding:3,ref:this.setEditButton,text:e?"Edit":"Set location",onClick:this.handleToggleModal}),e&&d(b,{tone:"critical",icon:x,padding:3,mode:"ghost",text:"Remove",onClick:this.handleClear})]})}),i&&d(M,{id:"".concat(this._geopointInputId,"_dialog"),onClose:this.handleCloseModal,header:"Place the marker on the map",width:1,children:d(te,{children:d(U,{config:oe(),children:o=>d($,{api:o,value:e||void 0,onChange:t?void 0:this.handleChange,defaultLocation:n.defaultLocation,defaultZoom:n.defaultZoom,drawPolygon:n.drawPolygon||!1,handleClear:this.handleClear})})})})]}):c("div",{children:[c("p",{children:["The ",d("a",{href:"https://sanity.io/docs/schema-types/geopoint-type",children:"Geopoint type"})," needs a Google Maps API key with access to:"]}),c("ul",{children:[d("li",{children:"Google Maps JavaScript API"}),d("li",{children:"Google Places API Web Service"}),d("li",{children:"Google Static Maps API"})]}),d("p",{children:"Please enter the API key with access to these services in your googleMapsInput plugin config."})]})}}class le extends h.PureComponent{constructor(){super(...arguments),this.eventHandlers={}}componentDidMount(){const{from:e,to:t,api:n,map:o,zIndex:r,onClick:a,color:i,arrowRef:l}=this.props,s={path:n.SymbolPath.FORWARD_OPEN_ARROW};this.line=new n.Polyline({map:o,zIndex:r,path:[e,t],icons:[{icon:s,offset:"50%"}],strokeOpacity:.55,strokeColor:i?i.text:"black"}),a&&(this.eventHandlers.click=n.event.addListener(this.line,"click",a)),l&&(l.current=this.line)}componentDidUpdate(e){if(!this.line)return;const{from:t,to:n,map:o}=this.props;q(e.from,t)&&q(e.to,n)||this.line.setPath([t,n]),e.map!==o&&this.line.setMap(o)}componentWillUnmount(){this.line&&this.line.setMap(null),this.eventHandlers.click&&this.eventHandlers.click.remove()}render(){return null}}function se(e){let{diff:t,api:n,map:o,label:r}=e;const{fromValue:a,toValue:i}=t,l=t.isChanged?t.annotation:void 0,s=A(l?l.author:null)||void 0,u=h.useRef(),g=h.useRef();return c(p,{children:[a&&d(Y,{api:n,map:o,position:a,zIndex:0,opacity:.55,markerRef:u,color:s}),a&&i&&d(le,{api:n,map:o,from:a,to:i,zIndex:1,color:s}),i&&d(Y,{api:n,map:o,position:i,zIndex:2,markerRef:g,label:r,color:s})]})}const ce=R.div(r||(r=a(["\n position: relative;\n min-height: 200px;\n\n &:empty {\n background-color: var(--card-skeleton-color-from);\n display: table;\n width: 100%;\n }\n\n &:empty:after {\n content: 'Missing/invalid data';\n display: table-cell;\n vertical-align: middle;\n text-align: center;\n position: relative;\n }\n"]))),de=e=>{let{diff:t,schemaType:n}=e;return d(ce,{children:d(U,{config:oe(),children:e=>d(pe,{api:e,diff:t,schemaType:n})})})};function pe(e){let{api:t,diff:n}=e;const o=(n.fromValue||[]).filter(he),r=(n.toValue||[]).filter(he);if(0===o.length&&0===r.length)return null;const a=function(e,t,n){const o=new n.LatLngBounds,r=[...e||[],...t||[]];return r.forEach((e=>o.extend(e))),o}(o,r,t);return d(X,{api:t,location:a.getCenter().toJSON(),mapTypeControl:!1,controlSize:20,bounds:a,children:e=>d(p,{children:n.items.map((n=>{let{toIndex:o,diff:r}=n;return function(e){return"unchanged"!==e.action&&"object"===e.type}(r)?d(se,{api:t,map:e,diff:r,label:"".concat(o)},o):null}))})})}function he(e){return"number"==typeof e.lat&&"number"==typeof e.lng}const ue=e=>{let{diff:t,schemaType:n}=e;return d(ce,{children:d(U,{config:oe(),children:e=>d(ge,{api:e,diff:t,schemaType:n})})})};function ge(e){let{api:t,diff:n}=e;const{fromValue:o,toValue:r}=n,a=H(n,["lat"])||H(n,["lng"])||H(n,[]),i=function(e,t){const{fromValue:n,toValue:o}=e;if(n&&o)return me(n,o,t).getCenter().toJSON();if(n)return n;if(o)return o;throw new Error("Neither a from or a to value present")}(n,t),l=o&&r?me(o,r,t):void 0;return d(S,{annotations:a?[a]:[],description:fe(n),children:d("div",{children:d(X,{api:t,location:i,mapTypeControl:!1,controlSize:20,bounds:l,scrollWheel:!1,children:e=>d(se,{api:t,map:e,diff:n})})})})}function me(e,t,n){return(new n.LatLngBounds).extend(e).extend(t)}function fe(e){const{fromValue:t,toValue:n}=e;return t&&n?"Moved":t?"Removed":n?"Added":"Unchanged"}const ye=j((e=>(re(e),{name:"google-maps-input",form:{components:{input(t){const n="array"===t.schemaType.jsonType&&"geopoint"===t.schemaType.of[0].name;if(ve("geopoint",t.schemaType)||n){return d(ie,l(l({},t),{},{geoConfig:e,drawPolygon:e.drawPolygon}))}return t.renderDefault(t)}}}})));function ve(e,t){return(null==t?void 0:t.name)===e||!!(null==t?void 0:t.name)&&ve(e,null==t?void 0:t.type)}export{de as GeopointArrayDiff,ue as GeopointFieldDiff,ie as GeopointInput,ye as googleMapsInput};//# sourceMappingURL=index.esm.js.map