@rr0/ufoathome 0.22.0 → 0.22.1

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.
@@ -5,6 +5,10 @@ const _f=`
5
5
  <label><span id="label-import-file">Load JSON file</span> <input id="import-file" type="file" accept="application/json,.json"/></label>
6
6
  <label><span id="label-import-url">Or load from URL</span> <input id="import-url" type="url" placeholder="https://…/sighting.json"/></label>
7
7
  <button id="import-url-button" type="button">Load</button>
8
+ <!-- The case, not the witness: every witness's own recording of the same sighting carries the
9
+ same caseId, which is exactly what lets a page group them (see Sighting.caseId). Putting it
10
+ beside a witness's name suggested it was theirs. -->
11
+ <label><span id="label-case-id">Case ID</span> <input id="caseId" type="text"/></label>
8
12
  <label><span id="label-description">Description</span> <textarea id="description" rows="2"></textarea></label>
9
13
  <label><span id="label-tags">Tags</span> <input id="tags" type="text" placeholder="comma-separated"/></label>
10
14
  </div>
@@ -17,7 +21,6 @@ const _f=`
17
21
  <label><span id="label-witness-title">Witness title</span> <input id="witnessTitle" type="text"/></label>
18
22
  <label><span id="label-witness-last-name">Witness last name</span> <input id="witnessLastName" type="text"/></label>
19
23
  <label><span id="label-witness-first-names">Witness first names</span> <input id="witnessFirstNames" type="text" placeholder="comma-separated"/></label>
20
- <label><span id="label-case-id">Case ID</span> <input id="caseId" type="text"/></label>
21
24
  <label><span id="label-instrument">Observed through</span> <select id="instrument"></select></label>
22
25
  <label><span id="label-camera-device">Camera/video device</span> <input id="cameraDevice" type="range" min="0" max="2" step="0.1" value="0"/></label>
23
26
  <button id="add-decor-witness" type="button">Add witness</button>
@@ -5397,4 +5397,4 @@ void main() {
5397
5397
  gl_FragColor = vec4(color, tex.a * uOpacity * (1.0 - blur * 0.5));
5398
5398
  }
