maparea 0.1.9 → 0.1.11

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.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- const{PI:e}=Math,t=e/180,n=180/e,r={spherical:0,ellipsoidal:.0818191908426},i=-85.05,a=85.05,o=-180,s=180,{PI:c,sin:l,tan:u,atan:d,pow:f,exp:p,log:m,abs:h}=Math;var g=class{_p;_c;_cc;_r=new Set;constructor(e){this._p=e,this.container.style=`position: relative; overflow: hidden;`,this.container.dataset.type=`maparea`}render(){for(let e of this._r)e(this)}onRender(e,t=!1){return this._r.add(e),t||e(this),()=>{this._r.delete(e)}}getOptions(){return{...this._p,center:this.center,bounds:this.bounds}}setOptions(e){this._p={...this._p,...e},delete this._c,delete this._cc,this.render()}get container(){if(!this._c){let e=document.querySelector(this._p.container);if(!e)throw Error(`missing container element`);this._c=e}return this._c}get box(){let e=this.container.getBoundingClientRect();return{x:e.left,y:e.top,w:e.width,h:e.height}}get bounds(){let e=this._p.bounds;return e?{...e}:{}}set bounds(e){this._p.bounds=e}get center(){let e=this._p.center;return e?e.slice():[0,0]}set center(e){this._p.center=e,delete this._cc,this.render()}get centerCoords(){if(!this._cc){let[e,t]=this.center;this._cc=this.toPixelCoords(e,t)}return this._cc}get zoom(){return this._p.zoom??this._p.minZoom??0}set zoom(e){let{minZoom:t,maxZoom:n}=this,r=e;e<t&&(r=t),e>n&&(r=n),this._p.zoom=r,delete this._cc,this.render()}get minZoom(){return this._p.minZoom??-1/0}set minZoom(e){this._p.minZoom=e,this.zoom<this.minZoom&&(this.zoom=this.minZoom)}get maxZoom(){return this._p.maxZoom??1/0}set maxZoom(e){this._p.maxZoom=e,this.zoom>this.maxZoom&&(this.zoom=this.maxZoom)}get projection(){return this._p.projection??`spherical`}set projection(e){this._p.projection=e,this.render()}get lang(){return this._p.lang??``}set lang(e){this._p.lang=e,this.render()}inPixelBounds(e,t){let[n,r]=this.toGeoCoords(e,t);return this.inBounds(n,r)}inBounds(e,t){let{minLat:n=i,maxLat:r=a,minLon:s=o,maxLon:c=180}=this.bounds;return e>=n&&e<=r&&t>=s&&t<=c}canMoveTo(e,t){if(!this.inBounds(e,t))return!1;let{w:n,h:r}=this.box;if(n===0||r===0)return!1;let[i,a]=this.toPixelCoords(e,t);return this.inPixelBounds(i-n/2,a-r/2)&&this.inPixelBounds(i+n/2,a+r/2)}toPixelCoords(e,n){let i=r[this.projection],a=f(2,this.zoom+7)/c,o=e*t,s=i===0?1:f((1-i*l(o))/(1+i*l(o)),i/2);return[a*(c+n*t),a*(c-m(s*u(c/4+o/2)))]}toGeoCoords(e,t){let o=r[this.projection],s=f(2,this.zoom+7)/c,l=(e/s-c)*n,u;if(o===0)u=2*(d(p(c-t/s))-c/4)*n;else{u=i;let e=a-i,n=NaN,r=0;for(;(Number.isNaN(n)||h(n-t)>.1)&&r++<30;)e/=2,n=this.toPixelCoords(u+e,l)[1],n>t&&(u+=e)}return(l<-180||l>=180)&&(l=(l+180)%360-180),(u<-90||u>=90)&&(u=(u+90)%180-90),[u,l]}};function _(e){let t=`touches`in e?e.touches[0]:e;return t?[t.clientX,t.clientY]:null}function v(e,t){return t===void 0||!(e instanceof HTMLElement)?!1:typeof t==`function`&&t(e)||typeof t==`string`&&e.closest(t)!==null}function y(e,t,n){let r=Date.now(),i=null,a=e=>{r=Date.now(),i=_(e)},o=a=>{if(v(a.target,n)||!i||Date.now()-r>150)return;let{box:o,centerCoords:[s,c]}=e,l=i[0]-o.x,u=i[1]-o.y,[d,f]=e.toGeoCoords(l-.5*o.w+s,u-.5*o.h+c);t({x:l,y:u,lat:d,lon:f,originalEvent:a}),i=null};return e.container.addEventListener(`mousedown`,a),e.container.addEventListener(`mouseup`,o),e.container.addEventListener(`touchstart`,a),e.container.addEventListener(`touchend`,o),()=>{e.container.removeEventListener(`mousedown`,a),e.container.removeEventListener(`mouseup`,o),e.container.removeEventListener(`touchstart`,a),e.container.removeEventListener(`touchend`,o)}}function b(){return Math.random().toString(36).slice(2)}function x(e,{id:t,className:n,inset:r=`0`}={}){let i=`${n?`.${n}`:``}${t?`[data-id="${t}"]`:``}`,a=document.querySelector(i);return a||(a=document.createElement(`div`),a.className=`${n?`${n} `:``}layer`,a.dataset.id=t??b(),a.style=`position: absolute; inset: ${r};`,e.container.append(a)),a}function S(e,t){return typeof t==`function`?t(e):t??``}function C(e,t){return e.toFixed(t).replace(/\.(\d*[^0])0+$/,`.$1`).replace(/\.0+$/,``)}function w(e,t,{className:n,coords:r,inset:i,layer:a,content:o}){let s=a??x(e,{className:`elements`});n&&t.setAttribute(`class`,n),t.style.position=`absolute`,s.append(t),e.onRender(()=>{if(i)t.style.inset=S(e,i);else if(r){let{centerCoords:[n,i],box:{w:a,h:o}}=e,[s,c]=e.toPixelCoords(...r),l=C(s-n+a/2,2),u=C(c-i+o/2,2);t.style.transform=`translate3d(${l}px, ${u}px, 0)`}if(o){let n=S(e,o);t.innerHTML!==n&&(t.innerHTML=n)}})}function T(e,{onStart:t,onMove:n,onEnd:r,wheel:i}={}){let a=null,o=null,s=Date.now(),c=!1,l=null,u=null;function d(t,r,i=100){u!==null&&(clearTimeout(u),u=null),l!==null&&(cancelAnimationFrame(l),l=null);let c=Date.now();c-s<i||(a!==null&&(a-=t),o!==null&&(o-=r),s=c,e.dataset.dragged||(e.dataset.dragged=`true`),l=requestAnimationFrame(()=>{l=null,(t!==0||r!==0)&&n?.(t,r)}))}function f(e,t,n){a!==null&&o!==null&&d(a-e,o-t,n)}function p(e,n){c=!0,t?.(),e!==void 0&&(a=e),n!==void 0&&(o=n),s=Date.now()}function m(t,n){c=!1,u=null,t!==void 0&&n!==void 0&&f(t,n),delete e.dataset.dragged,a=null,o=null,requestAnimationFrame(()=>{r?.()})}e.dataset.draggable=`true`;let h=null,g=null;e.addEventListener(`mousedown`,t=>{t.preventDefault(),!h&&(p(t.clientX,t.clientY),h=e=>{e.preventDefault(),f(e.clientX,e.clientY)},e.addEventListener(`mousemove`,h))}),e.addEventListener(`mouseup`,t=>{t.preventDefault(),h&&=(m(t.clientX,t.clientY),e.removeEventListener(`mousemove`,h),null)}),e.addEventListener(`touchstart`,t=>{t.preventDefault(),!g&&(p(t.touches[0]?.clientX,t.touches[0]?.clientY),g=e=>{e.preventDefault(),f(e.touches[0]?.clientX,e.touches[0]?.clientY)},e.addEventListener(`touchmove`,g))}),e.addEventListener(`touchend`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),e.addEventListener(`touchcancel`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),i&&e.addEventListener(`wheel`,e=>{e.preventDefault(),c||p(),e.shiftKey?d(e.deltaY,e.deltaX,10):d(e.deltaX,e.deltaY,10),u=setTimeout(()=>{m()},200)})}function E(e){let t=0,n=0;T(e.container,{onStart(){[t,n]=e.centerCoords},onMove(r,i){let a=t+r,o=n+i,s=e.toGeoCoords(a,o);e.canMoveTo(...s)&&(e.center=s,t=a,n=o)},wheel:!0})}function D(e,{storageKey:t,session:n=!1}={}){let r=n?window.sessionStorage:window.localStorage,i=t??[`maparea`,e.container.id].filter(Boolean).join(`#`),a=e.getOptions(),o=!1,s=()=>{try{r.setItem(i,JSON.stringify(e.getOptions()))}catch{}},c=()=>{try{let t=r.getItem(i);t===null?s():e.setOptions(JSON.parse(t))}catch{}},l=e=>{o=e===void 0?!o:e},u=()=>{e.setOptions(a)};c();let d=null;return e.onRender(()=>{o||(d&&=(clearTimeout(d),null),d=setTimeout(()=>{d=null,s()},350))}),{sync:c,write:s,toggle:l,reset:u}}function O(e,t){let n=new ResizeObserver(n=>{for(let r of n)if(r.contentBoxSize){if(t)if(r.contentBoxSize){let{inlineSize:e,blockSize:n}=r.contentBoxSize[0]??r.contentBoxSize;t({inlineSize:e,blockSize:n})}else{let{width:e,height:n}=r.contentRect;t({width:e,height:n})}e.render()}});return n.observe(e.container),()=>{n.unobserve(e.container)}}const k=`http://www.w3.org/2000/svg`,A={className:`shape`};function j(e,t,n){let r=x(e,n??A);r.toggleAttribute(`hidden`,t.length===0);let i=r.querySelector(`svg`);i||(i=document.createElementNS(k,`svg`),i.setAttribute(`xmlns`,k),r.append(i));let a=N(i,t.map(({id:t,coords:[n,r]})=>({id:t,coords:e.toPixelCoords(n,r)})),n);if(a){let{xMin:t,xMax:n,yMin:r,yMax:o}=a,{centerCoords:[s,c],box:l}=e,u=C(n-t,3),d=C(o-r,3),f=C(.5*l.w+t-s,2),p=C(.5*l.h+r-c,2);i.setAttribute(`viewBox`,`0 0 ${u} ${d}`),i.setAttribute(`width`,u),i.setAttribute(`height`,d),i.setAttribute(`style`,`position: absolute; transform: translate3d(${f}px, ${p}px, 0);`)}return r}function M(e){return parseFloat(window.getComputedStyle(e).strokeWidth||e.getAttribute(`stroke-width`)||`1`)}function N(e,t,n){if(t.length===0){e.innerHTML=``;return}let r=e.querySelector(`path`);r||(r=document.createElementNS(k,`path`),e.append(r));let i=t[0].coords[0],a=i,o=t[0].coords[1],s=o,c=``;for(let{coords:[e,n]}of t)i>e&&(i=e),a<e&&(a=e),o>n&&(o=n),s<n&&(s=n);i-=10,a+=10,o-=10,s+=10;let l=Array.from(e.querySelectorAll(`.marker`)),u=0;for(let{id:a,coords:[s,d]}of t){let t=C(s-i,3),f=C(d-o,3);if(c+=`${c?` L`:`M`} ${t} ${f}`,n?.markers){let n=l[u++];n||(n=document.createElementNS(k,`circle`),n.setAttribute(`class`,`marker`),n.setAttribute(`r`,String(1.5*M(r))),e.append(n)),n.setAttribute(`cx`,t),n.setAttribute(`cy`,f),n.dataset.id=a}}for(let e=u;e<l.length;e++)l[e].remove();return r.setAttribute(`d`,c),{xMin:i,xMax:a,yMin:o,yMax:s}}function P(e,t,n){let r=t.map(e=>({id:b(),coords:e}));e.onRender(()=>{j(e,r,{className:`shape`,...n})})}function F(e,t){let n=[],r=null,i={className:`shape-editor`,markers:!0},a=()=>{j(e,n,i),t?.onUpdate?.(n)};y(e,({lat:e,lon:t,originalEvent:i})=>{let o=(i.target?.closest(`.marker`))?.dataset.id;if(o&&r){clearTimeout(r),r=null,n=n.filter(({id:e})=>e!==o),a();return}let s=()=>{n.push({id:b(),coords:[e,t]}),a(),r=null};o?r=setTimeout(s,250):s()},t?.ignoreClicks),e.onRender(a)}const{floor:I,ceil:L,random:R}=Math,z=256;function B(e,t,n){return`${t},${n},${e.zoom},${e.lang}`}function V(e,t,n,{size:r=256,url:i,subdomains:a,retries:o=0,error:s}){let c=new Image,l=0,u=(r,o)=>{if(!i)return``;if(typeof i==`function`)return i(e,t,n);let s=i.replaceAll(`{x}`,String(r)).replaceAll(`{y}`,String(o)).replaceAll(`{z}`,String(e.zoom)).replaceAll(`{lang}`,e.lang);return a&&s.includes(`{s}`)&&(s=s.replaceAll(`{s}`,a[I(a.length*R())])),s};return c.width=r,c.height=r,c.src=u(t,n),c.dataset.id=B(e,t,n),c.style=`position: absolute;`,c.onerror=()=>{l++;let{src:i}=c;if(!i||l>o){let t=S(e,s);t&&(c.onerror=()=>{},c.dataset.src=i,c.src=t);return}let a=t*r,d=n*r,f=e.toPixelCoords(...e.toGeoCoords(a,d))[0],p=I(f/r);if(t!==p)c.src=u(p,n);else{let e=new URL(i);e.searchParams.set(`_t`,String(Date.now())),c.src=e.href}},c}function H(e){return e.querySelectorAll(`img[data-id]`)}function U(e,t){return e.querySelector(`img[data-id="${t}"]`)}function W(e,t={}){let{id:n=b(),attribution:r,attributionInset:i=`auto 0 0 auto`}=t,a=x(e,{id:n,className:`tiles`,...t}),o=x(e,{id:n,className:`tiles-attribution`,inset:i}),s=()=>{let{box:{w:n,h:i},centerCoords:[s,c]}=e,{size:l=256,margin:u=0}=t,d=Array.isArray(u)?u[0]:u,f=Array.isArray(u)?u[1]:u,p=L((n+2*d)/l),m=L((i+2*f)/l),h=I(s/l),g=I(c/l),_=null,v=new Set,y=``;for(let r=0;r<=p;r++){let o=h+(r%2==0?-1:1)*I(r/2);for(let r=0;r<=m;r++){let u=g+(r%2==0?-1:1)*I(r/2);y=B(e,o,u),_=U(a,y),_||(_=V(e,o,u,t),a.append(_));let d=C(.5*n+o*l-s,2),f=C(.5*i+u*l-c,2);_.style.transform=`translate3d(${d}px, ${f}px, 0)`,v.add(y)}}for(let e of H(a)){let{id:t}=e.dataset;t&&!v.has(t)&&e.remove()}let b=S(e,r);o.toggleAttribute(`hidden`,!b),o.innerHTML!==b&&(o.innerHTML=b)},c=e.zoom,l=null;return e.onRender(()=>{l!==null&&(clearTimeout(l),l=null),e.zoom===c?(a.style.opacity=``,s()):(a.style.opacity=`0`,l=setTimeout(()=>{l=null,a.style.opacity=``,s()},300)),c=e.zoom}),a}function G(e,t={}){let{plus:n=`➕`,minus:r=`➖`,inset:i=`0 0 auto auto`}=t,a=x(e,{className:`zoom-controls`,inset:i}),o=document.createElement(`button`);o.dataset.id=`plus`,o.innerHTML=n;let s=document.createElement(`button`);s.dataset.id=`minus`,s.innerHTML=r;let c=()=>{o.toggleAttribute(`disabled`,e.zoom+1>e.maxZoom),s.toggleAttribute(`disabled`,e.zoom-1<e.minZoom)};return y(e,({originalEvent:t})=>{let n=t.target?.closest(`button`);n&&(t.stopPropagation(),e.zoom+=n.dataset.id===`minus`?-1:1,c())}),e.onRender(c),a.append(o,s),a}function K(e){if(e.length===0)return{};let t=e[0][0],n=t,r=e[0][1],i=r;for(let[a,o]of e)t>a&&(t=a),n<a&&(n=a),r>o&&(r=o),i<o&&(i=o);return{minLat:t,maxLat:n,minLon:r,maxLon:i}}function q(e){let{minLat:t,maxLat:n,minLon:r,maxLon:i}=K(e);return[t===void 0||n===void 0?0:(n+t)/2,r===void 0||i===void 0?0:(i+r)/2]}function J(e){return Array.isArray(e)&&e.length===2&&typeof e[0]==`number`&&typeof e[1]==`number`}const Y=[.005,.018];function X(e){return Array.isArray(e)?J(e)?{minLat:e[0],maxLat:e[0],minLon:e[1],maxLon:e[1]}:K(e):e}function Z(e,[t,n]=Y){let{minLat:r=0,maxLat:i=0,minLon:a=0,maxLon:o=0}=X(e);return{minLat:r-t,maxLat:i+t,minLon:a-n,maxLon:o+n}}exports.DEG=n,exports.MAX_LAT=a,exports.MAX_LON=180,exports.MIN_LAT=i,exports.MIN_LON=o,exports.MapArea=g,exports.RAD=t,exports.addClickListener=y,exports.addElement=w,exports.addNavigation=E,exports.addPersistence=D,exports.addResizeObserver=O,exports.addShape=P,exports.addShapeEditor=F,exports.addTiles=W,exports.addZoomControls=G,exports.eccentricityMap=r,exports.getCenter=q,exports.getGeoBounds=K,exports.getId=b,exports.getLayer=x,exports.getPointerPosition=_,exports.getVicinity=Z,exports.isGeoCoords=J,exports.resolveString=S,exports.toPrecision=C;
1
+ const{PI:e}=Math,t=e/180,n=180/e,r={spherical:0,ellipsoidal:.0818191908426},i=-85.05,a=85.05,o=-180,s=180,{PI:c,sin:l,tan:u,atan:d,pow:f,exp:p,log:m,abs:h}=Math;var g=class{_p;_c;_cc;_r=new Set;constructor(e){this._p=e,this.container.style=`position: relative; overflow: hidden;`,this.container.dataset.type=`maparea`}render(){for(let e of this._r)e(this)}onRender(e,t=!1){return this._r.add(e),t||e(this),()=>{this._r.delete(e)}}getOptions(){return{...this._p,center:this.center,bounds:this.bounds}}setOptions(e){this._p={...this._p,...e},delete this._c,delete this._cc,this.render()}get container(){if(!this._c){let e=document.querySelector(this._p.container);if(!e)throw Error(`missing container element`);this._c=e}return this._c}get box(){let e=this.container.getBoundingClientRect();return{x:e.left,y:e.top,w:e.width,h:e.height}}get bounds(){let e=this._p.bounds;return e?{...e}:{}}set bounds(e){this._p.bounds=e}get center(){let e=this._p.center;return e?e.slice():[0,0]}set center(e){this._p.center=e,delete this._cc,this.render()}get centerCoords(){if(!this._cc){let[e,t]=this.center;this._cc=this.toPixelCoords(e,t)}return this._cc}get zoom(){return this._p.zoom??this._p.minZoom??0}set zoom(e){let{minZoom:t,maxZoom:n}=this,r=e;e<t&&(r=t),e>n&&(r=n),this._p.zoom=r,delete this._cc,this.render()}get minZoom(){return this._p.minZoom??-1/0}set minZoom(e){this._p.minZoom=e,this.zoom<this.minZoom&&(this.zoom=this.minZoom)}get maxZoom(){return this._p.maxZoom??1/0}set maxZoom(e){this._p.maxZoom=e,this.zoom>this.maxZoom&&(this.zoom=this.maxZoom)}get projection(){return this._p.projection??`spherical`}set projection(e){this._p.projection=e,this.render()}get lang(){return this._p.lang??``}set lang(e){this._p.lang=e,this.render()}inPixelBounds(e,t){let[n,r]=this.toGeoCoords(e,t);return this.inBounds(n,r)}inBounds(e,t){let{minLat:n=i,maxLat:r=a,minLon:s=o,maxLon:c=180}=this.bounds;return e>=n&&e<=r&&t>=s&&t<=c}canMoveTo(e,t){if(!this.inBounds(e,t))return!1;let{w:n,h:r}=this.box;if(n===0||r===0)return!1;let[i,a]=this.toPixelCoords(e,t);return this.inPixelBounds(i-n/2,a-r/2)&&this.inPixelBounds(i+n/2,a+r/2)}toPixelCoords(e,n){let i=r[this.projection],a=f(2,this.zoom+7)/c,o=e*t,s=i===0?1:f((1-i*l(o))/(1+i*l(o)),i/2);return[a*(c+n*t),a*(c-m(s*u(c/4+o/2)))]}toGeoCoords(e,t){let o=r[this.projection],s=f(2,this.zoom+7)/c,l=(e/s-c)*n,u;if(o===0)u=2*(d(p(c-t/s))-c/4)*n;else{u=i;let e=a-i,n=NaN,r=0;for(;(Number.isNaN(n)||h(n-t)>.1)&&r++<30;)e/=2,n=this.toPixelCoords(u+e,l)[1],n>t&&(u+=e)}return(l<-180||l>=180)&&(l=(l+180)%360-180),(u<-90||u>=90)&&(u=(u+90)%180-90),[u,l]}};function _(e){let t=`touches`in e?e.touches[0]:e;return t?[t.clientX,t.clientY]:null}function v(e,t){return t===void 0||!(e instanceof HTMLElement)?!1:typeof t==`function`&&t(e)||typeof t==`string`&&e.closest(t)!==null}function y(e,t,n){let r=Date.now(),i=null,a=e=>{r=Date.now(),i=_(e)},o=a=>{if(v(a.target,n)||!i||Date.now()-r>150)return;let{box:o,centerCoords:[s,c]}=e,l=i[0]-o.x,u=i[1]-o.y,[d,f]=e.toGeoCoords(l-.5*o.w+s,u-.5*o.h+c);t({x:l,y:u,lat:d,lon:f,originalEvent:a}),i=null};return e.container.addEventListener(`mousedown`,a),e.container.addEventListener(`mouseup`,o),e.container.addEventListener(`touchstart`,a),e.container.addEventListener(`touchend`,o),()=>{e.container.removeEventListener(`mousedown`,a),e.container.removeEventListener(`mouseup`,o),e.container.removeEventListener(`touchstart`,a),e.container.removeEventListener(`touchend`,o)}}function b(){return Math.random().toString(36).slice(2)}function x(e,{id:t,className:n,inset:r=`0`}={}){let i=`${n?`.${n}`:``}${t?`[data-id="${t}"]`:``}`,a=document.querySelector(i);return a||(a=document.createElement(`div`),a.className=`${n?`${n} `:``}layer`,a.dataset.id=t??b(),a.style=`position: absolute; inset: ${r};`,e.container.append(a)),a}function S(e,t){return t===void 0?t:t instanceof Function?t(e):t}function C(e,t){return e.toFixed(t).replace(/\.(\d*[^0])0+$/,`.$1`).replace(/\.0+$/,``)}function w(e,t,{className:n,coords:r,inset:i,layer:a,content:o}){let s=a??x(e,{className:`elements`});n&&t.setAttribute(`class`,n),t.style.position=`absolute`,s.append(t),e.onRender(()=>{if(i)t.style.inset=S(e,i)??``;else if(r){let{centerCoords:[n,i],box:{w:a,h:o}}=e,[s,c]=e.toPixelCoords(...r),l=C(s-n+a/2,2),u=C(c-i+o/2,2);t.style.transform=`translate3d(${l}px, ${u}px, 0)`}if(o){let n=S(e,o)??``;t.innerHTML!==n&&(t.innerHTML=n)}})}function T(e,{onStart:t,onMove:n,onEnd:r,wheel:i}={}){let a=null,o=null,s=Date.now(),c=!1,l=null,u=null;function d(t,r,i=100){u!==null&&(clearTimeout(u),u=null),l!==null&&(cancelAnimationFrame(l),l=null);let c=Date.now();c-s<i||(a!==null&&(a-=t),o!==null&&(o-=r),s=c,e.dataset.dragged||(e.dataset.dragged=`true`),l=requestAnimationFrame(()=>{l=null,(t!==0||r!==0)&&n?.(t,r)}))}function f(e,t,n){a!==null&&o!==null&&d(a-e,o-t,n)}function p(e,n){c=!0,t?.(),e!==void 0&&(a=e),n!==void 0&&(o=n),s=Date.now()}function m(t,n){c=!1,u=null,t!==void 0&&n!==void 0&&f(t,n),delete e.dataset.dragged,a=null,o=null,requestAnimationFrame(()=>{r?.()})}e.dataset.draggable=`true`;let h=null,g=null;e.addEventListener(`mousedown`,t=>{t.preventDefault(),!h&&(p(t.clientX,t.clientY),h=e=>{e.preventDefault(),f(e.clientX,e.clientY)},e.addEventListener(`mousemove`,h))}),e.addEventListener(`mouseup`,t=>{t.preventDefault(),h&&=(m(t.clientX,t.clientY),e.removeEventListener(`mousemove`,h),null)}),e.addEventListener(`touchstart`,t=>{t.preventDefault(),!g&&(p(t.touches[0]?.clientX,t.touches[0]?.clientY),g=e=>{e.preventDefault(),f(e.touches[0]?.clientX,e.touches[0]?.clientY)},e.addEventListener(`touchmove`,g))}),e.addEventListener(`touchend`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),e.addEventListener(`touchcancel`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),i&&e.addEventListener(`wheel`,e=>{e.preventDefault(),c||p(),e.shiftKey?d(e.deltaY,e.deltaX,10):d(e.deltaX,e.deltaY,10),u=setTimeout(()=>{m()},200)})}function E(e,t){let n=0,r=0;T(e.container,{onStart(){[n,r]=e.centerCoords},onMove(t,i){let a=n+t,o=r+i,s=e.toGeoCoords(a,o);e.canMoveTo(...s)&&(e.center=s,n=a,r=o)},wheel:t?.wheel??!0})}function D(e,{storageKey:t,session:n=!1}={}){let r=n?window.sessionStorage:window.localStorage,i=t??[`maparea`,e.container.id].filter(Boolean).join(`#`),a=e.getOptions(),o=!1,s=()=>{try{r.setItem(i,JSON.stringify(e.getOptions()))}catch{}},c=()=>{try{let t=r.getItem(i);t===null?s():e.setOptions(JSON.parse(t))}catch{}},l=e=>{o=e===void 0?!o:e},u=()=>{e.setOptions(a)};c();let d=null;return e.onRender(()=>{o||(d&&=(clearTimeout(d),null),d=setTimeout(()=>{d=null,s()},350))}),{sync:c,write:s,toggle:l,reset:u}}function O(e,t){let n=new ResizeObserver(n=>{for(let r of n)if(r.contentBoxSize){if(t)if(r.contentBoxSize){let{inlineSize:e,blockSize:n}=r.contentBoxSize[0]??r.contentBoxSize;t({inlineSize:e,blockSize:n})}else{let{width:e,height:n}=r.contentRect;t({width:e,height:n})}e.render()}});return n.observe(e.container),()=>{n.unobserve(e.container)}}const k=`http://www.w3.org/2000/svg`,A={className:`shape`};function j(e,t,n){let r=x(e,n??A);r.toggleAttribute(`hidden`,t.length===0);let i=r.querySelector(`svg`);i||(i=document.createElementNS(k,`svg`),i.setAttribute(`xmlns`,k),r.append(i));let a=N(i,t.map(({id:t,coords:[n,r]})=>({id:t,coords:e.toPixelCoords(n,r)})),n);if(a){let{xMin:t,xMax:n,yMin:r,yMax:o}=a,{centerCoords:[s,c],box:l}=e,u=C(n-t,3),d=C(o-r,3),f=C(.5*l.w+t-s,2),p=C(.5*l.h+r-c,2);i.setAttribute(`viewBox`,`0 0 ${u} ${d}`),i.setAttribute(`width`,u),i.setAttribute(`height`,d),i.setAttribute(`style`,`position: absolute; transform: translate3d(${f}px, ${p}px, 0);`)}return r}function M(e){return parseFloat(window.getComputedStyle(e).strokeWidth||e.getAttribute(`stroke-width`)||`1`)}function N(e,t,n){if(t.length===0){e.innerHTML=``;return}let r=e.querySelector(`path`);r||(r=document.createElementNS(k,`path`),e.append(r));let i=t[0].coords[0],a=i,o=t[0].coords[1],s=o,c=``;for(let{coords:[e,n]}of t)i>e&&(i=e),a<e&&(a=e),o>n&&(o=n),s<n&&(s=n);i-=10,a+=10,o-=10,s+=10;let l=Array.from(e.querySelectorAll(`.marker`)),u=0;for(let{id:a,coords:[s,d]}of t){let t=C(s-i,3),f=C(d-o,3);if(c+=`${c?` L`:`M`} ${t} ${f}`,n?.markers){let n=l[u++];n||(n=document.createElementNS(k,`circle`),n.setAttribute(`class`,`marker`),n.setAttribute(`r`,String(1.5*M(r))),e.append(n)),n.setAttribute(`cx`,t),n.setAttribute(`cy`,f),n.dataset.id=a}}for(let e=u;e<l.length;e++)l[e].remove();return r.setAttribute(`d`,c),{xMin:i,xMax:a,yMin:o,yMax:s}}function P(e,t,n){let r=t.map(e=>({id:b(),coords:e}));e.onRender(()=>{j(e,r,{className:`shape`,...n})})}function F(e,t){let n=[],r=null,i={className:`shape-editor`,markers:!0},a=()=>{j(e,n,i),t?.onUpdate?.(n)};y(e,({lat:e,lon:t,originalEvent:i})=>{let o=(i.target?.closest(`.marker`))?.dataset.id;if(o&&r){clearTimeout(r),r=null,n=n.filter(({id:e})=>e!==o),a();return}let s=()=>{n.push({id:b(),coords:[e,t]}),a(),r=null};o?r=setTimeout(s,250):s()},t?.ignoreClicks),e.onRender(a)}const{floor:I,ceil:L,random:R}=Math,ee=256;function z(e,t,n){return`${t},${n},${e.zoom},${e.lang}`}function B(e,t,n,{size:r,url:i,subdomains:a,error:o}){let s=new Image,c=S(e,r)??256;return s.width=c,s.height=c,s.src=((r,o)=>{if(!i)return``;if(typeof i==`function`)return i(e,t,n);let s=i.replaceAll(`{x}`,String(r)).replaceAll(`{y}`,String(o)).replaceAll(`{z}`,String(e.zoom)).replaceAll(`{lang}`,e.lang);return a&&s.includes(`{s}`)&&(s=s.replaceAll(`{s}`,a[I(a.length*R())])),s})(t,n),s.dataset.id=z(e,t,n),s.style=`position: absolute;`,s.addEventListener(`error`,t=>{let n=t.target;if(n instanceof HTMLImageElement){let t=S(e,o);t&&(n.dataset.src=s.src,n.src=t)}}),s}function V(e){return e.querySelectorAll(`img[data-id]`)}function H(e,t){return e.querySelector(`img[data-id="${t}"]`)}function U(e,t={}){let{id:n=b(),attribution:r,attributionInset:i=`auto 0 0 auto`}=t,a=x(e,{id:n,className:`tiles`,...t}),o=x(e,{id:n,className:`tiles-attribution`,inset:i}),s=()=>{let{box:{w:n,h:i},centerCoords:[s,c]}=e,{size:l,margin:u=0}=t,d=S(e,l)??256,f=Array.isArray(u)?u[0]:u,p=Array.isArray(u)?u[1]:u,m=L((n+2*f)/d),h=L((i+2*p)/d),g=I(s/d),_=I(c/d),v=null,y=new Set,b=``;for(let r=0;r<=m;r++){let o=g+(r%2==0?-1:1)*I(r/2);for(let r=0;r<=h;r++){let l=_+(r%2==0?-1:1)*I(r/2);b=z(e,o,l),v=H(a,b),v||(v=B(e,o,l,t),a.append(v));let u=C(.5*n+o*d-s,2),f=C(.5*i+l*d-c,2);v.style.transform=`translate3d(${u}px, ${f}px, 0)`,y.add(b)}}for(let e of V(a)){let{id:t}=e.dataset;t&&!y.has(t)&&e.remove()}let x=S(e,r)??``;o.toggleAttribute(`hidden`,!x),o.innerHTML!==x&&(o.innerHTML=x)},c=e.zoom,l=null;return e.onRender(()=>{l!==null&&(clearTimeout(l),l=null),e.zoom===c?(a.style.opacity=``,s()):(a.style.opacity=`0`,l=setTimeout(()=>{l=null,a.style.opacity=``,s()},300)),c=e.zoom}),a}function W(e,t={}){let{plus:n=`➕`,minus:r=`➖`,inset:i=`0 0 auto auto`}=t,a=x(e,{className:`zoom-controls`,inset:i}),o=document.createElement(`button`);o.dataset.id=`plus`,o.innerHTML=n;let s=document.createElement(`button`);s.dataset.id=`minus`,s.innerHTML=r;let c=()=>{o.toggleAttribute(`disabled`,e.zoom+1>e.maxZoom),s.toggleAttribute(`disabled`,e.zoom-1<e.minZoom)};return y(e,({originalEvent:t})=>{let n=t.target?.closest(`button`);n&&(t.stopPropagation(),e.zoom+=n.dataset.id===`minus`?-1:1,c())}),e.onRender(c),a.append(o,s),a}const{abs:G,log2:K,min:q,floor:J}=Math;function Y(e,t){let{box:{w:n,h:r},center:[i,a],zoom:o}=e,{minLat:s,maxLat:c,minLon:l,maxLon:u}=t,d=0,f=0;if(l!==void 0&&u!==void 0){let t=G(e.toPixelCoords(i,u)[0]-e.toPixelCoords(i,l)[0]);t!==0&&(d=K(n/t))}if(s!==void 0&&c!==void 0){let t=G(e.toPixelCoords(s,a)[1]-e.toPixelCoords(c,a)[1]);t!==0&&(f=K(r/t))}let p=J(q(o+d,o+f));p!==o&&(e.zoom=p)}function X(e){if(e.length===0)return{};let t=e[0][0],n=t,r=e[0][1],i=r;for(let[a,o]of e)t>a&&(t=a),n<a&&(n=a),r>o&&(r=o),i<o&&(i=o);return{minLat:t,maxLat:n,minLon:r,maxLon:i}}function Z(e){let{minLat:t,maxLat:n,minLon:r,maxLon:i}=X(e);return[t===void 0||n===void 0?0:(n+t)/2,r===void 0||i===void 0?0:(i+r)/2]}function Q(e){return Array.isArray(e)&&e.length===2&&typeof e[0]==`number`&&typeof e[1]==`number`}function $(e){return Q(e)?{minLat:e[0],maxLat:e[0],minLon:e[1],maxLon:e[1]}:Array.isArray(e)?X(e):e}const te=[.005,.018];function ne(e,t=te){let{minLat:n=0,maxLat:r=0,minLon:i=0,maxLon:a=0}=$(e),[o,s]=t;return{minLat:n-o,maxLat:r+o,minLon:i-s,maxLon:a+s}}exports.DEG=n,exports.MAX_LAT=a,exports.MAX_LON=180,exports.MIN_LAT=i,exports.MIN_LON=o,exports.MapArea=g,exports.RAD=t,exports.addClickListener=y,exports.addElement=w,exports.addMovableViewport=E,exports.addPersistence=D,exports.addResizeObserver=O,exports.addShape=P,exports.addShapeEditor=F,exports.addTiles=U,exports.addZoomControls=W,exports.eccentricityMap=r,exports.fitGeoBounds=Y,exports.getCenter=Z,exports.getGeoBounds=X,exports.getId=b,exports.getLayer=x,exports.getPointerPosition=_,exports.getVicinity=ne,exports.isCoordsArray=Q,exports.resolveDynamic=S,exports.toGeoBounds=$,exports.toPrecision=C;
package/dist/index.d.ts CHANGED
@@ -89,19 +89,19 @@ type MapAreaClickEvent = {
89
89
  };
