@mappedin/blue-dot 6.15.0-beta.0 → 6.17.0-beta.0
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/README.md +21 -0
- package/lib/esm/chunk-BRRC7V4T.js +1 -0
- package/lib/esm/chunk-UVQMTLHL.js +1 -0
- package/lib/esm/debug/index.d.ts +3039 -0
- package/lib/esm/debug/index.js +1 -0
- package/lib/esm/index.d.ts +411 -23
- package/lib/esm/index.js +1 -1
- package/lib/esm/react/index.d.ts +411 -23
- package/lib/esm/react/index.js +1 -1
- package/lib/rn/blue-dot.d.ts +16 -0
- package/lib/rn/index-rn.js +2 -2
- package/lib/rn/rn/use-blue-dot.d.ts +1 -1
- package/package.json +13 -5
- package/lib/esm/chunk-O22D2X2S.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as S,c as d,g as L,h as e,i as h,j as u,k as s,m as D,n as w}from"../chunk-UVQMTLHL.js";D();D();D();function Ke(l){var r,m;let t={};for(let[p,c]of l.Sensors.getAll())t[p]={enabled:c.isEnabled};let n={timestamp:Date.now(),state:l.getState(),position:l.coordinate?{lat:l.coordinate.latitude,lon:l.coordinate.longitude,floor:(r=l.floor)==null?void 0:r.name}:null,accuracy:l.accuracy,heading:l.heading,sensors:t,anchor:l.anchor,displacement:l.displacement},i=new Blob([JSON.stringify(n,null,2)],{type:"application/json"}),a=new File([i],"bluedot-debug-".concat(Date.now(),".json"),{type:"application/json"});(m=navigator.canShare)!=null&&m.call(navigator,{files:[a]})?navigator.share({files:[a]}).catch(()=>{Je(i,a.name)}):Je(i,a.name)}d(Ke,"exportDebugData");function Je(l,t){let n=URL.createObjectURL(l),i=document.createElement("a");i.href=n,i.download=t,i.click(),URL.revokeObjectURL(n)}d(Je,"downloadFile");D();var V={heading:{headingResponsiveness:40,compassNoiseTolerance:30,headingSnapThreshold:10,magneticDisturbanceGating:!0,headingChangeThreshold:2},motion:{stepSensitivity:50,averageStepLength:.7,strideVariability:0,motionResponsiveness:50,pdrEnabled:!0}};function $e(l){return{complementaryAlpha:.99-l.headingResponsiveness/100*.79,gyroNoiseThreshold:.1+l.compassNoiseTolerance/100*4.9,maxHeadingError:l.headingSnapThreshold,magneticGatingEnabled:l.magneticDisturbanceGating,deltaThreshold:l.headingChangeThreshold}}d($e,"headingConfigToFilterParams");function Ae(l){return{stepDetectionThreshold:2-l.stepSensitivity/100*1.5,stepLength:l.averageStepLength,strideAdaptation:l.strideVariability/100*.3,motionThreshold:1-l.motionResponsiveness/100*.8,pdrEnabled:l.pdrEnabled}}d(Ae,"motionConfigToSensorParams");function I(l,t,n){return Math.min(Math.max(l,t),n)}d(I,"clamp");function rt(l){var n,i,a,r,m,p,c,b,_,y;let t=S({},V);return l.heading&&(t.heading={headingResponsiveness:I((n=l.heading.headingResponsiveness)!=null?n:30,0,100),compassNoiseTolerance:I((i=l.heading.compassNoiseTolerance)!=null?i:50,0,100),headingSnapThreshold:I((a=l.heading.headingSnapThreshold)!=null?a:30,10,90),magneticDisturbanceGating:(r=l.heading.magneticDisturbanceGating)!=null?r:!0,headingChangeThreshold:I((m=l.heading.headingChangeThreshold)!=null?m:2,1,10)}),l.motion&&(t.motion={stepSensitivity:I((p=l.motion.stepSensitivity)!=null?p:50,0,100),averageStepLength:I((c=l.motion.averageStepLength)!=null?c:.7,.4,1.2),strideVariability:I((b=l.motion.strideVariability)!=null?b:0,0,100),motionResponsiveness:I((_=l.motion.motionResponsiveness)!=null?_:50,0,100),pdrEnabled:(y=l.motion.pdrEnabled)!=null?y:!0}),t}d(rt,"normalizeTuningConfig");var Qe=".bluedot-hud {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 10000;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n pointer-events: none;\n}\n\n.bluedot-hud--expanded {\n top: 0;\n display: flex;\n flex-direction: column;\n}\n\n.bluedot-hud * {\n box-sizing: border-box;\n}\n\n/* Collapsed bar */\n.bluedot-hud__collapsed {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n background: rgba(0, 0, 0, 0.85);\n color: #fff;\n pointer-events: auto;\n cursor: pointer;\n min-height: 36px;\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n}\n\n.bluedot-hud__status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.bluedot-hud__status-dot--active {\n background: #4ade80;\n box-shadow: 0 0 4px #4ade80;\n}\n\n.bluedot-hud__status-dot--inactive {\n background: #9ca3af;\n}\n\n.bluedot-hud__status-dot--error {\n background: #f87171;\n box-shadow: 0 0 4px #f87171;\n}\n\n.bluedot-hud__status-text {\n font-weight: 600;\n font-size: 12px;\n}\n\n.bluedot-hud__coords {\n color: #94a3b8;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 10px;\n flex: 1;\n}\n\n.bluedot-hud__heading {\n color: #60a5fa;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 11px;\n font-weight: 600;\n}\n\n/* Expanded panel */\n.bluedot-hud__expanded {\n display: none;\n flex-direction: column;\n background: rgba(0, 0, 0, 0.92);\n color: #fff;\n pointer-events: auto;\n flex: 1;\n overflow: hidden;\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n.bluedot-hud__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n cursor: pointer;\n min-height: 40px;\n}\n\n.bluedot-hud__title {\n font-weight: 600;\n font-size: 14px;\n}\n\n.bluedot-hud__header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.bluedot-hud__export-btn {\n background: #3b82f6;\n color: #fff;\n border: none;\n border-radius: 4px;\n padding: 6px 12px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n}\n\n.bluedot-hud__export-btn:active {\n background: #2563eb;\n}\n\n.bluedot-hud__collapse-icon {\n font-size: 12px;\n color: #94a3b8;\n}\n\n.bluedot-hud__content {\n padding: 4px 0;\n flex: 1;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.bluedot-hud__section {\n padding: 6px 12px;\n}\n\n.bluedot-hud__section:not(:last-child) {\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.bluedot-hud__section-title {\n font-weight: 600;\n font-size: 10px;\n color: #64748b;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n}\n\n.bluedot-hud__row {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 1px 0;\n margin-right: 12px;\n}\n\n.bluedot-hud__label {\n color: #94a3b8;\n font-size: 11px;\n}\n\n.bluedot-hud__value {\n color: #fff;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 11px;\n word-break: break-all;\n}\n\n.bluedot-hud__value--enabled {\n color: #4ade80;\n}\n\n.bluedot-hud__value--disabled {\n color: #6b7280;\n}\n\n.bluedot-hud__value--warning {\n color: #fbbf24;\n}\n\n.bluedot-hud__sensors {\n display: flex;\n flex-wrap: wrap;\n}\n\n/* Heading section with compass */\n.bluedot-hud__heading-content {\n display: flex;\n gap: 12px;\n align-items: flex-start;\n}\n\n/* Compass */\n.bluedot-hud__compass {\n position: relative;\n width: 56px;\n height: 56px;\n flex-shrink: 0;\n}\n\n.bluedot-hud__compass-ring {\n position: absolute;\n inset: 0;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-radius: 50%;\n}\n\n.bluedot-hud__compass-dir {\n position: absolute;\n font-size: 8px;\n font-weight: 600;\n color: #94a3b8;\n}\n\n.bluedot-hud__compass-dir--n {\n top: 2px;\n left: 50%;\n transform: translateX(-50%);\n color: #f87171;\n}\n\n.bluedot-hud__compass-dir--e {\n right: 2px;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.bluedot-hud__compass-dir--s {\n bottom: 2px;\n left: 50%;\n transform: translateX(-50%);\n}\n\n.bluedot-hud__compass-dir--w {\n left: 2px;\n top: 50%;\n transform: translateY(-50%);\n}\n\n.bluedot-hud__compass-needle {\n position: absolute;\n left: 50%;\n top: 50%;\n width: 3px;\n height: 20px;\n background: linear-gradient(to top, #3b82f6 0%, #60a5fa 100%);\n border-radius: 2px;\n transform-origin: bottom center;\n transform: translate(-50%, -100%) rotate(0deg);\n transition: transform 0.15s ease-out;\n}\n\n.bluedot-hud__compass-needle::before {\n content: '';\n position: absolute;\n top: -4px;\n left: 50%;\n transform: translateX(-50%);\n width: 0;\n height: 0;\n border-left: 4px solid transparent;\n border-right: 4px solid transparent;\n border-bottom: 6px solid #60a5fa;\n}\n\n.bluedot-hud__compass-center {\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 6px;\n height: 6px;\n background: #fff;\n border-radius: 50%;\n border: 1px solid #3b82f6;\n}\n\n/* Heading comparison list */\n.bluedot-hud__headings {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.bluedot-hud__heading-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 2px 6px;\n background: rgba(255, 255, 255, 0.05);\n border-radius: 3px;\n font-size: 10px;\n}\n\n.bluedot-hud__heading-row--displayed {\n background: rgba(59, 130, 246, 0.2);\n border: 1px solid rgba(59, 130, 246, 0.3);\n}\n\n.bluedot-hud__heading-label {\n color: #94a3b8;\n font-size: 10px;\n}\n\n.bluedot-hud__heading-value {\n color: #fff;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 10px;\n}\n\n.bluedot-hud__heading-diff {\n color: #94a3b8;\n margin-left: 3px;\n font-size: 9px;\n}\n\n.bluedot-hud__heading-diff--warning {\n color: #fbbf24;\n}\n\n/* State modifiers */\n.bluedot-hud--collapsed .bluedot-hud__collapsed {\n display: flex;\n}\n\n.bluedot-hud--collapsed .bluedot-hud__expanded {\n display: none;\n}\n\n.bluedot-hud--expanded .bluedot-hud__collapsed {\n display: none;\n}\n\n.bluedot-hud--expanded .bluedot-hud__expanded {\n display: flex;\n}\n\n/* Tuning section */\n.bluedot-hud__tuning {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.bluedot-hud__tuning-group {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n padding: 8px;\n}\n\n.bluedot-hud__tuning-group-title {\n color: #94a3b8;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n}\n\n.bluedot-hud__tuning-row {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-bottom: 10px;\n}\n\n.bluedot-hud__tuning-row--toggle {\n flex-direction: row;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n}\n\n.bluedot-hud__tuning-label-col {\n flex: 1;\n}\n\n.bluedot-hud__tuning-label {\n color: #e2e8f0;\n font-size: 12px;\n}\n\n.bluedot-hud__tuning-desc {\n color: #64748b;\n font-size: 10px;\n line-height: 1.3;\n margin-top: 1px;\n}\n\n.bluedot-hud__tuning-control {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.bluedot-hud__slider {\n flex: 1;\n height: 4px;\n background: #334155;\n border-radius: 2px;\n outline: none;\n -webkit-appearance: none;\n appearance: none;\n}\n\n.bluedot-hud__slider::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 14px;\n height: 14px;\n background: #3b82f6;\n border-radius: 50%;\n cursor: pointer;\n}\n\n.bluedot-hud__slider::-moz-range-thumb {\n width: 14px;\n height: 14px;\n background: #3b82f6;\n border-radius: 50%;\n cursor: pointer;\n border: none;\n}\n\n.bluedot-hud__slider-value {\n color: #94a3b8;\n font-size: 11px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n min-width: 40px;\n text-align: right;\n}\n\n.bluedot-hud__toggle {\n width: 36px;\n height: 20px;\n background: #334155;\n border-radius: 10px;\n position: relative;\n -webkit-appearance: none;\n appearance: none;\n outline: none;\n cursor: pointer;\n transition: background 0.2s;\n}\n\n.bluedot-hud__toggle:checked {\n background: #3b82f6;\n}\n\n.bluedot-hud__toggle::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n background: #fff;\n border-radius: 50%;\n transition: transform 0.2s;\n}\n\n.bluedot-hud__toggle:checked::before {\n transform: translateX(16px);\n}\n\n.bluedot-hud__reset-btn {\n background: #334155;\n color: #e2e8f0;\n border: none;\n border-radius: 4px;\n padding: 8px 12px;\n font-size: 12px;\n cursor: pointer;\n transition: background 0.2s;\n margin-top: 8px;\n}\n\n.bluedot-hud__reset-btn:hover {\n background: #475569;\n}\n\n/* Console section */\n.bluedot-hud__console-header {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 6px;\n}\n\n.bluedot-hud__console-clear {\n background: #334155;\n color: #94a3b8;\n border: none;\n border-radius: 3px;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n}\n\n.bluedot-hud__console-clear:active {\n background: #475569;\n}\n\n.bluedot-hud__console {\n background: rgba(0, 0, 0, 0.4);\n border-radius: 4px;\n padding: 6px;\n max-height: 200px;\n overflow-y: auto;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 10px;\n line-height: 1.4;\n -webkit-overflow-scrolling: touch;\n}\n\n.bluedot-hud__console-line {\n padding: 2px 0;\n word-break: break-word;\n color: #d1d5db;\n}\n\n.bluedot-hud__console-line--warn {\n color: #fbbf24;\n}\n\n.bluedot-hud__console-line--error {\n color: #f87171;\n}\n\n.bluedot-hud__console-time {\n color: #6b7280;\n margin-right: 6px;\n}\n";var Ze="bluedot-debug-hud-css",ht="bluedot-debug-hud",ct=200;function pt(l,t){let n=document.getElementById(t);if(n instanceof HTMLStyleElement){n.textContent=l;return}n=document.createElement("style"),n.id=t,n.textContent=l,document.head.appendChild(n)}d(pt,"injectCSS");function mt(l){let t=Math.floor((Date.now()-l)/1e3);if(t<60)return"".concat(t,"s ago");let n=Math.floor(t/60);return n<60?"".concat(n,"m ago"):"".concat(Math.floor(n/60),"h ago")}d(mt,"formatTimeAgo");function gt(l,t){let n=Math.max(0,Math.floor((l+t-Date.now())/1e3));return n<=0?"expired":n<60?"".concat(n,"s"):"".concat(Math.floor(n/60),"m ").concat(n%60,"s")}d(gt,"formatTimeRemaining");var f,C,T,R,me,ge,g,$,X,P,Y,Z,ee,be,fe,_e,xe,U,W,A,te,ne,oe,ie,G,N,E,B,M,o,et,tt,Ee,Re,nt,ot,z,he,ce,F,we,O,Ue,H,it,Ie,st,at,ze,Pe,Ge,Se,dt,pe,Le,Be=class Be{constructor(t){h(this,o);h(this,f);h(this,C);h(this,T,!0);h(this,R,[]);h(this,me,new Map);h(this,ge,new Map);h(this,g,{heading:S({},V.heading),motion:S({},V.motion)});h(this,$);h(this,X);h(this,P);h(this,Y);h(this,Z);h(this,ee);h(this,be);h(this,fe);h(this,_e);h(this,xe);h(this,U);h(this,W);h(this,A);h(this,te);h(this,ne);h(this,oe);h(this,ie);h(this,G);h(this,N);h(this,E);h(this,B,[]);h(this,M,null);if(u(this,f,t),pt(Qe,Ze),u(this,C,s(this,o,ot).call(this)),!document.body)throw new Error("DebugHUD: document.body is not available. Ensure the DOM is ready before creating the HUD.");document.body.appendChild(e(this,C)),s(this,o,et).call(this),s(this,o,st).call(this),s(this,o,at).call(this)}clearConsole(){u(this,B,[]),s(this,o,Re).call(this)}getTuningConfig(){return S({},e(this,g))}setTuningConfig(t){t.heading&&(e(this,g).heading=S(S({},e(this,g).heading),t.heading)),t.motion&&(e(this,g).motion=S(S({},e(this,g).motion),t.motion)),s(this,o,H).call(this),e(this,N).innerHTML="",s(this,o,we).call(this,e(this,N))}show(){e(this,C).style.display=""}hide(){e(this,C).style.display="none"}get isExpanded(){return!e(this,T)}expand(){e(this,T)&&(u(this,T,!1),e(this,C).classList.remove("bluedot-hud--collapsed"),e(this,C).classList.add("bluedot-hud--expanded"))}collapse(){e(this,T)||(u(this,T,!0),e(this,C).classList.add("bluedot-hud--collapsed"),e(this,C).classList.remove("bluedot-hud--expanded"))}toggleExpanded(){return e(this,T)?this.expand():this.collapse(),!e(this,T)}destroy(){s(this,o,tt).call(this);for(let n of e(this,R))n();u(this,R,[]),e(this,C).remove();let t=document.getElementById(Ze);t&&t.remove()}};f=new WeakMap,C=new WeakMap,T=new WeakMap,R=new WeakMap,me=new WeakMap,ge=new WeakMap,g=new WeakMap,$=new WeakMap,X=new WeakMap,P=new WeakMap,Y=new WeakMap,Z=new WeakMap,ee=new WeakMap,be=new WeakMap,fe=new WeakMap,_e=new WeakMap,xe=new WeakMap,U=new WeakMap,W=new WeakMap,A=new WeakMap,te=new WeakMap,ne=new WeakMap,oe=new WeakMap,ie=new WeakMap,G=new WeakMap,N=new WeakMap,E=new WeakMap,B=new WeakMap,M=new WeakMap,o=new WeakSet,et=d(function(){u(this,M,{log:w.log.bind(w),warn:w.warn.bind(w),error:w.error.bind(w)}),w.log=(...t)=>{e(this,M).log(...t),s(this,o,Ee).call(this,"log",t.map(String).join(" "))},w.warn=(...t)=>{e(this,M).warn(...t),s(this,o,Ee).call(this,"warn",t.map(String).join(" "))},w.error=(...t)=>{e(this,M).error(...t),s(this,o,Ee).call(this,"error",t.map(String).join(" "))}},"#interceptLogger"),tt=d(function(){e(this,M)&&(w.log=e(this,M).log,w.warn=e(this,M).warn,w.error=e(this,M).error,u(this,M,null))},"#restoreLogger"),Ee=d(function(t,n){let i={time:Date.now(),level:t,message:n};e(this,B).push(i),e(this,B).length>ct&&e(this,B).shift(),s(this,o,Re).call(this)},"#addLogEntry"),Re=d(function(){if(!e(this,E))return;let t=e(this,E).scrollHeight-e(this,E).scrollTop<=e(this,E).clientHeight+5;e(this,E).innerHTML="";for(let n of e(this,B)){let i=document.createElement("div");i.className="bluedot-hud__console-line bluedot-hud__console-line--".concat(n.level);let a=new Date(n.time),r="".concat(a.getHours().toString().padStart(2,"0"),":").concat(a.getMinutes().toString().padStart(2,"0"),":").concat(a.getSeconds().toString().padStart(2,"0"),".").concat(a.getMilliseconds().toString().padStart(3,"0"));i.innerHTML='<span class="bluedot-hud__console-time">'.concat(r,"</span> ").concat(s(this,o,nt).call(this,n.message)),e(this,E).appendChild(i)}t&&(e(this,E).scrollTop=e(this,E).scrollHeight)},"#updateConsole"),nt=d(function(t){let n=document.createElement("div");return n.textContent=t,n.innerHTML},"#escapeHtml"),ot=d(function(){let t=document.createElement("div");t.id=ht,t.className="bluedot-hud bluedot-hud--collapsed";let n=document.createElement("div");n.className="bluedot-hud__collapsed",n.addEventListener("click",()=>s(this,o,Ie).call(this)),u(this,$,document.createElement("span")),e(this,$).className="bluedot-hud__status-dot",u(this,X,document.createElement("span")),e(this,X).className="bluedot-hud__status-text",u(this,P,document.createElement("span")),e(this,P).className="bluedot-hud__coords",u(this,Y,document.createElement("span")),e(this,Y).className="bluedot-hud__heading",n.appendChild(e(this,$)),n.appendChild(e(this,X)),n.appendChild(e(this,P)),n.appendChild(e(this,Y));let i=document.createElement("div");i.className="bluedot-hud__expanded";let a=document.createElement("div");a.className="bluedot-hud__header",a.addEventListener("click",()=>s(this,o,Ie).call(this));let r=document.createElement("span");r.className="bluedot-hud__title",r.textContent="BlueDot Debug";let m=document.createElement("div");m.className="bluedot-hud__header-right";let p=document.createElement("button");p.className="bluedot-hud__export-btn",p.textContent="Export",p.addEventListener("click",Ce=>{Ce.stopPropagation(),Ke(e(this,f))});let c=document.createElement("span");c.className="bluedot-hud__collapse-icon",c.textContent="\u25BC",m.appendChild(p),m.appendChild(c),a.appendChild(r),a.appendChild(m);let b=document.createElement("div");b.className="bluedot-hud__content";let _=s(this,o,z).call(this,"Status"),y=document.createElement("div");y.className="bluedot-hud__row",u(this,Z,s(this,o,ce).call(this,"--")),u(this,ee,s(this,o,ce).call(this,"no")),y.appendChild(s(this,o,he).call(this,"Status:")),y.appendChild(e(this,Z)),y.appendChild(s(this,o,he).call(this,"Following:")),y.appendChild(e(this,ee)),_.appendChild(y);let x=s(this,o,z).call(this,"Position");u(this,be,s(this,o,F).call(this,x,"Lat")),u(this,fe,s(this,o,F).call(this,x,"Lon")),u(this,_e,s(this,o,F).call(this,x,"Accuracy")),u(this,xe,s(this,o,F).call(this,x,"Floor"));let re=s(this,o,z).call(this,"Heading"),ve=document.createElement("div");ve.className="bluedot-hud__heading-content";let ue=document.createElement("div");ue.className="bluedot-hud__compass";let Ne=document.createElement("div");Ne.className="bluedot-hud__compass-ring",u(this,W,document.createElement("div")),e(this,W).className="bluedot-hud__compass-needle";let Ye=document.createElement("div");Ye.className="bluedot-hud__compass-center";let lt=["N","E","S","W"];for(let Ce of lt){let Fe=document.createElement("span");Fe.className="bluedot-hud__compass-dir bluedot-hud__compass-dir--".concat(Ce.toLowerCase()),Fe.textContent=Ce,Ne.appendChild(Fe)}ue.appendChild(Ne),ue.appendChild(e(this,W)),ue.appendChild(Ye),u(this,U,document.createElement("div")),e(this,U).className="bluedot-hud__headings",ve.appendChild(ue),ve.appendChild(e(this,U)),re.appendChild(ve);let Q=s(this,o,z).call(this,"Anchor");u(this,A,s(this,o,F).call(this,Q,"Status")),u(this,te,s(this,o,F).call(this,Q,"Position")),u(this,ne,s(this,o,F).call(this,Q,"Set")),u(this,oe,s(this,o,F).call(this,Q,"TTL")),u(this,ie,s(this,o,F).call(this,Q,"Drift"));let We=s(this,o,z).call(this,"Sensors");u(this,G,document.createElement("div")),e(this,G).className="bluedot-hud__sensors",We.appendChild(e(this,G));let qe=s(this,o,z).call(this,"Tuning");u(this,N,document.createElement("div")),e(this,N).className="bluedot-hud__tuning",s(this,o,we).call(this,e(this,N)),qe.appendChild(e(this,N));let ke=s(this,o,z).call(this,"Console"),De=document.createElement("div");De.className="bluedot-hud__console-header";let ye=document.createElement("button");return ye.className="bluedot-hud__console-clear",ye.textContent="Clear",ye.addEventListener("click",()=>this.clearConsole()),De.appendChild(ye),ke.appendChild(De),u(this,E,document.createElement("div")),e(this,E).className="bluedot-hud__console",ke.appendChild(e(this,E)),b.appendChild(_),b.appendChild(x),b.appendChild(re),b.appendChild(Q),b.appendChild(We),b.appendChild(qe),b.appendChild(ke),i.appendChild(a),i.appendChild(b),t.appendChild(n),t.appendChild(i),t},"#createDOM"),z=d(function(t){let n=document.createElement("div");n.className="bluedot-hud__section";let i=document.createElement("div");return i.className="bluedot-hud__section-title",i.textContent=t,n.appendChild(i),n},"#createSection"),he=d(function(t){let n=document.createElement("span");return n.className="bluedot-hud__label",n.textContent=t,n},"#createLabel"),ce=d(function(t){let n=document.createElement("span");return n.className="bluedot-hud__value",n.textContent=t,n},"#createValue"),F=d(function(t,n){let i=document.createElement("div");i.className="bluedot-hud__row",i.appendChild(s(this,o,he).call(this,"".concat(n,":")));let a=s(this,o,ce).call(this,"--");return i.appendChild(a),t.appendChild(i),a},"#appendRow"),we=d(function(t){let n=document.createElement("div");n.className="bluedot-hud__tuning-group",n.innerHTML='<div class="bluedot-hud__tuning-group-title">Heading</div>',s(this,o,O).call(this,n,{id:"heading-responsiveness",label:"Heading responsiveness",description:"Higher = compass corrects heading faster (may jump)",min:0,max:100,value:e(this,g).heading.headingResponsiveness,onChange:d(r=>{e(this,g).heading.headingResponsiveness=r,s(this,o,H).call(this)},"onChange")}),s(this,o,O).call(this,n,{id:"compass-noise",label:"Rotation filtering",description:"Higher = ignore small turns, steadier heading",min:0,max:100,value:e(this,g).heading.compassNoiseTolerance,onChange:d(r=>{e(this,g).heading.compassNoiseTolerance=r,s(this,o,H).call(this)},"onChange")}),s(this,o,O).call(this,n,{id:"snap-threshold",label:"Heading snap threshold",description:"Higher = tolerate more drift before jumping",min:10,max:90,value:e(this,g).heading.headingSnapThreshold,unit:"\xB0",onChange:d(r=>{e(this,g).heading.headingSnapThreshold=r,s(this,o,H).call(this)},"onChange")}),s(this,o,Ue).call(this,n,{id:"magnetic-gating",label:"Magnetic disturbance gating",description:"On = ignore compass near metal/magnets",value:e(this,g).heading.magneticDisturbanceGating,onChange:d(r=>{e(this,g).heading.magneticDisturbanceGating=r,s(this,o,H).call(this)},"onChange")});let i=document.createElement("div");i.className="bluedot-hud__tuning-group",i.innerHTML='<div class="bluedot-hud__tuning-group-title">Motion (PDR)</div>',s(this,o,Ue).call(this,i,{id:"pdr-enabled",label:"PDR enabled",description:"On = dot moves with detected steps",value:e(this,g).motion.pdrEnabled,onChange:d(r=>{e(this,g).motion.pdrEnabled=r,s(this,o,H).call(this)},"onChange")}),s(this,o,O).call(this,i,{id:"step-sensitivity",label:"Step sensitivity",description:"Higher = more steps detected, more false positives",min:0,max:100,value:e(this,g).motion.stepSensitivity,onChange:d(r=>{e(this,g).motion.stepSensitivity=r,s(this,o,H).call(this)},"onChange")}),s(this,o,O).call(this,i,{id:"step-length",label:"Average step length",description:"Higher = dot moves farther per step",min:.4,max:1.2,step:.05,value:e(this,g).motion.averageStepLength,unit:"m",onChange:d(r=>{e(this,g).motion.averageStepLength=r,s(this,o,H).call(this)},"onChange")}),s(this,o,O).call(this,i,{id:"stride-variability",label:"Stride variability",description:"Higher = faster walking = longer steps",min:0,max:100,value:e(this,g).motion.strideVariability,onChange:d(r=>{e(this,g).motion.strideVariability=r,s(this,o,H).call(this)},"onChange")});let a=document.createElement("button");a.className="bluedot-hud__reset-btn",a.textContent="Reset to Defaults",a.addEventListener("click",()=>s(this,o,it).call(this)),t.appendChild(n),t.appendChild(i),t.appendChild(a)},"#createTuningControls"),O=d(function(t,n){var _,y;let i=document.createElement("div");i.className="bluedot-hud__tuning-row";let a=document.createElement("div");a.className="bluedot-hud__tuning-label-row";let r=document.createElement("label");r.className="bluedot-hud__tuning-label",r.htmlFor="bluedot-tuning-".concat(n.id),r.textContent=n.label;let m=document.createElement("div");m.className="bluedot-hud__tuning-desc",m.textContent=n.description,a.appendChild(r),a.appendChild(m);let p=document.createElement("div");p.className="bluedot-hud__tuning-control";let c=document.createElement("input");c.type="range",c.id="bluedot-tuning-".concat(n.id),c.className="bluedot-hud__slider",c.min=String(n.min),c.max=String(n.max),c.step=String((_=n.step)!=null?_:1),c.value=String(n.value);let b=document.createElement("span");b.className="bluedot-hud__slider-value",b.textContent="".concat(n.value).concat((y=n.unit)!=null?y:""),c.addEventListener("input",()=>{var re;let x=parseFloat(c.value);b.textContent="".concat(n.step&&n.step<1?x.toFixed(2):x).concat((re=n.unit)!=null?re:""),n.onChange(x)}),p.appendChild(c),p.appendChild(b),i.appendChild(a),i.appendChild(p),t.appendChild(i)},"#createSlider"),Ue=d(function(t,n){let i=document.createElement("div");i.className="bluedot-hud__tuning-row bluedot-hud__tuning-row--toggle";let a=document.createElement("div");a.className="bluedot-hud__tuning-label-col";let r=document.createElement("label");r.className="bluedot-hud__tuning-label",r.htmlFor="bluedot-tuning-".concat(n.id),r.textContent=n.label;let m=document.createElement("div");m.className="bluedot-hud__tuning-desc",m.textContent=n.description,a.appendChild(r),a.appendChild(m);let p=document.createElement("input");p.type="checkbox",p.id="bluedot-tuning-".concat(n.id),p.className="bluedot-hud__toggle",p.checked=n.value,p.addEventListener("change",()=>{n.onChange(p.checked)}),i.appendChild(a),i.appendChild(p),t.appendChild(i)},"#createToggle"),H=d(function(){let t=$e(e(this,g).heading);e(this,f).Fusion.headingFilter.configure(t);let n=Ae(e(this,g).motion),i=e(this,f).Sensors.get("devicemotion");i==null||i.configure(n);let a=e(this,f).Sensors.get("deviceorientation");a==null||a.configure({deltaThreshold:e(this,g).heading.headingChangeThreshold})},"#applyTuning"),it=d(function(){u(this,g,{heading:S({},V.heading),motion:S({},V.motion)}),s(this,o,H).call(this),e(this,N).innerHTML="",s(this,o,we).call(this,e(this,N))},"#resetTuning"),Ie=d(function(){u(this,T,!e(this,T)),e(this,C).classList.toggle("bluedot-hud--collapsed",e(this,T)),e(this,C).classList.toggle("bluedot-hud--expanded",!e(this,T))},"#toggle"),st=d(function(){let t=e(this,f).on("position-update",()=>s(this,o,Pe).call(this)),n=e(this,f).on("status-change",()=>s(this,o,ze).call(this)),i=e(this,f).on("follow-change",()=>s(this,o,Ge).call(this)),a=e(this,f).on("anchor-set",()=>s(this,o,pe).call(this)),r=e(this,f).on("anchor-expired",()=>s(this,o,pe).call(this));e(this,R).push(t,n,i,a,r);let m=e(this,f).Sensors.on("absolute-update",({sensorId:b,update:_})=>{_.heading!==void 0&&(e(this,me).set(b,_.heading),s(this,o,Se).call(this)),(_.accuracy!==void 0||_.confidence!==void 0)&&(e(this,ge).set(b,{accuracy:_.accuracy,confidence:_.confidence}),s(this,o,Le).call(this))});e(this,R).push(m);let p=setInterval(()=>s(this,o,pe).call(this),1e3);e(this,R).push(()=>clearInterval(p));let c=setInterval(()=>s(this,o,Le).call(this),1e3);e(this,R).push(()=>clearInterval(c))},"#subscribeToEvents"),at=d(function(){s(this,o,ze).call(this),s(this,o,Pe).call(this),s(this,o,Ge).call(this),s(this,o,Se).call(this),s(this,o,pe).call(this),s(this,o,Le).call(this)},"#updateAll"),ze=d(function(){let t=e(this,f).status;e(this,X).textContent=t,e(this,Z).textContent=t,e(this,$).classList.remove("bluedot-hud__status-dot--active","bluedot-hud__status-dot--inactive","bluedot-hud__status-dot--error"),t==="active"?e(this,$).classList.add("bluedot-hud__status-dot--active"):t==="inactive"||t==="hidden"?e(this,$).classList.add("bluedot-hud__status-dot--inactive"):e(this,$).classList.add("bluedot-hud__status-dot--error")},"#updateStatus"),Pe=d(function(){var a;let t=e(this,f).coordinate,n=e(this,f).accuracy,i=e(this,f).floor;t?e(this,P).textContent="".concat(t.latitude.toFixed(5),", ").concat(t.longitude.toFixed(5)):e(this,P).textContent="--",e(this,be).textContent=t?t.latitude.toFixed(6):"--",e(this,fe).textContent=t?t.longitude.toFixed(6):"--",e(this,_e).textContent=n!=null?"".concat(n.toFixed(1),"m"):"--",e(this,xe).textContent=(a=i==null?void 0:i.name)!=null?a:"--",s(this,o,Se).call(this)},"#updatePosition"),Ge=d(function(){e(this,ee).textContent=e(this,f).isFollowing?"yes":"no"},"#updateFollowing"),Se=d(function(){let t=e(this,f).heading;e(this,Y).textContent=t!=null?"".concat(t.toFixed(0),"\xB0"):"--",t!=null&&(e(this,W).style.transform="translate(-50%, -100%) rotate(".concat(t,"deg)")),e(this,U).innerHTML="";let n=document.createElement("div");n.className="bluedot-hud__heading-row bluedot-hud__heading-row--displayed",n.innerHTML='\n <span class="bluedot-hud__heading-label">Displayed</span>\n <span class="bluedot-hud__heading-value">'.concat(t!=null?"".concat(t.toFixed(0),"\xB0"):"--","</span>\n "),e(this,U).appendChild(n);for(let[i,a]of e(this,me)){let r=document.createElement("div");r.className="bluedot-hud__heading-row";let m=a!=null&&t!=null?s(this,o,dt).call(this,a-t):null,p=m!=null?" (".concat(m>=0?"+":"").concat(m.toFixed(0),"\xB0)"):"",c=m!=null&&Math.abs(m)>10?"bluedot-hud__heading-diff--warning":"";r.innerHTML='\n <span class="bluedot-hud__heading-label">'.concat(i,'</span>\n <span class="bluedot-hud__heading-value">').concat(a!=null?"".concat(a.toFixed(0),"\xB0"):"--",'<span class="bluedot-hud__heading-diff ').concat(c,'">').concat(p,"</span></span>\n "),e(this,U).appendChild(r)}},"#updateHeadings"),dt=d(function(t){for(;t>180;)t-=360;for(;t<-180;)t+=360;return t},"#normalizeAngleDiff"),pe=d(function(){let t=e(this,f).anchor,n=e(this,f).displacement;if(t){e(this,A).textContent="set (".concat(t.sensorId,")"),e(this,A).classList.add("bluedot-hud__value--enabled"),e(this,A).classList.remove("bluedot-hud__value--disabled"),e(this,te).textContent="".concat(t.latitude.toFixed(6),", ").concat(t.longitude.toFixed(6)),e(this,ne).textContent=mt(t.timestamp),e(this,oe).textContent=gt(t.timestamp,t.ttl);let i=Math.sqrt(n.dx**2+n.dy**2);e(this,ie).textContent="dx=".concat(n.dx>=0?"+":"").concat(n.dx.toFixed(2),"m, dy=").concat(n.dy>=0?"+":"").concat(n.dy.toFixed(2),"m (").concat(i.toFixed(2),"m)")}else e(this,A).textContent="none",e(this,A).classList.remove("bluedot-hud__value--enabled"),e(this,A).classList.add("bluedot-hud__value--disabled"),e(this,te).textContent="--",e(this,ne).textContent="--",e(this,oe).textContent="--",e(this,ie).textContent="--"},"#updateAnchor"),Le=d(function(){var t;e(this,G).innerHTML="";for(let[n,i]of e(this,f).Sensors.getAll()){let a=document.createElement("div");a.className="bluedot-hud__row";let r="".concat(n,":");n==="geolocation"&&(r=i.isLikelyIPS?"IPS (Wi-Fi):":"GPS:");let m=s(this,o,he).call(this,r),p=i.isEnabled?"enabled":"disabled",c=e(this,ge).get(n);if(i.isEnabled&&c){let x=[];c.accuracy!==void 0&&x.push("".concat(c.accuracy.toFixed(1),"m")),c.confidence!==void 0&&x.push("conf=".concat((c.confidence*100).toFixed(0),"%")),x.length>0&&(p=x.join(", "))}let b=s(this,o,ce).call(this,p);b.classList.add(i.isEnabled?"bluedot-hud__value--enabled":"bluedot-hud__value--disabled");let _=n==="geolocation"?i:null,y=(t=_==null?void 0:_.isLikelyIPS)!=null?t:!1;(c==null?void 0:c.confidence)!==void 0&&c.confidence<.5&&!y&&b.classList.add("bluedot-hud__value--warning"),a.appendChild(m),a.appendChild(b),e(this,G).appendChild(a)}},"#updateSensors"),d(Be,"DebugHUD");var Me=Be;D();var v,se,ae,Ve=class Ve{constructor(t=100){h(this,v,[]);h(this,se);h(this,ae,0);u(this,se,t)}record(t,n=Date.now()){e(this,v).push(t),e(this,v).length>e(this,se)&&e(this,v).shift(),u(this,ae,n)}getRate(){if(e(this,v).length<2)return 0;let t=e(this,ae)-(Date.now()-e(this,se)*100);return t>0?e(this,v).length/t*1e3:0}getAverage(){if(e(this,v).length===0)return 0;let t=0;for(let n of e(this,v))t+=n;return t/e(this,v).length}getLatest(){return e(this,v)[e(this,v).length-1]}getCount(){return e(this,v).length}clear(){u(this,v,[]),u(this,ae,0)}};v=new WeakMap,se=new WeakMap,ae=new WeakMap,d(Ve,"MetricTracker");var q=Ve,k,de,le,He,Oe=class Oe{constructor(t=5e3){h(this,le);h(this,k,[]);h(this,de);u(this,de,t)}tick(t=Date.now()){e(this,k).push(t),s(this,le,He).call(this,t)}getRate(t=Date.now()){return s(this,le,He).call(this,t),e(this,k).length===0?0:e(this,k).length/e(this,de)*1e3}getCount(t=Date.now()){return s(this,le,He).call(this,t),e(this,k).length}clear(){u(this,k,[])}};k=new WeakMap,de=new WeakMap,le=new WeakSet,He=d(function(t){let n=t-e(this,de);for(;e(this,k).length>0&&e(this,k)[0]<n;)e(this,k).shift()},"#prune"),d(Oe,"EventCounter");var J=Oe,K,j,Xe=class Xe{constructor(){h(this,K,new Map);h(this,j,!1);L(this,"compassUpdates",new J);L(this,"gyroUpdates",new J);L(this,"stepsDetected",new J);L(this,"positionUpdates",new J);L(this,"compassHeading",new q(50));L(this,"gyroAngularVelocity",new q(50));L(this,"stepLength",new q(20));L(this,"positionAccuracy",new q(20));L(this,"isMoving",!1);L(this,"magneticDisturbanceActive",!1);L(this,"lastFusedHeading",null)}enable(){u(this,j,!0)}disable(){u(this,j,!1)}get isEnabled(){return e(this,j)}emit(t,n){if(!e(this,j))return;let i=Date.now();switch(t){case"compass-update":this.compassUpdates.tick(i),this.compassHeading.record(n.heading,i);break;case"gyro-update":this.gyroUpdates.tick(i),this.gyroAngularVelocity.record(n.angularVelocity,i);break;case"step-detected":this.stepsDetected.tick(i),this.stepLength.record(n.stepLength,i);break;case"motion-state":this.isMoving=n.isMoving;break;case"magnetic-disturbance":this.magneticDisturbanceActive=n.active;break;case"heading-fused":this.lastFusedHeading=n.heading;break;case"position-update":this.positionUpdates.tick(i),this.positionAccuracy.record(n.accuracy,i);break}let a=e(this,K).get(t);if(a)for(let r of a)r(n)}on(t,n){let i=e(this,K).get(t);return i||(i=new Set,e(this,K).set(t,i)),i.add(n),()=>{i.delete(n)}}getSummary(){return{compassRate:this.compassUpdates.getRate(),gyroRate:this.gyroUpdates.getRate(),stepRate:this.stepsDetected.getRate(),positionRate:this.positionUpdates.getRate(),avgCompassHeading:this.compassHeading.getAverage(),avgGyroVelocity:this.gyroAngularVelocity.getAverage(),avgStepLength:this.stepLength.getAverage(),avgAccuracy:this.positionAccuracy.getAverage(),isMoving:this.isMoving,magneticDisturbanceActive:this.magneticDisturbanceActive,lastFusedHeading:this.lastFusedHeading}}clear(){this.compassUpdates.clear(),this.gyroUpdates.clear(),this.stepsDetected.clear(),this.positionUpdates.clear(),this.compassHeading.clear(),this.gyroAngularVelocity.clear(),this.stepLength.clear(),this.positionAccuracy.clear(),this.isMoving=!1,this.magneticDisturbanceActive=!1,this.lastFusedHeading=null}destroy(){this.clear(),e(this,K).clear(),u(this,j,!1)}};K=new WeakMap,j=new WeakMap,d(Xe,"Telemetry");var je=Xe;function $t(l){return new Me(l)}d($t,"enableDebugHUD");export{V as DEFAULT_TUNING_CONFIG,J as EventCounter,q as MetricTracker,je as Telemetry,$t as enableDebugHUD,$e as headingConfigToFilterParams,Ae as motionConfigToSensorParams,rt as normalizeTuningConfig};
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Coordinate, Floor, MapView, Model } from "@mappedin/mappedin-js";
|
|
2
2
|
|
|
3
|
-
//#region ../packages/common/browser.d.ts
|
|
4
|
-
|
|
5
|
-
type BrowserPermissionState = PermissionState | 'unavailable';
|
|
6
|
-
//#endregion
|
|
7
3
|
//#region ../../node_modules/.pnpm/type-fest@5.4.2/node_modules/type-fest/source/primitive.d.ts
|
|
4
|
+
|
|
8
5
|
/**
|
|
9
6
|
Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
|
|
10
7
|
|
|
@@ -872,25 +869,6 @@ Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper fo
|
|
|
872
869
|
*/
|
|
873
870
|
type _ReadonlyObjectDeep<ObjectType extends object> = { readonly [KeyType in keyof ObjectType]: ReadonlyDeep<ObjectType[KeyType]> };
|
|
874
871
|
//#endregion
|
|
875
|
-
//#region ../packages/common/extensions.d.ts
|
|
876
|
-
interface MapViewExtension<T> {
|
|
877
|
-
enable(options?: PartialDeep<T>): void;
|
|
878
|
-
disable(): void;
|
|
879
|
-
get isEnabled(): boolean;
|
|
880
|
-
destroy(): void;
|
|
881
|
-
}
|
|
882
|
-
//#endregion
|
|
883
|
-
//#region src/status/types.d.ts
|
|
884
|
-
type BlueDotStatus = 'hidden' | 'active' | 'inactive' | 'disabled';
|
|
885
|
-
type BlueDotAction = 'timeout' | 'error' | 'position-update' | 'enable' | 'disable' | 'initialize';
|
|
886
|
-
//#endregion
|
|
887
|
-
//#region src/follow/types.d.ts
|
|
888
|
-
type FollowMode = /** Camera position follows the Blue Dot's position. */
|
|
889
|
-
'position-only'
|
|
890
|
-
/** Camera position follows the Blue Dot's position. Camera bearing matches the Blue Dot's heading. */ | 'position-and-heading'
|
|
891
|
-
/** Camera position follows the Blue Dot's position. Camera bearing is calculated based on the Navigation path. */ | 'position-and-path-direction'
|
|
892
|
-
/** Disables follow mode */ | false;
|
|
893
|
-
//#endregion
|
|
894
872
|
//#region src/sensors/types.d.ts
|
|
895
873
|
/**
|
|
896
874
|
* Built-in sensor IDs
|
|
@@ -1028,7 +1006,34 @@ type SensorEventPayloads = {
|
|
|
1028
1006
|
};
|
|
1029
1007
|
};
|
|
1030
1008
|
//#endregion
|
|
1009
|
+
//#region src/fusion/anchor-state.d.ts
|
|
1010
|
+
/**
|
|
1011
|
+
* Anchor state in the fusion engine's hybrid anchor behavior model.
|
|
1012
|
+
*
|
|
1013
|
+
* - `'none'`: No anchor active; GPS measurements accepted, PDR ignored
|
|
1014
|
+
* - `'anchor-only'`: Anchor active and in exclusive period; GPS rejected, PDR accepted
|
|
1015
|
+
* - `'transition'`: Anchor active but past exclusive period; GPS accepted with increasing weight
|
|
1016
|
+
*/
|
|
1017
|
+
type AnchorState = 'none' | 'anchor-only' | 'transition';
|
|
1018
|
+
//#endregion
|
|
1031
1019
|
//#region src/fusion/types.d.ts
|
|
1020
|
+
type FusionEventPayloads = {
|
|
1021
|
+
'fused-position': {
|
|
1022
|
+
position: FusedPosition;
|
|
1023
|
+
};
|
|
1024
|
+
'heading-update': {
|
|
1025
|
+
heading: number;
|
|
1026
|
+
};
|
|
1027
|
+
'anchor-set': {
|
|
1028
|
+
anchor: PositionAnchor;
|
|
1029
|
+
};
|
|
1030
|
+
'anchor-expired': {
|
|
1031
|
+
anchor: PositionAnchor;
|
|
1032
|
+
};
|
|
1033
|
+
error: {
|
|
1034
|
+
error: Error | GeolocationPositionError;
|
|
1035
|
+
};
|
|
1036
|
+
};
|
|
1032
1037
|
type PositionMetadata = {
|
|
1033
1038
|
/** Confidence score 0-1 (0 = no confidence, 1 = 100% certain) */
|
|
1034
1039
|
confidence: number;
|
|
@@ -1109,6 +1114,29 @@ interface RelativePositionUpdate {
|
|
|
1109
1114
|
/** Confidence score 0-1 */
|
|
1110
1115
|
confidence: number;
|
|
1111
1116
|
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Configuration for the multi-sensor EKF fusion engine.
|
|
1119
|
+
*/
|
|
1120
|
+
interface FusionEngineConfig {
|
|
1121
|
+
/**
|
|
1122
|
+
* Duration in ms where anchor is exclusive (GPS rejected).
|
|
1123
|
+
* @default 5000 (5 seconds)
|
|
1124
|
+
*/
|
|
1125
|
+
anchorOnlyPeriodMs: number;
|
|
1126
|
+
/**
|
|
1127
|
+
* Half-life for state uncertainty growth in milliseconds.
|
|
1128
|
+
* The state uncertainty doubles every halfLifeMs when no measurements arrive.
|
|
1129
|
+
* Lower values = faster decay of old position estimates.
|
|
1130
|
+
* @default 10000 (10 seconds)
|
|
1131
|
+
*/
|
|
1132
|
+
halfLifeMs: number;
|
|
1133
|
+
/**
|
|
1134
|
+
* Maximum age of position updates to consider in milliseconds.
|
|
1135
|
+
* Updates older than this cause filter reset.
|
|
1136
|
+
* @default 5000 (5 seconds)
|
|
1137
|
+
*/
|
|
1138
|
+
maxAgeMs: number;
|
|
1139
|
+
}
|
|
1112
1140
|
/**
|
|
1113
1141
|
* Position anchor from a calibration source (VPS, AI Localizer).
|
|
1114
1142
|
* Anchors represent absolute ground truth positions that other sensors
|
|
@@ -1137,6 +1165,28 @@ interface PositionAnchor {
|
|
|
1137
1165
|
confidence?: number;
|
|
1138
1166
|
}
|
|
1139
1167
|
//#endregion
|
|
1168
|
+
//#region ../packages/common/browser.d.ts
|
|
1169
|
+
type BrowserPermissionState = PermissionState | 'unavailable';
|
|
1170
|
+
//#endregion
|
|
1171
|
+
//#region ../packages/common/extensions.d.ts
|
|
1172
|
+
interface MapViewExtension<T> {
|
|
1173
|
+
enable(options?: PartialDeep<T>): void;
|
|
1174
|
+
disable(): void;
|
|
1175
|
+
get isEnabled(): boolean;
|
|
1176
|
+
destroy(): void;
|
|
1177
|
+
}
|
|
1178
|
+
//#endregion
|
|
1179
|
+
//#region src/status/types.d.ts
|
|
1180
|
+
type BlueDotStatus = 'hidden' | 'active' | 'inactive' | 'disabled';
|
|
1181
|
+
type BlueDotAction = 'timeout' | 'error' | 'position-update' | 'enable' | 'disable' | 'initialize';
|
|
1182
|
+
//#endregion
|
|
1183
|
+
//#region src/follow/types.d.ts
|
|
1184
|
+
type FollowMode = /** Camera position follows the Blue Dot's position. */
|
|
1185
|
+
'position-only'
|
|
1186
|
+
/** Camera position follows the Blue Dot's position. Camera bearing matches the Blue Dot's heading. */ | 'position-and-heading'
|
|
1187
|
+
/** Camera position follows the Blue Dot's position. Camera bearing is calculated based on the Navigation path. */ | 'position-and-path-direction'
|
|
1188
|
+
/** Disables follow mode */ | false;
|
|
1189
|
+
//#endregion
|
|
1140
1190
|
//#region src/types.d.ts
|
|
1141
1191
|
type FollowCameraOptions = {
|
|
1142
1192
|
/**
|
|
@@ -1922,6 +1972,329 @@ declare class SensorRegistry extends PubSub<SensorEventPayloads> {
|
|
|
1922
1972
|
destroy(): void;
|
|
1923
1973
|
}
|
|
1924
1974
|
//#endregion
|
|
1975
|
+
//#region src/fusion/algorithms/types.d.ts
|
|
1976
|
+
/**
|
|
1977
|
+
* Interface for heading fusion algorithms.
|
|
1978
|
+
* Combines compass, gyroscope, and GPS heading for stable heading estimation.
|
|
1979
|
+
*/
|
|
1980
|
+
interface HeadingFusionAlgorithm {
|
|
1981
|
+
/**
|
|
1982
|
+
* Update with compass heading (absolute but noisy).
|
|
1983
|
+
* @param heading Compass heading in degrees [0, 360)
|
|
1984
|
+
* @param timestamp Update timestamp in milliseconds
|
|
1985
|
+
*/
|
|
1986
|
+
updateCompass(heading: number, timestamp: number): void;
|
|
1987
|
+
/**
|
|
1988
|
+
* Update with gyroscope angular velocity (smooth relative changes).
|
|
1989
|
+
* @param angularVelocity Angular velocity in deg/s around vertical axis
|
|
1990
|
+
* @param timestamp Update timestamp in milliseconds
|
|
1991
|
+
*/
|
|
1992
|
+
updateGyro(angularVelocity: number, timestamp: number): void;
|
|
1993
|
+
/**
|
|
1994
|
+
* Correct heading with GPS ground truth when moving.
|
|
1995
|
+
* @param gpsHeading GPS heading in degrees [0, 360)
|
|
1996
|
+
* @param speed Current speed in m/s
|
|
1997
|
+
*/
|
|
1998
|
+
correctWithGps(gpsHeading: number, speed: number): void;
|
|
1999
|
+
/**
|
|
2000
|
+
* Get the current fused heading.
|
|
2001
|
+
* @returns Fused heading in degrees [0, 360), or null if not initialized
|
|
2002
|
+
*/
|
|
2003
|
+
getHeading(): number | null;
|
|
2004
|
+
/**
|
|
2005
|
+
* Reset the algorithm state.
|
|
2006
|
+
*/
|
|
2007
|
+
reset(): void;
|
|
2008
|
+
}
|
|
2009
|
+
//#endregion
|
|
2010
|
+
//#region src/fusion/algorithms/heading-filter.d.ts
|
|
2011
|
+
/**
|
|
2012
|
+
* Configuration options for the heading fusion filter.
|
|
2013
|
+
*/
|
|
2014
|
+
interface HeadingFilterConfig {
|
|
2015
|
+
/** Complementary filter alpha (0-1). Higher = more gyro weight. */
|
|
2016
|
+
complementaryAlpha: number;
|
|
2017
|
+
/** Minimum angular velocity to integrate (deg/s). */
|
|
2018
|
+
gyroNoiseThreshold: number;
|
|
2019
|
+
/** Maximum heading error before snapping to compass (degrees). */
|
|
2020
|
+
maxHeadingError: number;
|
|
2021
|
+
/** Enable magnetic disturbance detection. */
|
|
2022
|
+
magneticGatingEnabled: boolean;
|
|
2023
|
+
/** Minimum heading delta to emit updates (degrees). */
|
|
2024
|
+
deltaThreshold: number;
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Complementary filter for heading fusion.
|
|
2028
|
+
* Combines compass (absolute but noisy), gyroscope (smooth relative changes),
|
|
2029
|
+
* and GPS heading (ground truth when moving) to produce stable heading.
|
|
2030
|
+
*
|
|
2031
|
+
* The filter works by:
|
|
2032
|
+
* 1. Short-term: Integrate gyroscope angular velocity for smooth rotations
|
|
2033
|
+
* 2. Long-term: Slowly blend toward compass to prevent gyroscope drift
|
|
2034
|
+
* 3. Correction: When GPS heading is valid (moving fast enough), use as ground truth
|
|
2035
|
+
*
|
|
2036
|
+
* @example
|
|
2037
|
+
* ```ts
|
|
2038
|
+
* const filter = new HeadingFusionFilter();
|
|
2039
|
+
*
|
|
2040
|
+
* // Update with compass reading
|
|
2041
|
+
* filter.updateCompass(45, Date.now());
|
|
2042
|
+
*
|
|
2043
|
+
* // Update with gyroscope angular velocity
|
|
2044
|
+
* filter.updateGyro(5.0, Date.now()); // 5 deg/s rotation
|
|
2045
|
+
*
|
|
2046
|
+
* // Correct with GPS when moving
|
|
2047
|
+
* filter.correctWithGps(47, 1.5); // heading 47°, speed 1.5 m/s
|
|
2048
|
+
*
|
|
2049
|
+
* // Get fused heading
|
|
2050
|
+
* const heading = filter.getHeading(); // ~46°
|
|
2051
|
+
* ```
|
|
2052
|
+
*/
|
|
2053
|
+
declare class HeadingFusionFilter implements HeadingFusionAlgorithm {
|
|
2054
|
+
#private;
|
|
2055
|
+
/**
|
|
2056
|
+
* Update the filter with a compass heading reading.
|
|
2057
|
+
* The compass provides absolute heading but is susceptible to magnetic interference.
|
|
2058
|
+
* @param heading Compass heading in degrees [0, 360)
|
|
2059
|
+
* @param timestamp Update timestamp in milliseconds
|
|
2060
|
+
*/
|
|
2061
|
+
updateCompass(heading: number, _timestamp: number): void;
|
|
2062
|
+
/**
|
|
2063
|
+
* Update the filter with gyroscope angular velocity.
|
|
2064
|
+
* The gyroscope provides smooth relative heading changes immune to magnetic fields.
|
|
2065
|
+
* @param angularVelocity Angular velocity around vertical axis in deg/s
|
|
2066
|
+
* @param timestamp Update timestamp in milliseconds
|
|
2067
|
+
*/
|
|
2068
|
+
updateGyro(angularVelocity: number, timestamp: number): void;
|
|
2069
|
+
/**
|
|
2070
|
+
* Correct the heading with GPS when available.
|
|
2071
|
+
* GPS heading is only considered when moving fast enough and with sufficient confidence.
|
|
2072
|
+
* @param gpsHeading GPS heading in degrees [0, 360)
|
|
2073
|
+
* @param speed Current speed in m/s
|
|
2074
|
+
* @param confidence GPS confidence (0-1), affects how much GPS heading influences result
|
|
2075
|
+
*/
|
|
2076
|
+
correctWithGps(gpsHeading: number, speed: number, confidence?: number): void;
|
|
2077
|
+
/**
|
|
2078
|
+
* Configure the filter parameters at runtime.
|
|
2079
|
+
* @param config Partial configuration to apply
|
|
2080
|
+
*/
|
|
2081
|
+
configure(config: Partial<HeadingFilterConfig>): void;
|
|
2082
|
+
/**
|
|
2083
|
+
* Get current configuration values.
|
|
2084
|
+
*/
|
|
2085
|
+
getConfig(): HeadingFilterConfig;
|
|
2086
|
+
/**
|
|
2087
|
+
* Check if magnetic disturbance is currently detected.
|
|
2088
|
+
*/
|
|
2089
|
+
isMagneticDisturbanceActive(): boolean;
|
|
2090
|
+
/**
|
|
2091
|
+
* Get the current fused heading.
|
|
2092
|
+
* @returns Fused heading in degrees [0, 360), or null if not initialized
|
|
2093
|
+
*/
|
|
2094
|
+
getHeading(): number | null;
|
|
2095
|
+
/**
|
|
2096
|
+
* Check if the filter has been initialized with at least one compass reading.
|
|
2097
|
+
* @returns True if filter is initialized
|
|
2098
|
+
*/
|
|
2099
|
+
isInitialized(): boolean;
|
|
2100
|
+
/**
|
|
2101
|
+
* Get the last compass heading received.
|
|
2102
|
+
* @returns Last compass heading in degrees, or null if none received
|
|
2103
|
+
*/
|
|
2104
|
+
getLastCompassHeading(): number | null;
|
|
2105
|
+
/**
|
|
2106
|
+
* Reset the filter state.
|
|
2107
|
+
* Call on floor changes or when heading should be re-initialized.
|
|
2108
|
+
*/
|
|
2109
|
+
reset(): void;
|
|
2110
|
+
}
|
|
2111
|
+
//#endregion
|
|
2112
|
+
//#region src/fusion/algorithms/multi-sensor-ekf.d.ts
|
|
2113
|
+
/**
|
|
2114
|
+
* Configuration options for the Multi-Sensor EKF.
|
|
2115
|
+
*/
|
|
2116
|
+
interface MultiSensorEKFOptions {
|
|
2117
|
+
/**
|
|
2118
|
+
* Half-life for uncertainty growth in milliseconds.
|
|
2119
|
+
* The state uncertainty doubles every halfLifeMs when no measurements arrive.
|
|
2120
|
+
* Lower values = faster decay of old estimates.
|
|
2121
|
+
* @default 10000 (10 seconds)
|
|
2122
|
+
*/
|
|
2123
|
+
halfLifeMs: number;
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* Multi-sensor Extended Kalman Filter for position fusion.
|
|
2127
|
+
*
|
|
2128
|
+
* Combines position measurements from multiple sources (GPS, VPS, anchors) and
|
|
2129
|
+
* displacement measurements from PDR using a constant-velocity motion model.
|
|
2130
|
+
*
|
|
2131
|
+
* Key features:
|
|
2132
|
+
* - All methods take explicit timestamps (no Date.now() inside)
|
|
2133
|
+
* - Confidence-weighted fusion via measurement noise parameter
|
|
2134
|
+
* - Half-life decay of old estimates via process noise scaling
|
|
2135
|
+
* - Supports both absolute position and relative displacement updates
|
|
2136
|
+
*
|
|
2137
|
+
* State vector: [latitude, longitude, velocity_lat, velocity_lon]
|
|
2138
|
+
*
|
|
2139
|
+
* @example
|
|
2140
|
+
* ```ts
|
|
2141
|
+
* const ekf = new MultiSensorEKF({ halfLifeMs: 10000 });
|
|
2142
|
+
*
|
|
2143
|
+
* // Initialize with first position
|
|
2144
|
+
* ekf.updatePosition(43.123, -79.456, 0.0001, 0);
|
|
2145
|
+
*
|
|
2146
|
+
* // Predict forward
|
|
2147
|
+
* ekf.predict(1000);
|
|
2148
|
+
*
|
|
2149
|
+
* // Update with new GPS measurement (low confidence = high noise)
|
|
2150
|
+
* ekf.updatePosition(43.124, -79.455, 0.001, 1000);
|
|
2151
|
+
*
|
|
2152
|
+
* // Get fused position
|
|
2153
|
+
* const pos = ekf.getPosition(); // { latitude: ~43.1235, longitude: ~-79.4555 }
|
|
2154
|
+
* ```
|
|
2155
|
+
*/
|
|
2156
|
+
declare class MultiSensorEKF {
|
|
2157
|
+
#private;
|
|
2158
|
+
constructor(options?: Partial<MultiSensorEKFOptions>);
|
|
2159
|
+
/**
|
|
2160
|
+
* Predict step: project state forward to the given timestamp.
|
|
2161
|
+
* Increases uncertainty based on elapsed time and half-life configuration.
|
|
2162
|
+
*
|
|
2163
|
+
* @param timestampMs - Current timestamp in milliseconds
|
|
2164
|
+
*/
|
|
2165
|
+
predict(timestampMs: number): void;
|
|
2166
|
+
/**
|
|
2167
|
+
* Update state with a position measurement (GPS, VPS, anchor).
|
|
2168
|
+
*
|
|
2169
|
+
* @param latitude - Measured latitude in degrees
|
|
2170
|
+
* @param longitude - Measured longitude in degrees
|
|
2171
|
+
* @param measurementNoise - Measurement noise variance (higher = less trust)
|
|
2172
|
+
* @param timestampMs - Measurement timestamp in milliseconds
|
|
2173
|
+
*/
|
|
2174
|
+
updatePosition(latitude: number, longitude: number, measurementNoise: number, timestampMs: number): void;
|
|
2175
|
+
/**
|
|
2176
|
+
* Update state with an odometry measurement (PDR displacement).
|
|
2177
|
+
*
|
|
2178
|
+
* Unlike position updates, odometry provides relative displacement rather than
|
|
2179
|
+
* absolute position. The displacement is added directly to the state.
|
|
2180
|
+
*
|
|
2181
|
+
* @param dx - Displacement east in meters (positive = east)
|
|
2182
|
+
* @param dy - Displacement north in meters (positive = north)
|
|
2183
|
+
* @param measurementNoise - Measurement noise variance (higher = less trust)
|
|
2184
|
+
* @param timestampMs - Measurement timestamp in milliseconds
|
|
2185
|
+
*/
|
|
2186
|
+
updateOdometry(dx: number, dy: number, measurementNoise: number, timestampMs: number): void;
|
|
2187
|
+
/**
|
|
2188
|
+
* Get the current position estimate.
|
|
2189
|
+
* @returns Position or null if filter not initialized
|
|
2190
|
+
*/
|
|
2191
|
+
getPosition(): {
|
|
2192
|
+
latitude: number;
|
|
2193
|
+
longitude: number;
|
|
2194
|
+
} | null;
|
|
2195
|
+
/**
|
|
2196
|
+
* Get the current velocity estimate.
|
|
2197
|
+
* @returns Velocity in degrees per second, or null if filter not initialized
|
|
2198
|
+
*/
|
|
2199
|
+
getVelocity(): {
|
|
2200
|
+
vLat: number;
|
|
2201
|
+
vLon: number;
|
|
2202
|
+
} | null;
|
|
2203
|
+
/**
|
|
2204
|
+
* Get the current position uncertainty (trace of position covariance).
|
|
2205
|
+
* Higher values indicate less certainty in the position estimate.
|
|
2206
|
+
* @returns Uncertainty value, or Infinity if filter not initialized
|
|
2207
|
+
*/
|
|
2208
|
+
getUncertainty(): number;
|
|
2209
|
+
/**
|
|
2210
|
+
* Get the last update timestamp.
|
|
2211
|
+
* @returns Timestamp in ms, or null if filter not initialized
|
|
2212
|
+
*/
|
|
2213
|
+
getLastTimestamp(): number | null;
|
|
2214
|
+
/**
|
|
2215
|
+
* Check if the filter has been initialized with at least one measurement.
|
|
2216
|
+
*/
|
|
2217
|
+
isInitialized(): boolean;
|
|
2218
|
+
/**
|
|
2219
|
+
* Reset the filter state.
|
|
2220
|
+
* Call on floor changes, large position jumps, or time gaps.
|
|
2221
|
+
*/
|
|
2222
|
+
reset(): void;
|
|
2223
|
+
}
|
|
2224
|
+
//#endregion
|
|
2225
|
+
//#region src/fusion/fusion-engine.d.ts
|
|
2226
|
+
/**
|
|
2227
|
+
* Multi-sensor fusion engine that combines position updates from multiple sources.
|
|
2228
|
+
*
|
|
2229
|
+
* Uses an Extended Kalman Filter (EKF) for position fusion with:
|
|
2230
|
+
* - Confidence-weighted measurements (high confidence = more influence)
|
|
2231
|
+
* - Half-life decay of old estimates (uncertainty grows over time)
|
|
2232
|
+
* - Hybrid anchor behavior (anchor-only period, then transition to GPS)
|
|
2233
|
+
*
|
|
2234
|
+
* Heading fusion uses a separate complementary filter combining compass and gyroscope.
|
|
2235
|
+
*/
|
|
2236
|
+
declare class FusionEngine extends PubSub<FusionEventPayloads> {
|
|
2237
|
+
#private;
|
|
2238
|
+
constructor(registry: SensorRegistry, config?: Partial<FusionEngineConfig>);
|
|
2239
|
+
/**
|
|
2240
|
+
* Get the current fusion configuration.
|
|
2241
|
+
*/
|
|
2242
|
+
get config(): Readonly<FusionEngineConfig>;
|
|
2243
|
+
/**
|
|
2244
|
+
* Get the current anchor state.
|
|
2245
|
+
* @param nowMs - Current timestamp (defaults to Date.now())
|
|
2246
|
+
*/
|
|
2247
|
+
getAnchorState(nowMs?: number): AnchorState;
|
|
2248
|
+
/**
|
|
2249
|
+
* Get the current position anchor if one is set and not expired.
|
|
2250
|
+
*/
|
|
2251
|
+
get anchor(): Readonly<PositionAnchor> | undefined;
|
|
2252
|
+
/**
|
|
2253
|
+
* Get the current accumulated displacement from the anchor in meters.
|
|
2254
|
+
* Returns (0, 0) if no anchor is set or no movement has occurred.
|
|
2255
|
+
*/
|
|
2256
|
+
get displacement(): Readonly<DisplacementVector>;
|
|
2257
|
+
/**
|
|
2258
|
+
* Set an absolute position anchor from a calibration source (VPS, AI Localizer).
|
|
2259
|
+
* When an anchor is active, it provides the absolute position and other sensors
|
|
2260
|
+
* can provide relative updates from this reference point.
|
|
2261
|
+
*
|
|
2262
|
+
* @param anchor - The position anchor to set
|
|
2263
|
+
* @param configOverride - Optional config overrides for this anchor (e.g., anchorOnlyPeriodMs)
|
|
2264
|
+
*/
|
|
2265
|
+
setAnchor(anchor: PositionAnchor, configOverride?: Partial<Pick<FusionEngineConfig, 'anchorOnlyPeriodMs'>>): void;
|
|
2266
|
+
/**
|
|
2267
|
+
* Clear the current position anchor and accumulated displacement.
|
|
2268
|
+
*/
|
|
2269
|
+
clearAnchor(): void;
|
|
2270
|
+
/**
|
|
2271
|
+
* Reset the EKF state.
|
|
2272
|
+
* Call on floor changes or large position jumps.
|
|
2273
|
+
*/
|
|
2274
|
+
resetEKF(): void;
|
|
2275
|
+
/**
|
|
2276
|
+
* Reset the heading fusion filter state.
|
|
2277
|
+
* Call on floor changes or when heading should be re-initialized.
|
|
2278
|
+
*/
|
|
2279
|
+
resetHeadingFilter(): void;
|
|
2280
|
+
/**
|
|
2281
|
+
* Get the heading fusion filter for configuration.
|
|
2282
|
+
* @internal Used by debug tools for runtime tuning.
|
|
2283
|
+
*/
|
|
2284
|
+
get headingFilter(): HeadingFusionFilter;
|
|
2285
|
+
/**
|
|
2286
|
+
* Get the multi-sensor EKF for inspection.
|
|
2287
|
+
* @internal Used by debug tools for runtime inspection.
|
|
2288
|
+
*/
|
|
2289
|
+
get ekf(): MultiSensorEKF;
|
|
2290
|
+
/**
|
|
2291
|
+
* Get the last fused position.
|
|
2292
|
+
* @returns The last fused position, or undefined if none available
|
|
2293
|
+
*/
|
|
2294
|
+
getLastPosition(): FusedPosition | undefined;
|
|
2295
|
+
destroy(): void;
|
|
2296
|
+
}
|
|
2297
|
+
//#endregion
|
|
1925
2298
|
//#region src/blue-dot.d.ts
|
|
1926
2299
|
/**
|
|
1927
2300
|
* Show a Blue Dot indicating the device's position on the map.
|
|
@@ -1954,6 +2327,21 @@ declare class BlueDot implements MapViewExtension<BlueDotState> {
|
|
|
1954
2327
|
constructor(mapView: MapView);
|
|
1955
2328
|
/** Sensors API */
|
|
1956
2329
|
get Sensors(): SensorRegistry;
|
|
2330
|
+
/**
|
|
2331
|
+
* Fusion engine API.
|
|
2332
|
+
* @internal Used by debug tools for runtime tuning and inspection.
|
|
2333
|
+
*/
|
|
2334
|
+
get Fusion(): FusionEngine;
|
|
2335
|
+
/**
|
|
2336
|
+
* Get the current position anchor if one is set and not expired.
|
|
2337
|
+
* Anchors provide absolute ground truth positions from calibration sources (VPS, AI Localizer).
|
|
2338
|
+
*/
|
|
2339
|
+
get anchor(): Readonly<PositionAnchor> | undefined;
|
|
2340
|
+
/**
|
|
2341
|
+
* Get the current accumulated displacement from the anchor in meters.
|
|
2342
|
+
* Returns { dx: 0, dy: 0 } if no anchor is set or no movement has occurred.
|
|
2343
|
+
*/
|
|
2344
|
+
get displacement(): Readonly<DisplacementVector>;
|
|
1957
2345
|
/**
|
|
1958
2346
|
* Get the Model for the BlueDot core element.
|
|
1959
2347
|
*/
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{a as t,b as e,c as s,d as n}from"./chunk-BRRC7V4T.js";import{m as o}from"./chunk-UVQMTLHL.js";o();export{t as BaseSensor,n as BlueDot,e as ManualSensor,s as SensorRegistry};
|