5399
5399
  `;let ea;function tM(){if(ea)return ea;const i=128,e=document.createElement("canvas");e.width=i,e.height=i;const t=e.getContext("2d"),n=t.createRadialGradient(i/2,i/2,0,i/2,i/2,i/2);return n.addColorStop(0,"rgba(255,255,255,1)"),n.addColorStop(.4,"rgba(255,255,255,0.35)"),n.addColorStop(1,"rgba(255,255,255,0)"),t.fillStyle=n,t.fillRect(0,0,i,i),ea=new Xn(e),ea}function nM(i){const t=document.createElement("canvas");t.width=128,t.height=128;const n=t.getContext("2d"),s=128/2-2,r=128/2,a=128/2,o="#2e2b26",l="#f4f1e2";n.fillStyle=o,n.beginPath(),n.arc(r,a,s,0,Math.PI*2),n.fill();const c=g0(i.illuminatedFraction,0,1),h=i.phaseFraction<.5,d=s*Math.abs(1-2*c),u=c<.5;return n.save(),n.beginPath(),n.arc(r,a,s,0,Math.PI*2),n.clip(),n.fillStyle=l,n.beginPath(),h?(n.arc(r,a,s,-Math.PI/2,Math.PI/2,!1),n.ellipse(r,a,d,s,0,Math.PI/2,-Math.PI/2,u)):(n.arc(r,a,s,Math.PI/2,-Math.PI/2,!1),n.ellipse(r,a,d,s,0,-Math.PI/2,Math.PI/2,u)),n.fill(),n.restore(),new Xn(t)}function iM(i){const e=document.createElement("canvas");e.width=128,e.height=128;const t=e.getContext("2d");return t.fillStyle="rgba(0, 0, 0, 0.55)",t.beginPath(),t.arc(64,64,60,0,Math.PI*2),t.fill(),t.fillStyle="#ffffff",t.font="bold 52px sans-serif",t.textAlign="center",t.textBaseline="middle",t.fillText(i,64,68),new Xn(e)}function Oo(i){let e=i;return function(){e|=0,e=e+1831565813|0;let n=Math.imul(e^e>>>15,1|e);return n=n+Math.imul(n^n>>>7,61|n)^n,((n^n>>>14)>>>0)/4294967296}}const Vu=new Map;function sM(i){const e=i.byteLength/(4*Float32Array.BYTES_PER_ELEMENT),t=e,n=t*Float32Array.BYTES_PER_ELEMENT;return{count:e,ra:new Float32Array(i,0*n,t),dec:new Float32Array(i,1*n,t),mag:new Float32Array(i,2*n,t),ci:new Float32Array(i,3*n,t)}}function rM(i){let e=Vu.get(i);return e||(e=fetch(i).then(t=>t.arrayBuffer()).then(sM),Vu.set(i,e)),e}const aM=new URL(""+new URL("rain-BvWZrB9h.ogg",import.meta.url).href,import.meta.url).href,oM=new URL(""+new URL("wind-BjklexY7.ogg",import.meta.url).href,import.meta.url).href,lM=new URL(""+new URL("thunder-DA48qs_v.wav",import.meta.url).href,import.meta.url).href,cM=20,hM=1;class uM{context;buffers=new Map;ambientSource;ambientGain;ambientKey="none";ambientToken=0;ambientVolume=0;windSource;windGain;windActive=!1;windToken=0;windVolume=0;paused=!0;requested={type:"none",intensity:0,windSpeed:0};resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(e){console.warn("WeatherAudio: Web Audio unavailable, weather sounds disabled:",e);return}}this.context.state==="suspended"&&this.context.resume()}setAmbient(e,t,n){if(this.requested={type:e,intensity:t,windSpeed:n},!this.context)return;this.paused&&(e="none",t=0,n=0);const s=e==="rain"||e==="hail"?e:"none";if(this.ambientVolume=s==="hail"?Math.min(1,t*1.3+.2):s==="rain"?t:0,s!==this.ambientKey){this.ambientKey=s;const a=++this.ambientToken;this.stopSource(this.ambientSource,this.ambientGain),this.ambientSource=void 0,this.ambientGain=void 0,s!=="none"&&this.startLoop(aM,this.ambientVolume).then(o=>this.applyIfCurrent(o,a,()=>this.ambientToken,l=>{this.ambientSource=l?.source,this.ambientGain=l?.gain,l&&(l.gain.gain.value=this.ambientVolume)}))}else this.ambientGain&&(this.ambientGain.gain.value=this.ambientVolume);this.windVolume=Math.min(n/cM,1);const r=n>hM;if(r!==this.windActive){this.windActive=r;const a=++this.windToken;this.stopSource(this.windSource,this.windGain),this.windSource=void 0,this.windGain=void 0,r&&this.startLoop(oM,this.windVolume).then(o=>this.applyIfCurrent(o,a,()=>this.windToken,l=>{this.windSource=l?.source,this.windGain=l?.gain,l&&(l.gain.gain.value=this.windVolume)}))}else this.windGain&&(this.windGain.gain.value=this.windVolume)}setPaused(e){if(e===this.paused)return;this.paused=e;const{type:t,intensity:n,windSpeed:s}=this.requested;this.setAmbient(t,n,s)}playThunder(){!this.context||this.paused||this.playOneShot(lM,.9)}dispose(){this.ambientToken++,this.windToken++,this.stopSource(this.ambientSource,this.ambientGain),this.stopSource(this.windSource,this.windGain),this.ambientSource=void 0,this.ambientGain=void 0,this.windSource=void 0,this.windGain=void 0,this.context?.close(),this.context=void 0,this.buffers.clear()}applyIfCurrent(e,t,n,s){if(t!==n()){e?.source.stop();return}s(e)}async startLoop(e,t){const n=this.context;if(n)try{const s=await this.getBuffer(e),r=n.createBufferSource();r.buffer=s,r.loop=!0;const a=n.createGain();return a.gain.value=t,r.connect(a).connect(n.destination),r.start(),{source:r,gain:a}}catch(s){console.warn("Weather ambient sound failed to load, staying silent:",s);return}}async playOneShot(e,t){const n=this.context;if(n)try{const s=await this.getBuffer(e),r=n.createBufferSource();r.buffer=s;const a=n.createGain();a.gain.value=t,r.connect(a).connect(n.destination),r.start()}catch(s){console.warn("Thunder sound failed to load:",s)}}async getBuffer(e){const t=this.context;if(!t)throw new Error("WeatherAudio: AudioContext not ready — resume() must be called first");let n=this.buffers.get(e);return n||(n=fetch(e).then(s=>{if(!s.ok)throw new Error(`Audio fetch failed (${s.status}): ${e}`);return s.arrayBuffer()}).then(s=>t.decodeAudioData(s)),this.buffers.set(e,n)),n}stopSource(e,t){try{e?.stop()}catch{}e?.disconnect(),t?.disconnect()}}class dM{lowerM;upperM;add(e,t){if(!(e<=0)){if(t.behindM!==void 0){const n=Vt.sizeMAt(t.behindM,e);this.lowerM=this.lowerM===void 0?n:Math.max(this.lowerM,n)}if(t.inFrontM!==void 0){const n=Vt.sizeMAt(t.inFrontM,e);this.upperM=this.upperM===void 0?n:Math.min(this.upperM,n)}}}get sizeRange(){return{minM:this.lowerM,maxM:this.upperM}}get empty(){return this.lowerM===void 0&&this.upperM===void 0}get contradictory(){return this.lowerM!==void 0&&this.upperM!==void 0&&this.lowerM>this.upperM}distanceRangeAt(e){return e<=0?{}:{minM:this.lowerM===void 0?void 0:Vt.distanceMAt(this.lowerM,e),maxM:this.upperM===void 0?void 0:Vt.distanceMAt(this.upperM,e)}}clear(){this.lowerM=void 0,this.upperM=void 0}}Ku();const fM={sun:{en:"Sun",fr:"Soleil"},moon:{en:"Moon",fr:"Lune"},Venus:{en:"Venus",fr:"Vénus"},Mars:{en:"Mars",fr:"Mars"},Jupiter:{en:"Jupiter",fr:"Jupiter"},Saturn:{en:"Saturn",fr:"Saturne"}},pM=["en","fr"],mM={building:{en:"Building",fr:"Bâtiment"},tree:{en:"Tree",fr:"Arbre"},streetlight:{en:"Streetlight",fr:"Lampadaire"},vehicle:{en:"Vehicle",fr:"Véhicule"},witness:{en:"Witness",fr:"Témoin"},aircraft:{en:"Aircraft",fr:"Aéronef"}},gM=new URL(""+new URL("stars-mag7.5-DDr9QasD.bin",import.meta.url).href,import.meta.url).href,_M={sun:{altitudeDeg:-3,azimuthDeg:180,magnitude:-26.7},moon:{altitudeDeg:-90,azimuthDeg:0,phase:{phaseFraction:0,illuminatedFraction:0},magnitude:-12.7},planets:[]},Bo={lat:0,lng:0,elevationM:0,headingDeg:void 0,pitchDeg:0,fovDeg:60};class vM extends HTMLElement{static get observedAttributes(){return["src","star-catalog-src","show-compass","lens-flare-intensity","lens-flare-brightness"]}shadow;stageElement;frameElement;sceneCanvas;ufoElement;sceneRenderer;hoverTooltip;resizeObserver;sizeEstimates=new Map;sizeEstimatesFor;lastTimeMs=0;starCatalog;weatherAudio=new uM;thunderTimeoutId;handleFullscreenChange=()=>this.resizeToStage();handlePointerMove=e=>{this.sceneRenderer.setCompassHovered(!0);const t=this.ufoElement.canvasElement,n=t.getBoundingClientRect();if(n.width===0||n.height===0)return;const s=(e.clientX-n.left)/n.width*t.width,r=(e.clientY-n.top)/n.height*t.height;if(this.ufoElement.hasVisibleShapeAt(s,r)){this.hoverTooltip.hidden=!0;return}const a=(e.clientX-n.left)/n.width*2-1,o=-((e.clientY-n.top)/n.height*2-1),l=Ta(navigator.languages,pM),c=this.sceneRenderer.pickBodyAt(a,o);if(c){this.showHoverTooltip(e,fM[c]?.[l]??c);return}const h=this.sceneRenderer.pickDecorAt(a,o),d=h?this.ufoElement.sighting.decor.find(u=>u.id===h):void 0;if(d){this.showHoverTooltip(e,d.title||mM[d.kind][l]);return}this.hoverTooltip.hidden=!0};showHoverTooltip(e,t){this.hoverTooltip.textContent=t,this.hoverTooltip.hidden=!1;const n=this.stageElement.getBoundingClientRect();this.hoverTooltip.style.left=`${e.clientX-n.left+12}px`,this.hoverTooltip.style.top=`${e.clientY-n.top+12}px`}handlePointerLeave=()=>{this.hoverTooltip.hidden=!0,this.sceneRenderer.setCompassHovered(!1)};handleLightningFlash=()=>{clearTimeout(this.thunderTimeoutId);const e=(.5+Math.random()*3.5)*1e3;this.thunderTimeoutId=window.setTimeout(()=>this.weatherAudio.playThunder(),e)};handleFirstInteraction=()=>{this.weatherAudio.resume(),this.setWeather(Gc(this.ufoElement.sighting,this.lastTimeMs))};handleTimeUpdate=e=>{this.lastTimeMs=e.detail.time,this.syncAnimationsToPlayback(),this.updateAstronomy(this.lastTimeMs),this.updateUfoOcclusion(this.lastTimeMs)};syncAnimationsToPlayback(){const e=this.ufoElement.playbackState==="playing";this.sceneRenderer.setAnimationsRunning(e),this.weatherAudio.setPaused(!e),e||clearTimeout(this.thunderTimeoutId)}constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${C0}</style>${R0}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.stageElement=this.shadow.getElementById("stage"),this.frameElement=this.shadow.getElementById("frame"),this.sceneCanvas=this.shadow.getElementById("scene-canvas"),this.sceneRenderer=new q3(this.sceneCanvas,void 0,this.handleLightningFlash),this.hoverTooltip=this.shadow.getElementById("hover-tooltip"),this.ufoElement=document.createElement(Ho),this.ufoElement.classList.add("ufo-overlay"),this.ufoElement.style.setProperty("--ufo-canvas-background","transparent"),this.ufoElement.style.setProperty("--ufo-canvas-border","none"),this.ufoElement.fullscreenTarget=this.stageElement,this.shadow.getElementById("ufo-slot").replaceWith(this.ufoElement),this.ufoElement.addEventListener("timeupdate",this.handleTimeUpdate),this.ufoElement.canvasElement.addEventListener("pointermove",this.handlePointerMove),this.ufoElement.canvasElement.addEventListener("pointerleave",this.handlePointerLeave),this.ufoElement.canvasElement.addEventListener("pointerdown",this.handleFirstInteraction,{once:!0})}connectedCallback(){this.resizeToStage(),this.updateAstronomy(this.lastTimeMs),this.loadStars(),this.resizeObserver=new ResizeObserver(()=>this.resizeToStage()),this.resizeObserver.observe(this.frameElement),document.addEventListener("fullscreenchange",this.handleFullscreenChange);const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){this.resizeObserver?.disconnect(),document.removeEventListener("fullscreenchange",this.handleFullscreenChange),this.sceneRenderer.stopTwinkle(),clearTimeout(this.thunderTimeoutId),this.weatherAudio.dispose()}attributeChangedCallback(e,t,n){if(e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n),e==="star-catalog-src"&&n!==t&&this.isConnected&&this.loadStars(),e==="show-compass"&&n!==t&&this.sceneRenderer.setShowCompass(this.hasAttribute("show-compass")),e==="lens-flare-intensity"&&n!==t){const s=n===null?NaN:parseFloat(n);this.sceneRenderer.setLensFlareArtifactIntensity(Number.isFinite(s)?s:0)}if(e==="lens-flare-brightness"&&n!==t){const s=n===null?NaN:parseFloat(n);this.sceneRenderer.setDazzleIntensity(Number.isFinite(s)?s:1)}}setCompassForced(e){this.sceneRenderer.setCompassForced(e)}setIndoorLook(e,t){this.sceneRenderer.setIndoorLook(e,t)}setWeather(e){this.sceneRenderer.setWeather(e),this.weatherAudio.setAmbient(e.precipitationType,e.precipitationIntensity,e.windSpeed)}pickDecorAt(e,t){return this.sceneRenderer.pickDecorAt(e,t)}resumeWeatherAudio(){this.weatherAudio.resume()}async loadFromSrc(e){const t=await fetch(e);this.sightingData=await t.json()}get sightingData(){return this.ufoElement.sightingData}set sightingData(e){this.ufoElement.sightingData=e,this.lastTimeMs=0,this.updateAstronomy(0)}get currentTerrainAttribution(){return this.sceneRenderer.currentTerrainAttribution}setTerrainProviders(e){this.sceneRenderer.setTerrainProviders(e)}resizeToStage(){const e=this.frameElement.getBoundingClientRect(),t=Math.max(1,Math.round(e.width)),n=Math.max(1,Math.round(e.height));this.sceneCanvas.width=t,this.sceneCanvas.height=n,this.sceneRenderer.resize(t,n)}async loadStars(){const e=this.getAttribute("star-catalog-src")??gM;this.starCatalog=await rM(e),this.updateAstronomy(this.lastTimeMs)}updateAstronomy(e){const t=this.ufoElement.sighting;this.setWeather(Gc(t,e)),this.sceneRenderer.setProjection(t.instrument.projection),this.sceneRenderer.setDecor(t.decor);const n=Ys(t,e);this.sceneRenderer.setObserverPose(n??Bo),this.sceneRenderer.updateDecorAnchoring(Ys(t,0),n,e),this.sceneRenderer.updateDecorLitState(e),this.sceneRenderer.setTerrainOrigin(n?.lat,n?.lng);const s=n?.lat??Bo.lat,r=n?.lng??Bo.lng,a=e0(t.event.time??{},r,t.event.utcOffsetHours);if(!a){this.sceneRenderer.setAstronomy(_M);return}const o=new Date(a.getTime()+e),l={lat:s,lng:r,elevationM:n?.elevationM??0},c={...bo("Sun",o,l),magnitude:Eo("Sun",o)},h={...bo("Moon",o,l),phase:Qx(o),magnitude:Eo("Moon",o)},d=Kx.map(u=>({body:u,position:bo(u,o,l),magnitude:Eo(u,o)}));this.sceneRenderer.setAstronomy({sun:c,moon:h,planets:d,stars:this.starCatalog?{catalog:this.starCatalog,date:o,observer:l}:void 0})}updateUfoOcclusion(e){const t=this.ufoElement.sighting;t!==this.sizeEstimatesFor&&(this.sizeEstimates.clear(),this.sizeEstimatesFor=t);const n=t.timeline,s=this.ufoElement.canvasElement,r=new Set;for(const a of n.sourceIds){const o=n.getInterpolatedShapeAt(e,a);if(!o)continue;const l=(o.bounds.x+o.bounds.width/2)/s.width*2-1,c=-((o.bounds.y+o.bounds.height/2)/s.height*2-1);this.sceneRenderer.isScreenPointOccluded(l,c,a,o.behindCloud)&&r.add(a);const h=o.angular?.widthDeg??this.projectionAt(e).pxToDeg(o.bounds.width);this.sizeEstimateOf(a).add(h,this.sceneRenderer.decorDistancesAt(l,c,a))}this.ufoElement.setOccludedSourceIds(r)}sizeRangeOf(e){return this.sizeEstimateOf(e).sizeRange}distanceRangeAt(e,t){const n=this.ufoElement.sighting.timeline.getInterpolatedShapeAt(t,e);if(!n)return{};const s=n.angular?.widthDeg??this.projectionAt(t).pxToDeg(n.bounds.width);return this.sizeEstimateOf(e).distanceRangeAt(s)}sizeContradictory(e){return this.sizeEstimateOf(e).contradictory}projectionAt(e){const t=this.ufoElement.sighting,n=Ys(t,e)?.fovDeg??ac.DEFAULT_FOV_DEG;return hs.of(t.instrument,Vt.CANVAS_HEIGHT_PX,n)}sizeEstimateOf(e){let t=this.sizeEstimates.get(e);return t||(t=new dM,this.sizeEstimates.set(e,t)),t}}const rc="rr0-scene";function _0(){Ku(),customElements.get(rc)||customElements.define(rc,vM)}const v0={testimonyBy:"Testimony by",about:"About",close:"Close",observation:"Observation",date:"Date",location:"Location",case:"Case",description:"Description",tags:"Tags",credits:"Credits",editThisObservation:"Edit this observation",embed:"Embed",embedReplay:"Replay",embedEdit:"Editor",embedCopy:"Copy",embedCopied:"Copied"},xM=Object.freeze(Object.defineProperty({__proto__:null,eyewitnessMessages_en:v0},Symbol.toStringTag,{value:"Module"}));_0();const MM="“Thunder” by Jerimee",SM="https://creativecommons.org/licenses/by/3.0/",yM="CC BY 3.0",zo="https://ufoathome.org";class bM extends HTMLElement{static get observedAttributes(){return["src"]}shadow;sceneElement;toolbarElement;testimonyPrefix;witnessText;witnessSelect;infoButton;infoPanel;infoAppLink;infoObservationHeading;infoObservationList;infoCreditsToggle;infoCreditsList;infoCloseButton;infoEmbedToggle;infoEmbedPanel;embedReplayRadio;embedEditRadio;labelEmbedReplay;labelEmbedEdit;embedMarkup;embedCopyButton;supportsPopover=typeof HTMLElement.prototype.showPopover=="function";entries=[];currentSrc;infoOpen=!1;creditsOpen=!1;embedOpen=!1;language="en";messages=v0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"});const e=document.createElement("template");e.innerHTML=`<style>${A0}</style>${T0}`,this.shadow.appendChild(e.content.cloneNode(!0)),this.sceneElement=document.createElement(rc),this.shadow.getElementById("ufo-slot").replaceWith(this.sceneElement),this.toolbarElement=this.shadow.getElementById("toolbar"),this.testimonyPrefix=this.shadow.getElementById("testimony-prefix"),this.witnessText=this.shadow.getElementById("witness-text"),this.witnessSelect=this.shadow.getElementById("witness"),this.infoButton=this.shadow.getElementById("info-button"),this.infoPanel=this.shadow.getElementById("info-panel"),this.infoAppLink=this.shadow.getElementById("info-app-link"),this.infoObservationHeading=this.shadow.getElementById("info-observation-heading"),this.infoObservationList=this.shadow.getElementById("info-observation-list"),this.infoCreditsToggle=this.shadow.getElementById("info-credits-toggle"),this.infoCreditsList=this.shadow.getElementById("info-credits-list"),this.infoCloseButton=this.shadow.getElementById("info-close"),this.infoEmbedToggle=this.shadow.getElementById("info-embed-toggle"),this.infoEmbedPanel=this.shadow.getElementById("info-embed"),this.embedReplayRadio=this.shadow.getElementById("embed-kind-replay"),this.embedEditRadio=this.shadow.getElementById("embed-kind-edit"),this.labelEmbedReplay=this.shadow.getElementById("label-embed-replay"),this.labelEmbedEdit=this.shadow.getElementById("label-embed-edit"),this.embedMarkup=this.shadow.getElementById("embed-markup"),this.embedCopyButton=this.shadow.getElementById("embed-copy"),this.witnessSelect.addEventListener("change",()=>this.selectWitness(this.witnessSelect.value)),this.supportsPopover?(this.infoPanel.setAttribute("popover","auto"),this.infoPanel.removeAttribute("hidden"),this.infoButton.setAttribute("popovertarget","info-panel"),this.infoPanel.addEventListener("beforetoggle",t=>{t.newState==="open"&&this.populateInfoPanel()}),this.infoPanel.addEventListener("toggle",t=>this.syncInfoOpen(t.newState==="open"))):this.infoButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCloseButton.addEventListener("click",()=>this.toggleInfoPanel()),this.infoCreditsToggle.addEventListener("click",()=>this.toggleCredits()),this.infoEmbedToggle.addEventListener("click",()=>this.toggleEmbed());for(const t of[this.embedReplayRadio,this.embedEditRadio])t.addEventListener("change",()=>this.refreshEmbedMarkup());this.embedCopyButton.addEventListener("click",()=>void this.copyEmbedMarkup()),this.loadLocaleMessages()}async loadLocaleMessages(){this.language=Ta(navigator.languages,$u),this.language!=="en"&&(this.messages=await gf(this.language),this.testimonyPrefix.textContent=this.messages.testimonyBy,this.infoButton.title=this.messages.about,this.infoButton.setAttribute("aria-label",this.messages.about),this.infoCloseButton.setAttribute("aria-label",this.messages.close),this.infoObservationHeading.textContent=this.messages.observation,this.infoCreditsToggle.textContent=this.messages.credits,this.infoEmbedToggle.textContent=this.messages.embed,this.labelEmbedReplay.textContent=this.messages.embedReplay,this.labelEmbedEdit.textContent=this.messages.embedEdit,this.embedCopyButton.textContent=this.messages.embedCopy,this.infoOpen&&this.populateInfoPanel(),this.updateTestimonyLine())}connectedCallback(){const e=this.getAttribute("src");e&&this.loadFromSrc(e)}disconnectedCallback(){document.removeEventListener("click",this.handleOutsideClick)}attributeChangedCallback(e,t,n){e==="src"&&n&&n!==t&&this.isConnected&&this.loadFromSrc(n)}async loadFromSrc(e){const n=await(await fetch(e)).json();Array.isArray(n)?await this.loadWitnessUrls(n):this.setEntries([{src:e,sighting:n}])}get witnessUrls(){return this.entries.map(e=>e.src)}set witnessUrls(e){this.loadWitnessUrls(e)}async loadWitnessUrls(e){const t=await Promise.all(e.map(async n=>{const s=await fetch(n);return{src:n,sighting:await s.json()}}));this.setEntries(t)}setEntries(e){this.entries=e,this.warnOnMismatchedCaseIds(e),this.toolbarElement.hidden=e.length===0;const t=e.length>1;this.witnessSelect.hidden=!t,this.witnessText.hidden=t,this.witnessSelect.innerHTML="";for(const s of e){const r=document.createElement("option");r.value=s.src,r.textContent=this.witnessDisplayName(s.sighting.witness)??s.src,this.witnessSelect.appendChild(r)}const n=e.find(s=>s.src===this.currentSrc)??e[0];n?this.selectWitness(n.src):this.updateTestimonyLine()}editorUrl(){if(!this.currentSrc)return zo;const e=new URL(this.currentSrc,location.href);return e.origin===location.origin?`${zo}${e.pathname}`:`${zo}/?sighting=${encodeURIComponent(e.href)}`}embedMarkupFor(e){const t=e==="edit"?"rr0-ufo-recorder":"rr0-eyewitness",n=new URL(`${t}.mjs`,import.meta.url).href,s=this.currentSrc?new URL(this.currentSrc,location.href).href:"";return`<script type="module" src="${n}"><\/script>