90
90
  type MapAreaClickCallback = (event: MapAreaClickEvent) => void;
91
91
  /**
92
- * Adds a click listener to the map and returns a function
93
- * removing the added click listener.
92
+ * Adds a click listener to the map and returns a function that removes
93
+ * the added listener.
94
94
  */
95
95
  declare function addClickListener(map: MapArea, callback: MapAreaClickCallback, ignored?: IgnoredElement): () => void;
96
96
 
97
- type DynamicString = string | ((map: MapArea) => string);
97
+ type Dynamic<T> = T | ((map: MapArea) => T);
98
98
 
99
99
  type MapAreaElementOptions = {
100
100
  className?: string; /** Geographical position (`[lat, lon]`) of the element's top left corner. */
101
101
  coords?: GeoCoords; /** CSS `inset` (disregarding `coords`). */
102
- inset?: DynamicString; /** Target layer. */
102
+ inset?: Dynamic<string>; /** Target layer. */
103
103
  layer?: Element; /** HTML content of the element. */
104
- content?: DynamicString;
104
+ content?: Dynamic<string>;
105
105
  };
106
106
  /**
107
107
  * Adds an HTML or SVG element to the map.
@@ -118,12 +118,25 @@ declare function addElement(map: MapArea, element: HTMLElement | SVGSVGElement,
118
118
  content
119
119
  }: MapAreaElementOptions): void;
120
120
 
121
- declare function addNavigation(map: MapArea): void;
121
+ type MapAreaNavigationOptions = {
122
+ wheel?: boolean;
123
+ };
124
+ /**
125
+ * Enables navigation over the given map container with a mouse or touches
126
+ * or a scroll wheel (the latter can be disabled by setting `options.wheel`
127
+ * to `false`).
128
+ */
129
+ declare function addMovableViewport(map: MapArea, options?: MapAreaNavigationOptions): void;
122
130
 