5400
- <${t} src="${s}"></${t}>`}refreshEmbedMarkup(){this.embedMarkup.value=this.embedMarkupFor(this.embedEditRadio.checked?"edit":"replay")}async copyEmbedMarkup(){try{await navigator.clipboard.writeText(this.embedMarkup.value),this.embedCopyButton.textContent=this.messages.embedCopied,window.setTimeout(()=>this.embedCopyButton.textContent=this.messages.embedCopy,1500)}catch{this.embedMarkup.select()}}warnOnMismatchedCaseIds(e){const t=new Set(e.map(n=>n.sighting.caseId).filter(n=>n!==void 0));t.size>1&&console.warn(`<rr0-eyewitness>: witnesses declare different case ids (${[...t].join(", ")}) — they may not belong to the same case.`)}selectWitness(e){const t=this.entries.find(n=>n.src===e);t&&(this.currentSrc=e,this.witnessSelect.value=e,this.sceneElement.sightingData=t.sighting,this.updateTestimonyLine(),this.infoOpen&&this.populateInfoPanel())}updateTestimonyLine(){const e=this.entries.find(t=>t.src===this.currentSrc);e&&(this.witnessText.textContent=this.witnessDisplayName(e.sighting.witness)??e.src)}witnessDisplayName(e){if(!e)return;const t=[...e.firstNames??[],e.lastName].filter(Boolean).join(" ");return e.title||t||e.id||e.dirName}formatDate(e){const t=e.place?.[0],n=e0(e.time??{},t?.lng??0,e.utcOffsetHours);if(!n)return;const s=n.getTime()+this.utcOffsetHoursOf(e,t?.lng??0)*36e5;return new Intl.DateTimeFormat(this.language==="fr"?"fr-FR":"en-US",{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(s))}utcOffsetHoursOf(e,t){return e.utcOffsetHours??Math.round(t/15)}formatLocation(e){const t=e.place?.[0];if(t)return`${t.lat.toFixed(4)}, ${t.lng.toFixed(4)}`}toggleInfoPanel(){const e=!this.infoOpen;if(this.supportsPopover){const t=this.infoPanel.matches(":popover-open");e&&!t?this.infoPanel.showPopover():!e&&t&&this.infoPanel.hidePopover();return}this.syncInfoOpen(e),this.infoPanel.hidden=!e,e?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}syncInfoOpen(e){e!==this.infoOpen&&(this.infoOpen=e,this.infoButton.setAttribute("aria-expanded",String(e)),e?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false"),this.embedOpen=!1,this.infoEmbedPanel.hidden=!0,this.infoEmbedToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=e=>{const t=e.composedPath();!t.includes(this.infoPanel)&&!t.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}toggleEmbed(){this.embedOpen=!this.embedOpen,this.infoEmbedPanel.hidden=!this.embedOpen,this.infoEmbedToggle.setAttribute("aria-expanded",String(this.embedOpen)),this.embedOpen&&(this.refreshEmbedMarkup(),this.revealInPanel(this.infoEmbedPanel))}revealInPanel(e){e.scrollIntoView?.({block:"nearest"})}populateInfoPanel(){const e=this.entries.find(r=>r.src===this.currentSrc);if(this.infoObservationList.innerHTML="",e){const r=this.formatDate(e.sighting);r&&this.appendInfoRow(this.infoObservationList,this.messages.date,r);const a=this.formatLocation(e.sighting);a&&this.appendInfoRow(this.infoObservationList,this.messages.location,a),e.sighting.caseId&&this.appendInfoRow(this.infoObservationList,this.messages.case,e.sighting.caseId),e.sighting.description&&this.appendInfoRow(this.infoObservationList,this.messages.description,e.sighting.description),e.sighting.tags&&e.sighting.tags.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,e.sighting.tags.join(", "))}this.refreshEmbedMarkup(),this.infoAppLink.href=this.editorUrl(),this.infoAppLink.textContent="UFO@home v0.22.0",this.infoAppLink.title=this.messages.editThisObservation,this.infoAppLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCreditsList.innerHTML="";const t=this.sceneElement.currentTerrainAttribution;if(t){const r=document.createElement("li");r.textContent=t,this.infoCreditsList.appendChild(r)}const n=document.createElement("li");n.textContent=`${MM} (`;const s=document.createElement("a");s.href=SM,s.target="_blank",s.rel="noopener",s.textContent=yM,n.appendChild(s),n.appendChild(document.createTextNode(")")),this.infoCreditsList.appendChild(n)}appendInfoRow(e,t,n){const s=document.createElement("dt");s.textContent=t;const r=document.createElement("dd");r.textContent=n,e.appendChild(s),e.appendChild(r)}}const Wu="rr0-eyewitness";function EM(){_0(),customElements.get(Wu)||customElements.define(Wu,bM)}EM();
5400
+ <${t} src="${s}"></${t}>`}refreshEmbedMarkup(){this.embedMarkup.value=this.embedMarkupFor(this.embedEditRadio.checked?"edit":"replay")}async copyEmbedMarkup(){try{await navigator.clipboard.writeText(this.embedMarkup.value),this.embedCopyButton.textContent=this.messages.embedCopied,window.setTimeout(()=>this.embedCopyButton.textContent=this.messages.embedCopy,1500)}catch{this.embedMarkup.select()}}warnOnMismatchedCaseIds(e){const t=new Set(e.map(n=>n.sighting.caseId).filter(n=>n!==void 0));t.size>1&&console.warn(`<rr0-eyewitness>: witnesses declare different case ids (${[...t].join(", ")}) — they may not belong to the same case.`)}selectWitness(e){const t=this.entries.find(n=>n.src===e);t&&(this.currentSrc=e,this.witnessSelect.value=e,this.sceneElement.sightingData=t.sighting,this.updateTestimonyLine(),this.infoOpen&&this.populateInfoPanel())}updateTestimonyLine(){const e=this.entries.find(t=>t.src===this.currentSrc);e&&(this.witnessText.textContent=this.witnessDisplayName(e.sighting.witness)??e.src)}witnessDisplayName(e){if(!e)return;const t=[...e.firstNames??[],e.lastName].filter(Boolean).join(" ");return e.title||t||e.id||e.dirName}formatDate(e){const t=e.place?.[0],n=e0(e.time??{},t?.lng??0,e.utcOffsetHours);if(!n)return;const s=n.getTime()+this.utcOffsetHoursOf(e,t?.lng??0)*36e5;return new Intl.DateTimeFormat(this.language==="fr"?"fr-FR":"en-US",{dateStyle:"long",timeStyle:"short",timeZone:"UTC"}).format(new Date(s))}utcOffsetHoursOf(e,t){return e.utcOffsetHours??Math.round(t/15)}formatLocation(e){const t=e.place?.[0];if(t)return`${t.lat.toFixed(4)}, ${t.lng.toFixed(4)}`}toggleInfoPanel(){const e=!this.infoOpen;if(this.supportsPopover){const t=this.infoPanel.matches(":popover-open");e&&!t?this.infoPanel.showPopover():!e&&t&&this.infoPanel.hidePopover();return}this.syncInfoOpen(e),this.infoPanel.hidden=!e,e?document.addEventListener("click",this.handleOutsideClick):document.removeEventListener("click",this.handleOutsideClick)}syncInfoOpen(e){e!==this.infoOpen&&(this.infoOpen=e,this.infoButton.setAttribute("aria-expanded",String(e)),e?this.supportsPopover||this.populateInfoPanel():(this.creditsOpen=!1,this.infoCreditsList.hidden=!0,this.infoCreditsToggle.setAttribute("aria-expanded","false"),this.embedOpen=!1,this.infoEmbedPanel.hidden=!0,this.infoEmbedToggle.setAttribute("aria-expanded","false")))}handleOutsideClick=e=>{const t=e.composedPath();!t.includes(this.infoPanel)&&!t.includes(this.infoButton)&&this.toggleInfoPanel()};toggleCredits(){this.creditsOpen=!this.creditsOpen,this.infoCreditsList.hidden=!this.creditsOpen,this.infoCreditsToggle.setAttribute("aria-expanded",String(this.creditsOpen)),this.creditsOpen&&this.revealInPanel(this.infoCreditsList)}toggleEmbed(){this.embedOpen=!this.embedOpen,this.infoEmbedPanel.hidden=!this.embedOpen,this.infoEmbedToggle.setAttribute("aria-expanded",String(this.embedOpen)),this.embedOpen&&(this.refreshEmbedMarkup(),this.revealInPanel(this.infoEmbedPanel))}revealInPanel(e){e.scrollIntoView?.({block:"nearest"})}populateInfoPanel(){const e=this.entries.find(r=>r.src===this.currentSrc);if(this.infoObservationList.innerHTML="",e){const r=this.formatDate(e.sighting);r&&this.appendInfoRow(this.infoObservationList,this.messages.date,r);const a=this.formatLocation(e.sighting);a&&this.appendInfoRow(this.infoObservationList,this.messages.location,a),e.sighting.caseId&&this.appendInfoRow(this.infoObservationList,this.messages.case,e.sighting.caseId),e.sighting.description&&this.appendInfoRow(this.infoObservationList,this.messages.description,e.sighting.description),e.sighting.tags&&e.sighting.tags.length>0&&this.appendInfoRow(this.infoObservationList,this.messages.tags,e.sighting.tags.join(", "))}this.refreshEmbedMarkup(),this.infoAppLink.href=this.editorUrl(),this.infoAppLink.textContent="UFO@home v0.22.1",this.infoAppLink.title=this.messages.editThisObservation,this.infoAppLink.setAttribute("aria-label",this.messages.editThisObservation),this.infoCreditsList.innerHTML="";const t=this.sceneElement.currentTerrainAttribution;if(t){const r=document.createElement("li");r.textContent=t,this.infoCreditsList.appendChild(r)}const n=document.createElement("li");n.textContent=`${MM} (`;const s=document.createElement("a");s.href=SM,s.target="_blank",s.rel="noopener",s.textContent=yM,n.appendChild(s),n.appendChild(document.createTextNode(")")),this.infoCreditsList.appendChild(n)}appendInfoRow(e,t,n){const s=document.createElement("dt");s.textContent=t;const r=document.createElement("dd");r.textContent=n,e.appendChild(s),e.appendChild(r)}}const Wu="rr0-eyewitness";function EM(){_0(),customElements.get(Wu)||customElements.define(Wu,bM)}EM();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rr0/ufoathome",
3
3
  "type": "module",
4
- "version": "0.22.0",
4
+ "version": "0.22.1",
5
5
  "description": "UFO@home — record and replay a UFO sighting's shape, movement and appearance",
6
6
  "author": "Jérôme Beau <rr0@rr0.org> (https://rr0.org)",
7
7
  "license": "MIT",