123
131
  type PersistenceOptions = {
124
132
  storageKey?: string;
125
133
  session?: boolean;
126
134
  };
135
+ /**
136
+ * Enables persistence of the map's state across page reloads by saving it to
137
+ * the browser storage (`localStorage` by default, `sessionStorage` with
138
+ * `session` set to `true`).
139
+ */
127
140
  declare function addPersistence(map: MapArea, {
128
141
  storageKey,
129
142
  session
@@ -145,6 +158,9 @@ type MapAreaResizeEvent = {
145
158
  height?: number;
146
159
  };
147
160
  type MapAreaResizeCallback = (event: MapAreaResizeEvent) => void;
161
+ /**
162
+ * Adds a resize observer to the map and returns a function turning it off.
163
+ */
148
164
  declare function addResizeObserver(map: MapArea, callback?: MapAreaResizeCallback): () => void;
149
165
 
150
166
  type LayerOptions = {
@@ -153,6 +169,10 @@ type LayerOptions = {
153
169
  inset?: string;
154
170
  };
155
171
 
172
+ /**
173
+ * Adds a shape based on the given array of geographic coordinates to
174
+ * the specified map layer.
175
+ */
156
176
  declare function addShape(map: MapArea, coords: GeoCoords[], layerOptions?: LayerOptions): void;
157
177
 
158
178
  type Vertex<T> = {
@@ -166,6 +186,9 @@ type ShapeEditorOptions = {
166
186
  onUpdate?: (shape: GeoVertex[]) => void;
167
187
  ignoreClicks?: IgnoredElement;
168
188
  };
189
+ /**
190
+ * Adds a shape editor to the given map container.
191
+ */
169
192
  declare function addShapeEditor(map: MapArea, options?: ShapeEditorOptions): void;
170
193
 
171
194
  type MapAreaTileOptions = LayerOptions & {
@@ -175,18 +198,22 @@ type MapAreaTileOptions = LayerOptions & {
175
198
  * or a function of `(map, x, y) => string` returning a fixed string URL.
176
199
  */
177
200
  url?: string | ((map: MapArea, xIndex: number, yIndex: number) => string); /** Values of the `{s}` placeholder of the tile URLs. */
178
- subdomains?: string[]; /** Maximum retry count per tile. */
179
- retries?: number; /** URL to be used instead of a tile that failed to load. */
180
- error?: DynamicString; /** Tile size. */
181
- size?: number;
201
+ subdomains?: string[]; /** URL to be used instead of a tile that failed to load. */
202
+ error?: Dynamic<string>; /** Tile size. */
203
+ size?: Dynamic<number>;
182
204
  /**
183
205
  * Margin in pixels, or a tuple of an x- and y-margin, to be tiled
184
206
  * outside the viewport.
185
207
  */
186
208
  margin?: number | [number, number]; /** Attribution HTML content. */
187
- attribution?: DynamicString; /** Attribution's CSS `inset`. */
209
+ attribution?: Dynamic<string>; /** Attribution's CSS `inset`. */
188
210
  attributionInset?: string;
189
211
  };
212
+ /**
213
+ * Adds image tiles to the given map container based on `options.url`,
214
+ * which is a string URL with placeholders or a function of
215
+ * `(map, xIndex, yIndex) => string`.
216
+ */
190
217
  declare function addTiles(map: MapArea, options?: MapAreaTileOptions): HTMLElement;
191
218
 
192
219
  type ZoomControlOptions = {
@@ -194,6 +221,9 @@ type ZoomControlOptions = {
194
221
  minus?: string; /** CSS `inset` */
195
222
  inset?: string;
196
223
  };
224
+ /**
225
+ * Adds customizable zoom controls to the given map container.
226
+ */
197
227
  declare function addZoomControls(map: MapArea, options?: ZoomControlOptions): HTMLElement;
198
228
 
199
229
  type PixelVertex = Vertex<PixelCoords>;
@@ -202,10 +232,26 @@ type ShapeLayerOptions = LayerOptions & {
202
232
  markers?: boolean;
203
233
  };
204
234
 
235
+ /**
236
+ * Fits the map to the given geographic bounds.
237
+ */
238
+ declare function fitGeoBounds(map: MapArea, bounds: GeoBounds): void;
239
+
240
+ /**
241
+ * Calculates the geographic coordinates of the center of an array
242
+ * of geographic coordinates.
243
+ */
205
244
  declare function getCenter(coords: GeoCoords[]): GeoCoords;
206
245
 
246
+ /**
247
+ * Returns the minimal and maximal latitudes and longitudes of
248
+ * an array of geographic coordinates.
249
+ */
207
250
  declare function getGeoBounds(coords: GeoCoords[]): GeoBounds;
208
251
 
252
+ /**
253
+ * Generates a string ID.
254
+ */
209
255
  declare function getId(): string;
210
256
 
211
257
  /**
@@ -218,14 +264,31 @@ declare function getLayer(map: MapArea, {
218
264
  inset
219
265
  }?: LayerOptions): HTMLElement;
220
266
 
267
+ /**
268
+ * Returns the pointer pixel position `[x, y]` of the given mouse or
269
+ * touch event.
270
+ */
221
271
  declare function getPointerPosition(event: MouseEvent | TouchEvent): [number, number] | null;
222
272
 
223
- declare function getVicinity(x: GeoCoords | GeoCoords[] | GeoBounds, [dLat, dLon]?: GeoCoords): GeoBounds;
273
+ /**
274
+ * Returns the minimal and maximal latitudes and longitudes of a region
275
+ * surrounding a geographic area, an array of geographic coordinates,
276
+ * or a single point.
277
+ */
278
+ declare function getVicinity(x: GeoCoords | GeoCoords[] | GeoBounds, padding?: GeoCoords): GeoBounds;
279
+
280
+ /**
281
+ * Checks whether the given value is an array of coordinates.
282
+ */
283
+ declare function isCoordsArray(x: unknown): x is [number, number];
224
284
 
225
- declare function isGeoCoords(x: unknown): x is GeoCoords;
285
+ /**
286
+ * Resolves a dynamic value to a static value based on the context.
287
+ */
288
+ declare function resolveDynamic<T>(map: MapArea, x: Dynamic<T> | undefined): T | undefined;
226
289
 
227
- declare function resolveString(map: MapArea, x: DynamicString | undefined): string;
290
+ declare function toGeoBounds(x: GeoCoords | GeoCoords[] | GeoBounds): GeoBounds;
228
291
 
229
292
  declare function toPrecision(x: number, n: number): string;
230
293
 
231
- export { BoxDimensions, DEG, DynamicString, GeoBounds, GeoCoords, GeoVertex, IgnoredElement, LayerOptions, MAX_LAT, MAX_LON, MIN_LAT, MIN_LON, MapArea, MapAreaClickCallback, MapAreaClickEvent, MapAreaElementOptions, MapAreaOptions, MapAreaResizeCallback, MapAreaResizeEvent, MapAreaTileOptions, PersistenceOptions, PixelCoords, PixelVertex, Projection, RAD, RenderCallback, ShapeEditorOptions, ShapeLayerOptions, ZoomControlOptions, addClickListener, addElement, addNavigation, addPersistence, addResizeObserver, addShape, addShapeEditor, addTiles, addZoomControls, eccentricityMap, getCenter, getGeoBounds, getId, getLayer, getPointerPosition, getVicinity, isGeoCoords, resolveString, toPrecision };
294
+ export { BoxDimensions, DEG, Dynamic, GeoBounds, GeoCoords, GeoVertex, IgnoredElement, LayerOptions, MAX_LAT, MAX_LON, MIN_LAT, MIN_LON, MapArea, MapAreaClickCallback, MapAreaClickEvent, MapAreaElementOptions, MapAreaNavigationOptions, MapAreaOptions, MapAreaResizeCallback, MapAreaResizeEvent, MapAreaTileOptions, PersistenceOptions, PixelCoords, PixelVertex, Projection, RAD, RenderCallback, ShapeEditorOptions, ShapeLayerOptions, ZoomControlOptions, addClickListener, addElement, addMovableViewport, addPersistence, addResizeObserver, addShape, addShapeEditor, addTiles, addZoomControls, eccentricityMap, fitGeoBounds, getCenter, getGeoBounds, getId, getLayer, getPointerPosition, getVicinity, isCoordsArray, resolveDynamic, toGeoBounds, toPrecision };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- const{PI:e}=Math,t=e/180,n=180/e,r={spherical:0,ellipsoidal:.0818191908426},i=-85.05,a=85.05,o=-180,s=180,{PI:c,sin:l,tan:u,atan:d,pow:f,exp:p,log:m,abs:h}=Math;var g=class{_p;_c;_cc;_r=new Set;constructor(e){this._p=e,this.container.style=`position: relative; overflow: hidden;`,this.container.dataset.type=`maparea`}render(){for(let e of this._r)e(this)}onRender(e,t=!1){return this._r.add(e),t||e(this),()=>{this._r.delete(e)}}getOptions(){return{...this._p,center:this.center,bounds:this.bounds}}setOptions(e){this._p={...this._p,...e},delete this._c,delete this._cc,this.render()}get container(){if(!this._c){let e=document.querySelector(this._p.container);if(!e)throw Error(`missing container element`);this._c=e}return this._c}get box(){let e=this.container.getBoundingClientRect();return{x:e.left,y:e.top,w:e.width,h:e.height}}get bounds(){let e=this._p.bounds;return e?{...e}:{}}set bounds(e){this._p.bounds=e}get center(){let e=this._p.center;return e?e.slice():[0,0]}set center(e){this._p.center=e,delete this._cc,this.render()}get centerCoords(){if(!this._cc){let[e,t]=this.center;this._cc=this.toPixelCoords(e,t)}return this._cc}get zoom(){return this._p.zoom??this._p.minZoom??0}set zoom(e){let{minZoom:t,maxZoom:n}=this,r=e;e<t&&(r=t),e>n&&(r=n),this._p.zoom=r,delete this._cc,this.render()}get minZoom(){return this._p.minZoom??-1/0}set minZoom(e){this._p.minZoom=e,this.zoom<this.minZoom&&(this.zoom=this.minZoom)}get maxZoom(){return this._p.maxZoom??1/0}set maxZoom(e){this._p.maxZoom=e,this.zoom>this.maxZoom&&(this.zoom=this.maxZoom)}get projection(){return this._p.projection??`spherical`}set projection(e){this._p.projection=e,this.render()}get lang(){return this._p.lang??``}set lang(e){this._p.lang=e,this.render()}inPixelBounds(e,t){let[n,r]=this.toGeoCoords(e,t);return this.inBounds(n,r)}inBounds(e,t){let{minLat:n=i,maxLat:r=a,minLon:s=o,maxLon:c=180}=this.bounds;return e>=n&&e<=r&&t>=s&&t<=c}canMoveTo(e,t){if(!this.inBounds(e,t))return!1;let{w:n,h:r}=this.box;if(n===0||r===0)return!1;let[i,a]=this.toPixelCoords(e,t);return this.inPixelBounds(i-n/2,a-r/2)&&this.inPixelBounds(i+n/2,a+r/2)}toPixelCoords(e,n){let i=r[this.projection],a=f(2,this.zoom+7)/c,o=e*t,s=i===0?1:f((1-i*l(o))/(1+i*l(o)),i/2);return[a*(c+n*t),a*(c-m(s*u(c/4+o/2)))]}toGeoCoords(e,t){let o=r[this.projection],s=f(2,this.zoom+7)/c,l=(e/s-c)*n,u;if(o===0)u=2*(d(p(c-t/s))-c/4)*n;else{u=i;let e=a-i,n=NaN,r=0;for(;(Number.isNaN(n)||h(n-t)>.1)&&r++<30;)e/=2,n=this.toPixelCoords(u+e,l)[1],n>t&&(u+=e)}return(l<-180||l>=180)&&(l=(l+180)%360-180),(u<-90||u>=90)&&(u=(u+90)%180-90),[u,l]}};function _(e){let t=`touches`in e?e.touches[0]:e;return t?[t.clientX,t.clientY]:null}function v(e,t){return t===void 0||!(e instanceof HTMLElement)?!1:typeof t==`function`&&t(e)||typeof t==`string`&&e.closest(t)!==null}function y(e,t,n){let r=Date.now(),i=null,a=e=>{r=Date.now(),i=_(e)},o=a=>{if(v(a.target,n)||!i||Date.now()-r>150)return;let{box:o,centerCoords:[s,c]}=e,l=i[0]-o.x,u=i[1]-o.y,[d,f]=e.toGeoCoords(l-.5*o.w+s,u-.5*o.h+c);t({x:l,y:u,lat:d,lon:f,originalEvent:a}),i=null};return e.container.addEventListener(`mousedown`,a),e.container.addEventListener(`mouseup`,o),e.container.addEventListener(`touchstart`,a),e.container.addEventListener(`touchend`,o),()=>{e.container.removeEventListener(`mousedown`,a),e.container.removeEventListener(`mouseup`,o),e.container.removeEventListener(`touchstart`,a),e.container.removeEventListener(`touchend`,o)}}function b(){return Math.random().toString(36).slice(2)}function x(e,{id:t,className:n,inset:r=`0`}={}){let i=`${n?`.${n}`:``}${t?`[data-id="${t}"]`:``}`,a=document.querySelector(i);return a||(a=document.createElement(`div`),a.className=`${n?`${n} `:``}layer`,a.dataset.id=t??b(),a.style=`position: absolute; inset: ${r};`,e.container.append(a)),a}function S(e,t){return typeof t==`function`?t(e):t??``}function C(e,t){return e.toFixed(t).replace(/\.(\d*[^0])0+$/,`.$1`).replace(/\.0+$/,``)}function w(e,t,{className:n,coords:r,inset:i,layer:a,content:o}){let s=a??x(e,{className:`elements`});n&&t.setAttribute(`class`,n),t.style.position=`absolute`,s.append(t),e.onRender(()=>{if(i)t.style.inset=S(e,i);else if(r){let{centerCoords:[n,i],box:{w:a,h:o}}=e,[s,c]=e.toPixelCoords(...r),l=C(s-n+a/2,2),u=C(c-i+o/2,2);t.style.transform=`translate3d(${l}px, ${u}px, 0)`}if(o){let n=S(e,o);t.innerHTML!==n&&(t.innerHTML=n)}})}function T(e,{onStart:t,onMove:n,onEnd:r,wheel:i}={}){let a=null,o=null,s=Date.now(),c=!1,l=null,u=null;function d(t,r,i=100){u!==null&&(clearTimeout(u),u=null),l!==null&&(cancelAnimationFrame(l),l=null);let c=Date.now();c-s<i||(a!==null&&(a-=t),o!==null&&(o-=r),s=c,e.dataset.dragged||(e.dataset.dragged=`true`),l=requestAnimationFrame(()=>{l=null,(t!==0||r!==0)&&n?.(t,r)}))}function f(e,t,n){a!==null&&o!==null&&d(a-e,o-t,n)}function p(e,n){c=!0,t?.(),e!==void 0&&(a=e),n!==void 0&&(o=n),s=Date.now()}function m(t,n){c=!1,u=null,t!==void 0&&n!==void 0&&f(t,n),delete e.dataset.dragged,a=null,o=null,requestAnimationFrame(()=>{r?.()})}e.dataset.draggable=`true`;let h=null,g=null;e.addEventListener(`mousedown`,t=>{t.preventDefault(),!h&&(p(t.clientX,t.clientY),h=e=>{e.preventDefault(),f(e.clientX,e.clientY)},e.addEventListener(`mousemove`,h))}),e.addEventListener(`mouseup`,t=>{t.preventDefault(),h&&=(m(t.clientX,t.clientY),e.removeEventListener(`mousemove`,h),null)}),e.addEventListener(`touchstart`,t=>{t.preventDefault(),!g&&(p(t.touches[0]?.clientX,t.touches[0]?.clientY),g=e=>{e.preventDefault(),f(e.touches[0]?.clientX,e.touches[0]?.clientY)},e.addEventListener(`touchmove`,g))}),e.addEventListener(`touchend`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),e.addEventListener(`touchcancel`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),i&&e.addEventListener(`wheel`,e=>{e.preventDefault(),c||p(),e.shiftKey?d(e.deltaY,e.deltaX,10):d(e.deltaX,e.deltaY,10),u=setTimeout(()=>{m()},200)})}function E(e){let t=0,n=0;T(e.container,{onStart(){[t,n]=e.centerCoords},onMove(r,i){let a=t+r,o=n+i,s=e.toGeoCoords(a,o);e.canMoveTo(...s)&&(e.center=s,t=a,n=o)},wheel:!0})}function D(e,{storageKey:t,session:n=!1}={}){let r=n?window.sessionStorage:window.localStorage,i=t??[`maparea`,e.container.id].filter(Boolean).join(`#`),a=e.getOptions(),o=!1,s=()=>{try{r.setItem(i,JSON.stringify(e.getOptions()))}catch{}},c=()=>{try{let t=r.getItem(i);t===null?s():e.setOptions(JSON.parse(t))}catch{}},l=e=>{o=e===void 0?!o:e},u=()=>{e.setOptions(a)};c();let d=null;return e.onRender(()=>{o||(d&&=(clearTimeout(d),null),d=setTimeout(()=>{d=null,s()},350))}),{sync:c,write:s,toggle:l,reset:u}}function O(e,t){let n=new ResizeObserver(n=>{for(let r of n)if(r.contentBoxSize){if(t)if(r.contentBoxSize){let{inlineSize:e,blockSize:n}=r.contentBoxSize[0]??r.contentBoxSize;t({inlineSize:e,blockSize:n})}else{let{width:e,height:n}=r.contentRect;t({width:e,height:n})}e.render()}});return n.observe(e.container),()=>{n.unobserve(e.container)}}const k=`http://www.w3.org/2000/svg`,A={className:`shape`};function j(e,t,n){let r=x(e,n??A);r.toggleAttribute(`hidden`,t.length===0);let i=r.querySelector(`svg`);i||(i=document.createElementNS(k,`svg`),i.setAttribute(`xmlns`,k),r.append(i));let a=N(i,t.map(({id:t,coords:[n,r]})=>({id:t,coords:e.toPixelCoords(n,r)})),n);if(a){let{xMin:t,xMax:n,yMin:r,yMax:o}=a,{centerCoords:[s,c],box:l}=e,u=C(n-t,3),d=C(o-r,3),f=C(.5*l.w+t-s,2),p=C(.5*l.h+r-c,2);i.setAttribute(`viewBox`,`0 0 ${u} ${d}`),i.setAttribute(`width`,u),i.setAttribute(`height`,d),i.setAttribute(`style`,`position: absolute; transform: translate3d(${f}px, ${p}px, 0);`)}return r}function M(e){return parseFloat(window.getComputedStyle(e).strokeWidth||e.getAttribute(`stroke-width`)||`1`)}function N(e,t,n){if(t.length===0){e.innerHTML=``;return}let r=e.querySelector(`path`);r||(r=document.createElementNS(k,`path`),e.append(r));let i=t[0].coords[0],a=i,o=t[0].coords[1],s=o,c=``;for(let{coords:[e,n]}of t)i>e&&(i=e),a<e&&(a=e),o>n&&(o=n),s<n&&(s=n);i-=10,a+=10,o-=10,s+=10;let l=Array.from(e.querySelectorAll(`.marker`)),u=0;for(let{id:a,coords:[s,d]}of t){let t=C(s-i,3),f=C(d-o,3);if(c+=`${c?` L`:`M`} ${t} ${f}`,n?.markers){let n=l[u++];n||(n=document.createElementNS(k,`circle`),n.setAttribute(`class`,`marker`),n.setAttribute(`r`,String(1.5*M(r))),e.append(n)),n.setAttribute(`cx`,t),n.setAttribute(`cy`,f),n.dataset.id=a}}for(let e=u;e<l.length;e++)l[e].remove();return r.setAttribute(`d`,c),{xMin:i,xMax:a,yMin:o,yMax:s}}function P(e,t,n){let r=t.map(e=>({id:b(),coords:e}));e.onRender(()=>{j(e,r,{className:`shape`,...n})})}function F(e,t){let n=[],r=null,i={className:`shape-editor`,markers:!0},a=()=>{j(e,n,i),t?.onUpdate?.(n)};y(e,({lat:e,lon:t,originalEvent:i})=>{let o=(i.target?.closest(`.marker`))?.dataset.id;if(o&&r){clearTimeout(r),r=null,n=n.filter(({id:e})=>e!==o),a();return}let s=()=>{n.push({id:b(),coords:[e,t]}),a(),r=null};o?r=setTimeout(s,250):s()},t?.ignoreClicks),e.onRender(a)}const{floor:I,ceil:L,random:R}=Math;function z(e,t,n){return`${t},${n},${e.zoom},${e.lang}`}function B(e,t,n,{size:r=256,url:i,subdomains:a,retries:o=0,error:s}){let c=new Image,l=0,u=(r,o)=>{if(!i)return``;if(typeof i==`function`)return i(e,t,n);let s=i.replaceAll(`{x}`,String(r)).replaceAll(`{y}`,String(o)).replaceAll(`{z}`,String(e.zoom)).replaceAll(`{lang}`,e.lang);return a&&s.includes(`{s}`)&&(s=s.replaceAll(`{s}`,a[I(a.length*R())])),s};return c.width=r,c.height=r,c.src=u(t,n),c.dataset.id=z(e,t,n),c.style=`position: absolute;`,c.onerror=()=>{l++;let{src:i}=c;if(!i||l>o){let t=S(e,s);t&&(c.onerror=()=>{},c.dataset.src=i,c.src=t);return}let a=t*r,d=n*r,f=e.toPixelCoords(...e.toGeoCoords(a,d))[0],p=I(f/r);if(t!==p)c.src=u(p,n);else{let e=new URL(i);e.searchParams.set(`_t`,String(Date.now())),c.src=e.href}},c}function V(e){return e.querySelectorAll(`img[data-id]`)}function H(e,t){return e.querySelector(`img[data-id="${t}"]`)}function U(e,t={}){let{id:n=b(),attribution:r,attributionInset:i=`auto 0 0 auto`}=t,a=x(e,{id:n,className:`tiles`,...t}),o=x(e,{id:n,className:`tiles-attribution`,inset:i}),s=()=>{let{box:{w:n,h:i},centerCoords:[s,c]}=e,{size:l=256,margin:u=0}=t,d=Array.isArray(u)?u[0]:u,f=Array.isArray(u)?u[1]:u,p=L((n+2*d)/l),m=L((i+2*f)/l),h=I(s/l),g=I(c/l),_=null,v=new Set,y=``;for(let r=0;r<=p;r++){let o=h+(r%2==0?-1:1)*I(r/2);for(let r=0;r<=m;r++){let u=g+(r%2==0?-1:1)*I(r/2);y=z(e,o,u),_=H(a,y),_||(_=B(e,o,u,t),a.append(_));let d=C(.5*n+o*l-s,2),f=C(.5*i+u*l-c,2);_.style.transform=`translate3d(${d}px, ${f}px, 0)`,v.add(y)}}for(let e of V(a)){let{id:t}=e.dataset;t&&!v.has(t)&&e.remove()}let b=S(e,r);o.toggleAttribute(`hidden`,!b),o.innerHTML!==b&&(o.innerHTML=b)},c=e.zoom,l=null;return e.onRender(()=>{l!==null&&(clearTimeout(l),l=null),e.zoom===c?(a.style.opacity=``,s()):(a.style.opacity=`0`,l=setTimeout(()=>{l=null,a.style.opacity=``,s()},300)),c=e.zoom}),a}function W(e,t={}){let{plus:n=`➕`,minus:r=`➖`,inset:i=`0 0 auto auto`}=t,a=x(e,{className:`zoom-controls`,inset:i}),o=document.createElement(`button`);o.dataset.id=`plus`,o.innerHTML=n;let s=document.createElement(`button`);s.dataset.id=`minus`,s.innerHTML=r;let c=()=>{o.toggleAttribute(`disabled`,e.zoom+1>e.maxZoom),s.toggleAttribute(`disabled`,e.zoom-1<e.minZoom)};return y(e,({originalEvent:t})=>{let n=t.target?.closest(`button`);n&&(t.stopPropagation(),e.zoom+=n.dataset.id===`minus`?-1:1,c())}),e.onRender(c),a.append(o,s),a}function G(e){if(e.length===0)return{};let t=e[0][0],n=t,r=e[0][1],i=r;for(let[a,o]of e)t>a&&(t=a),n<a&&(n=a),r>o&&(r=o),i<o&&(i=o);return{minLat:t,maxLat:n,minLon:r,maxLon:i}}function K(e){let{minLat:t,maxLat:n,minLon:r,maxLon:i}=G(e);return[t===void 0||n===void 0?0:(n+t)/2,r===void 0||i===void 0?0:(i+r)/2]}function q(e){return Array.isArray(e)&&e.length===2&&typeof e[0]==`number`&&typeof e[1]==`number`}const J=[.005,.018];function Y(e){return Array.isArray(e)?q(e)?{minLat:e[0],maxLat:e[0],minLon:e[1],maxLon:e[1]}:G(e):e}function X(e,[t,n]=J){let{minLat:r=0,maxLat:i=0,minLon:a=0,maxLon:o=0}=Y(e);return{minLat:r-t,maxLat:i+t,minLon:a-n,maxLon:o+n}}export{n as DEG,a as MAX_LAT,s as MAX_LON,i as MIN_LAT,o as MIN_LON,g as MapArea,t as RAD,y as addClickListener,w as addElement,E as addNavigation,D as addPersistence,O as addResizeObserver,P as addShape,F as addShapeEditor,U as addTiles,W as addZoomControls,r as eccentricityMap,K as getCenter,G as getGeoBounds,b as getId,x as getLayer,_ as getPointerPosition,X as getVicinity,q as isGeoCoords,S as resolveString,C as toPrecision};
1
+ const{PI:e}=Math,t=e/180,n=180/e,r={spherical:0,ellipsoidal:.0818191908426},i=-85.05,a=85.05,o=-180,s=180,{PI:c,sin:l,tan:u,atan:d,pow:f,exp:p,log:m,abs:h}=Math;var g=class{_p;_c;_cc;_r=new Set;constructor(e){this._p=e,this.container.style=`position: relative; overflow: hidden;`,this.container.dataset.type=`maparea`}render(){for(let e of this._r)e(this)}onRender(e,t=!1){return this._r.add(e),t||e(this),()=>{this._r.delete(e)}}getOptions(){return{...this._p,center:this.center,bounds:this.bounds}}setOptions(e){this._p={...this._p,...e},delete this._c,delete this._cc,this.render()}get container(){if(!this._c){let e=document.querySelector(this._p.container);if(!e)throw Error(`missing container element`);this._c=e}return this._c}get box(){let e=this.container.getBoundingClientRect();return{x:e.left,y:e.top,w:e.width,h:e.height}}get bounds(){let e=this._p.bounds;return e?{...e}:{}}set bounds(e){this._p.bounds=e}get center(){let e=this._p.center;return e?e.slice():[0,0]}set center(e){this._p.center=e,delete this._cc,this.render()}get centerCoords(){if(!this._cc){let[e,t]=this.center;this._cc=this.toPixelCoords(e,t)}return this._cc}get zoom(){return this._p.zoom??this._p.minZoom??0}set zoom(e){let{minZoom:t,maxZoom:n}=this,r=e;e<t&&(r=t),e>n&&(r=n),this._p.zoom=r,delete this._cc,this.render()}get minZoom(){return this._p.minZoom??-1/0}set minZoom(e){this._p.minZoom=e,this.zoom<this.minZoom&&(this.zoom=this.minZoom)}get maxZoom(){return this._p.maxZoom??1/0}set maxZoom(e){this._p.maxZoom=e,this.zoom>this.maxZoom&&(this.zoom=this.maxZoom)}get projection(){return this._p.projection??`spherical`}set projection(e){this._p.projection=e,this.render()}get lang(){return this._p.lang??``}set lang(e){this._p.lang=e,this.render()}inPixelBounds(e,t){let[n,r]=this.toGeoCoords(e,t);return this.inBounds(n,r)}inBounds(e,t){let{minLat:n=i,maxLat:r=a,minLon:s=o,maxLon:c=180}=this.bounds;return e>=n&&e<=r&&t>=s&&t<=c}canMoveTo(e,t){if(!this.inBounds(e,t))return!1;let{w:n,h:r}=this.box;if(n===0||r===0)return!1;let[i,a]=this.toPixelCoords(e,t);return this.inPixelBounds(i-n/2,a-r/2)&&this.inPixelBounds(i+n/2,a+r/2)}toPixelCoords(e,n){let i=r[this.projection],a=f(2,this.zoom+7)/c,o=e*t,s=i===0?1:f((1-i*l(o))/(1+i*l(o)),i/2);return[a*(c+n*t),a*(c-m(s*u(c/4+o/2)))]}toGeoCoords(e,t){let o=r[this.projection],s=f(2,this.zoom+7)/c,l=(e/s-c)*n,u;if(o===0)u=2*(d(p(c-t/s))-c/4)*n;else{u=i;let e=a-i,n=NaN,r=0;for(;(Number.isNaN(n)||h(n-t)>.1)&&r++<30;)e/=2,n=this.toPixelCoords(u+e,l)[1],n>t&&(u+=e)}return(l<-180||l>=180)&&(l=(l+180)%360-180),(u<-90||u>=90)&&(u=(u+90)%180-90),[u,l]}};function _(e){let t=`touches`in e?e.touches[0]:e;return t?[t.clientX,t.clientY]:null}function v(e,t){return t===void 0||!(e instanceof HTMLElement)?!1:typeof t==`function`&&t(e)||typeof t==`string`&&e.closest(t)!==null}function y(e,t,n){let r=Date.now(),i=null,a=e=>{r=Date.now(),i=_(e)},o=a=>{if(v(a.target,n)||!i||Date.now()-r>150)return;let{box:o,centerCoords:[s,c]}=e,l=i[0]-o.x,u=i[1]-o.y,[d,f]=e.toGeoCoords(l-.5*o.w+s,u-.5*o.h+c);t({x:l,y:u,lat:d,lon:f,originalEvent:a}),i=null};return e.container.addEventListener(`mousedown`,a),e.container.addEventListener(`mouseup`,o),e.container.addEventListener(`touchstart`,a),e.container.addEventListener(`touchend`,o),()=>{e.container.removeEventListener(`mousedown`,a),e.container.removeEventListener(`mouseup`,o),e.container.removeEventListener(`touchstart`,a),e.container.removeEventListener(`touchend`,o)}}function b(){return Math.random().toString(36).slice(2)}function x(e,{id:t,className:n,inset:r=`0`}={}){let i=`${n?`.${n}`:``}${t?`[data-id="${t}"]`:``}`,a=document.querySelector(i);return a||(a=document.createElement(`div`),a.className=`${n?`${n} `:``}layer`,a.dataset.id=t??b(),a.style=`position: absolute; inset: ${r};`,e.container.append(a)),a}function S(e,t){return t===void 0?t:t instanceof Function?t(e):t}function C(e,t){return e.toFixed(t).replace(/\.(\d*[^0])0+$/,`.$1`).replace(/\.0+$/,``)}function w(e,t,{className:n,coords:r,inset:i,layer:a,content:o}){let s=a??x(e,{className:`elements`});n&&t.setAttribute(`class`,n),t.style.position=`absolute`,s.append(t),e.onRender(()=>{if(i)t.style.inset=S(e,i)??``;else if(r){let{centerCoords:[n,i],box:{w:a,h:o}}=e,[s,c]=e.toPixelCoords(...r),l=C(s-n+a/2,2),u=C(c-i+o/2,2);t.style.transform=`translate3d(${l}px, ${u}px, 0)`}if(o){let n=S(e,o)??``;t.innerHTML!==n&&(t.innerHTML=n)}})}function T(e,{onStart:t,onMove:n,onEnd:r,wheel:i}={}){let a=null,o=null,s=Date.now(),c=!1,l=null,u=null;function d(t,r,i=100){u!==null&&(clearTimeout(u),u=null),l!==null&&(cancelAnimationFrame(l),l=null);let c=Date.now();c-s<i||(a!==null&&(a-=t),o!==null&&(o-=r),s=c,e.dataset.dragged||(e.dataset.dragged=`true`),l=requestAnimationFrame(()=>{l=null,(t!==0||r!==0)&&n?.(t,r)}))}function f(e,t,n){a!==null&&o!==null&&d(a-e,o-t,n)}function p(e,n){c=!0,t?.(),e!==void 0&&(a=e),n!==void 0&&(o=n),s=Date.now()}function m(t,n){c=!1,u=null,t!==void 0&&n!==void 0&&f(t,n),delete e.dataset.dragged,a=null,o=null,requestAnimationFrame(()=>{r?.()})}e.dataset.draggable=`true`;let h=null,g=null;e.addEventListener(`mousedown`,t=>{t.preventDefault(),!h&&(p(t.clientX,t.clientY),h=e=>{e.preventDefault(),f(e.clientX,e.clientY)},e.addEventListener(`mousemove`,h))}),e.addEventListener(`mouseup`,t=>{t.preventDefault(),h&&=(m(t.clientX,t.clientY),e.removeEventListener(`mousemove`,h),null)}),e.addEventListener(`touchstart`,t=>{t.preventDefault(),!g&&(p(t.touches[0]?.clientX,t.touches[0]?.clientY),g=e=>{e.preventDefault(),f(e.touches[0]?.clientX,e.touches[0]?.clientY)},e.addEventListener(`touchmove`,g))}),e.addEventListener(`touchend`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),e.addEventListener(`touchcancel`,t=>{t.preventDefault(),g&&=(m(t.touches[0]?.clientX,t.touches[0]?.clientY),e.removeEventListener(`touchmove`,g),null)}),i&&e.addEventListener(`wheel`,e=>{e.preventDefault(),c||p(),e.shiftKey?d(e.deltaY,e.deltaX,10):d(e.deltaX,e.deltaY,10),u=setTimeout(()=>{m()},200)})}function E(e,t){let n=0,r=0;T(e.container,{onStart(){[n,r]=e.centerCoords},onMove(t,i){let a=n+t,o=r+i,s=e.toGeoCoords(a,o);e.canMoveTo(...s)&&(e.center=s,n=a,r=o)},wheel:t?.wheel??!0})}function D(e,{storageKey:t,session:n=!1}={}){let r=n?window.sessionStorage:window.localStorage,i=t??[`maparea`,e.container.id].filter(Boolean).join(`#`),a=e.getOptions(),o=!1,s=()=>{try{r.setItem(i,JSON.stringify(e.getOptions()))}catch{}},c=()=>{try{let t=r.getItem(i);t===null?s():e.setOptions(JSON.parse(t))}catch{}},l=e=>{o=e===void 0?!o:e},u=()=>{e.setOptions(a)};c();let d=null;return e.onRender(()=>{o||(d&&=(clearTimeout(d),null),d=setTimeout(()=>{d=null,s()},350))}),{sync:c,write:s,toggle:l,reset:u}}function O(e,t){let n=new ResizeObserver(n=>{for(let r of n)if(r.contentBoxSize){if(t)if(r.contentBoxSize){let{inlineSize:e,blockSize:n}=r.contentBoxSize[0]??r.contentBoxSize;t({inlineSize:e,blockSize:n})}else{let{width:e,height:n}=r.contentRect;t({width:e,height:n})}e.render()}});return n.observe(e.container),()=>{n.unobserve(e.container)}}const k=`http://www.w3.org/2000/svg`,A={className:`shape`};function j(e,t,n){let r=x(e,n??A);r.toggleAttribute(`hidden`,t.length===0);let i=r.querySelector(`svg`);i||(i=document.createElementNS(k,`svg`),i.setAttribute(`xmlns`,k),r.append(i));let a=N(i,t.map(({id:t,coords:[n,r]})=>({id:t,coords:e.toPixelCoords(n,r)})),n);if(a){let{xMin:t,xMax:n,yMin:r,yMax:o}=a,{centerCoords:[s,c],box:l}=e,u=C(n-t,3),d=C(o-r,3),f=C(.5*l.w+t-s,2),p=C(.5*l.h+r-c,2);i.setAttribute(`viewBox`,`0 0 ${u} ${d}`),i.setAttribute(`width`,u),i.setAttribute(`height`,d),i.setAttribute(`style`,`position: absolute; transform: translate3d(${f}px, ${p}px, 0);`)}return r}function M(e){return parseFloat(window.getComputedStyle(e).strokeWidth||e.getAttribute(`stroke-width`)||`1`)}function N(e,t,n){if(t.length===0){e.innerHTML=``;return}let r=e.querySelector(`path`);r||(r=document.createElementNS(k,`path`),e.append(r));let i=t[0].coords[0],a=i,o=t[0].coords[1],s=o,c=``;for(let{coords:[e,n]}of t)i>e&&(i=e),a<e&&(a=e),o>n&&(o=n),s<n&&(s=n);i-=10,a+=10,o-=10,s+=10;let l=Array.from(e.querySelectorAll(`.marker`)),u=0;for(let{id:a,coords:[s,d]}of t){let t=C(s-i,3),f=C(d-o,3);if(c+=`${c?` L`:`M`} ${t} ${f}`,n?.markers){let n=l[u++];n||(n=document.createElementNS(k,`circle`),n.setAttribute(`class`,`marker`),n.setAttribute(`r`,String(1.5*M(r))),e.append(n)),n.setAttribute(`cx`,t),n.setAttribute(`cy`,f),n.dataset.id=a}}for(let e=u;e<l.length;e++)l[e].remove();return r.setAttribute(`d`,c),{xMin:i,xMax:a,yMin:o,yMax:s}}function P(e,t,n){let r=t.map(e=>({id:b(),coords:e}));e.onRender(()=>{j(e,r,{className:`shape`,...n})})}function F(e,t){let n=[],r=null,i={className:`shape-editor`,markers:!0},a=()=>{j(e,n,i),t?.onUpdate?.(n)};y(e,({lat:e,lon:t,originalEvent:i})=>{let o=(i.target?.closest(`.marker`))?.dataset.id;if(o&&r){clearTimeout(r),r=null,n=n.filter(({id:e})=>e!==o),a();return}let s=()=>{n.push({id:b(),coords:[e,t]}),a(),r=null};o?r=setTimeout(s,250):s()},t?.ignoreClicks),e.onRender(a)}const{floor:I,ceil:L,random:R}=Math;function z(e,t,n){return`${t},${n},${e.zoom},${e.lang}`}function B(e,t,n,{size:r,url:i,subdomains:a,error:o}){let s=new Image,c=S(e,r)??256;return s.width=c,s.height=c,s.src=((r,o)=>{if(!i)return``;if(typeof i==`function`)return i(e,t,n);let s=i.replaceAll(`{x}`,String(r)).replaceAll(`{y}`,String(o)).replaceAll(`{z}`,String(e.zoom)).replaceAll(`{lang}`,e.lang);return a&&s.includes(`{s}`)&&(s=s.replaceAll(`{s}`,a[I(a.length*R())])),s})(t,n),s.dataset.id=z(e,t,n),s.style=`position: absolute;`,s.addEventListener(`error`,t=>{let n=t.target;if(n instanceof HTMLImageElement){let t=S(e,o);t&&(n.dataset.src=s.src,n.src=t)}}),s}function V(e){return e.querySelectorAll(`img[data-id]`)}function H(e,t){return e.querySelector(`img[data-id="${t}"]`)}function U(e,t={}){let{id:n=b(),attribution:r,attributionInset:i=`auto 0 0 auto`}=t,a=x(e,{id:n,className:`tiles`,...t}),o=x(e,{id:n,className:`tiles-attribution`,inset:i}),s=()=>{let{box:{w:n,h:i},centerCoords:[s,c]}=e,{size:l,margin:u=0}=t,d=S(e,l)??256,f=Array.isArray(u)?u[0]:u,p=Array.isArray(u)?u[1]:u,m=L((n+2*f)/d),h=L((i+2*p)/d),g=I(s/d),_=I(c/d),v=null,y=new Set,b=``;for(let r=0;r<=m;r++){let o=g+(r%2==0?-1:1)*I(r/2);for(let r=0;r<=h;r++){let l=_+(r%2==0?-1:1)*I(r/2);b=z(e,o,l),v=H(a,b),v||(v=B(e,o,l,t),a.append(v));let u=C(.5*n+o*d-s,2),f=C(.5*i+l*d-c,2);v.style.transform=`translate3d(${u}px, ${f}px, 0)`,y.add(b)}}for(let e of V(a)){let{id:t}=e.dataset;t&&!y.has(t)&&e.remove()}let x=S(e,r)??``;o.toggleAttribute(`hidden`,!x),o.innerHTML!==x&&(o.innerHTML=x)},c=e.zoom,l=null;return e.onRender(()=>{l!==null&&(clearTimeout(l),l=null),e.zoom===c?(a.style.opacity=``,s()):(a.style.opacity=`0`,l=setTimeout(()=>{l=null,a.style.opacity=``,s()},300)),c=e.zoom}),a}function W(e,t={}){let{plus:n=`➕`,minus:r=`➖`,inset:i=`0 0 auto auto`}=t,a=x(e,{className:`zoom-controls`,inset:i}),o=document.createElement(`button`);o.dataset.id=`plus`,o.innerHTML=n;let s=document.createElement(`button`);s.dataset.id=`minus`,s.innerHTML=r;let c=()=>{o.toggleAttribute(`disabled`,e.zoom+1>e.maxZoom),s.toggleAttribute(`disabled`,e.zoom-1<e.minZoom)};return y(e,({originalEvent:t})=>{let n=t.target?.closest(`button`);n&&(t.stopPropagation(),e.zoom+=n.dataset.id===`minus`?-1:1,c())}),e.onRender(c),a.append(o,s),a}const{abs:G,log2:K,min:q,floor:J}=Math;function Y(e,t){let{box:{w:n,h:r},center:[i,a],zoom:o}=e,{minLat:s,maxLat:c,minLon:l,maxLon:u}=t,d=0,f=0;if(l!==void 0&&u!==void 0){let t=G(e.toPixelCoords(i,u)[0]-e.toPixelCoords(i,l)[0]);t!==0&&(d=K(n/t))}if(s!==void 0&&c!==void 0){let t=G(e.toPixelCoords(s,a)[1]-e.toPixelCoords(c,a)[1]);t!==0&&(f=K(r/t))}let p=J(q(o+d,o+f));p!==o&&(e.zoom=p)}function X(e){if(e.length===0)return{};let t=e[0][0],n=t,r=e[0][1],i=r;for(let[a,o]of e)t>a&&(t=a),n<a&&(n=a),r>o&&(r=o),i<o&&(i=o);return{minLat:t,maxLat:n,minLon:r,maxLon:i}}function Z(e){let{minLat:t,maxLat:n,minLon:r,maxLon:i}=X(e);return[t===void 0||n===void 0?0:(n+t)/2,r===void 0||i===void 0?0:(i+r)/2]}function Q(e){return Array.isArray(e)&&e.length===2&&typeof e[0]==`number`&&typeof e[1]==`number`}function $(e){return Q(e)?{minLat:e[0],maxLat:e[0],minLon:e[1],maxLon:e[1]}:Array.isArray(e)?X(e):e}const ee=[.005,.018];function te(e,t=ee){let{minLat:n=0,maxLat:r=0,minLon:i=0,maxLon:a=0}=$(e),[o,s]=t;return{minLat:n-o,maxLat:r+o,minLon:i-s,maxLon:a+s}}export{n as DEG,a as MAX_LAT,s as MAX_LON,i as MIN_LAT,o as MIN_LON,g as MapArea,t as RAD,y as addClickListener,w as addElement,E as addMovableViewport,D as addPersistence,O as addResizeObserver,P as addShape,F as addShapeEditor,U as addTiles,W as addZoomControls,r as eccentricityMap,Y as fitGeoBounds,Z as getCenter,X as getGeoBounds,b as getId,x as getLayer,_ as getPointerPosition,te as getVicinity,Q as isCoordsArray,S as resolveDynamic,$ as toGeoBounds,C as toPrecision};
package/index.ts CHANGED
@@ -2,7 +2,7 @@ export * from "./src/MapArea/const.ts";
2
2
  export * from "./src/MapArea/index.ts";
3
3
  export * from "./src/plugins/addClickListener.ts";
4
4
  export * from "./src/plugins/addElement.ts";
5
- export * from "./src/plugins/addNavigation.ts";
5
+ export * from "./src/plugins/addMovableViewport.ts";
6
6
  export * from "./src/plugins/addPersistence.ts";
7
7
  export * from "./src/plugins/addResizeObserver.ts";
8
8
  export * from "./src/plugins/addShape.ts";
@@ -10,7 +10,7 @@ export * from "./src/plugins/addShapeEditor.ts";
10
10
  export * from "./src/plugins/addTiles.ts";
11
11
  export * from "./src/plugins/addZoomControls.ts";
12
12
  export * from "./src/types/BoxDimensions.ts";
13
- export * from "./src/types/DynamicString.ts";
13
+ export * from "./src/types/Dynamic.ts";
14
14
  export * from "./src/types/GeoBounds.ts";
15
15
  export * from "./src/types/GeoCoords.ts";
16
16
  export * from "./src/types/GeoVertex.ts";
@@ -20,12 +20,14 @@ export * from "./src/types/PixelCoords.ts";
20
20
  export * from "./src/types/PixelVertex.ts";
21
21
  export * from "./src/types/Projection.ts";
22
22
  export * from "./src/types/ShapeLayerOptions.ts";
23
+ export * from "./src/utils/fitGeoBounds.ts";
23
24
  export * from "./src/utils/getCenter.ts";
24
25
  export * from "./src/utils/getGeoBounds.ts";
25
26
  export * from "./src/utils/getId.ts";
26
27
  export * from "./src/utils/getLayer.ts";
27
28
  export * from "./src/utils/getPointerPosition.ts";
28
29
  export * from "./src/utils/getVicinity.ts";
29
- export * from "./src/utils/isGeoCoords.ts";
30
- export * from "./src/utils/resolveString.ts";
30
+ export * from "./src/utils/isCoordsArray.ts";
31
+ export * from "./src/utils/resolveDynamic.ts";
32
+ export * from "./src/utils/toGeoBounds.ts";
31
33
  export * from "./src/utils/toPrecision.ts";
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
- {
2
- "name": "maparea",
3
- "version": "0.1.9",
4
- "type": "module",
5
- "main": "./dist/index.cjs",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
8
- "scripts": {
9
- "preversion": "npm run shape",
10
- "shape": "npx codeshape --minify",
11
- "start": "npx @t8/serve test --spa -b --watch"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "git://github.com/axtk/maparea.git"
16
- },
17
- "author": "axtk",
18
- "license": "MIT"
19
- }
1
+ {
2
+ "name": "maparea",
3
+ "version": "0.1.11",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "preversion": "npm run shape",
10
+ "shape": "npx codeshape --minify",
11
+ "start": "npx @t8/serve test --spa -b --watch"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git://github.com/axtk/maparea.git"
16
+ },
17
+ "author": "axtk",
18
+ "license": "MIT"
19
+ }