@rr0/ufoathome 0.132.0 → 0.134.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/dist-embed-interview/InterviewMessages_es-BJHVnSkP.js +1 -0
- package/dist-embed-interview/InterviewMessages_fr-Dhtz904e.js +1 -0
- package/dist-embed-interview/InterviewMessages_it-D0Dff5zn.js +1 -0
- package/dist-embed-interview/rr0-interview.mjs +6 -6
- package/dist-embed-scene/rr0-scene.mjs +60 -58
- package/dist-embed-scene/sightingSchema-DfbuP60Y.js +1 -0
- package/dist-embed-sighting/{CoverageAssessor-CZfxbN9A.js → CoverageAssessor-Dd6oOWlq.js} +1 -1
- package/dist-embed-sighting/{SightingMessages_es-OXYzPf-m.js → SightingMessages_es-CxoccMw6.js} +1 -1
- package/dist-embed-sighting/SightingMessages_fr-CdqAz1Hz.js +1 -0
- package/dist-embed-sighting/{SightingMessages_it-B9f92W5s.js → SightingMessages_it-CkQVXDPv.js} +1 -1
- package/dist-embed-sighting/rr0-sighting.mjs +313 -254
- package/dist-embed-sighting/sightingSchema-DfbuP60Y.js +1 -0
- package/dist-embed-sighting-editor/{AdsbLolArchiveProvider-DOGYqP24.js → AdsbLolArchiveProvider-DU2U8NdB.js} +1 -1
- package/dist-embed-sighting-editor/{BeamEditor-rgFtq8yH.js → BeamEditor-CCsp2xr2.js} +1 -1
- package/dist-embed-sighting-editor/{BeamSystem-CGcP-5uL.js → BeamSystem-BnI9L86u.js} +1 -1
- package/dist-embed-sighting-editor/{BodyEditor-TjnivtCI.js → BodyEditor-DtBz9fVX.js} +2 -2
- package/dist-embed-sighting-editor/CaseEditorMessages_es-BrH54rIz.js +1 -0
- package/dist-embed-sighting-editor/CaseEditorMessages_fr-DF-qjRtx.js +1 -0
- package/dist-embed-sighting-editor/CaseEditorMessages_it-Cb_U9B3i.js +1 -0
- package/dist-embed-sighting-editor/{ContrailSystem-C7wqDUfk.js → ContrailSystem-DugiVtAv.js} +1 -1
- package/dist-embed-sighting-editor/{CoverageAssessor-BbvPELCG.js → CoverageAssessor-DXVjXoUX.js} +1 -1
- package/dist-embed-sighting-editor/GLTFLoader-DLQh4lKb.js +1 -0
- package/dist-embed-sighting-editor/{HeadlightSystem-Dyh8W52L.js → HeadlightSystem-BEWiubrn.js} +1 -1
- package/dist-embed-sighting-editor/{HynekAssessor-TsYamQ6r.js → HynekAssessor-Bc2SulU3.js} +1 -1
- package/dist-embed-sighting-editor/InterviewEditorElement-bUyn6irj.js +229 -0
- package/dist-embed-sighting-editor/InterviewMessages_en-CRvWVmlL.js +1 -0
- package/dist-embed-sighting-editor/InterviewMessages_es-BJHVnSkP.js +1 -0
- package/dist-embed-sighting-editor/InterviewMessages_fr-Dhtz904e.js +1 -0
- package/dist-embed-sighting-editor/InterviewMessages_it-D0Dff5zn.js +1 -0
- package/dist-embed-sighting-editor/{LaserBeam-BxHm8xkN.js → LaserBeam-B6u7y0-E.js} +1 -1
- package/dist-embed-sighting-editor/{LaunchEditor-DrBVJxSe.js → LaunchEditor-qoB8RSgQ.js} +1 -1
- package/dist-embed-sighting-editor/ModelSource-CnDfgMtY.js +1 -0
- package/dist-embed-sighting-editor/{ModelThumbnails-BXnPtOMG.js → ModelThumbnails-CYHW7hxV.js} +1 -1
- package/dist-embed-sighting-editor/{ModelViewer-CMxc0zPv.js → ModelViewer-BzHV3bjz.js} +1 -1
- package/dist-embed-sighting-editor/RailwaySystem-CzPTp4PW.js +41 -0
- package/dist-embed-sighting-editor/{RoadMarkings-BHKxo_8h.js → RoadMarkings-BWoz2Cuq.js} +1 -1
- package/dist-embed-sighting-editor/{SceneNames_es-BQyea_Xf.js → SceneNames_es-7RR79EmC.js} +1 -1
- package/dist-embed-sighting-editor/{SceneNames_fr-DKRWoM54.js → SceneNames_fr-Da_S9KXa.js} +1 -1
- package/dist-embed-sighting-editor/{SceneNames_it-BcASO5PP.js → SceneNames_it-BwFZROII.js} +1 -1
- package/dist-embed-sighting-editor/SightingEditorMessages_es-pgii85sY.js +12 -0
- package/dist-embed-sighting-editor/SightingEditorMessages_fr-BysKDyGf.js +12 -0
- package/dist-embed-sighting-editor/{SightingEditorMessages_it-BaBliW7B.js → SightingEditorMessages_it-DOnHDjjj.js} +2 -2
- package/dist-embed-sighting-editor/{SightingFileEditor-BoJcuWFQ.js → SightingFileEditor-LAzFduCJ.js} +18 -17
- package/dist-embed-sighting-editor/{TraceSystem-DMeO0tBV.js → TraceSystem-Dgxizn7s.js} +2 -2
- package/dist-embed-sighting-editor/{WaterSystem-BFrSxN_o.js → WaterSystem-Bv5uZSRK.js} +1 -1
- package/dist-embed-sighting-editor/interviewSchema-7rMvPyAl.js +1 -0
- package/dist-embed-sighting-editor/rr0-sighting-editor.mjs +1231 -552
- package/dist-embed-sighting-editor/sightingSchema-DfbuP60Y.js +1 -0
- package/dist-embed-sighting-editor/surroundingsSources-B1931yh4.js +1 -0
- package/dist-embed-sighting-editor/{trafficRuntime-DqMAn7zG.js → trafficRuntime-STzu7-Xp.js} +1 -1
- package/package.json +1 -1
- package/dist-embed-interview/InterviewMessages_es-CNKjrohj.js +0 -1
- package/dist-embed-interview/InterviewMessages_fr-BP99Pg7g.js +0 -1
- package/dist-embed-interview/InterviewMessages_it-DTIrw8wW.js +0 -1
- package/dist-embed-scene/sightingSchema-DZCs9lw3.js +0 -1
- package/dist-embed-sighting/SightingMessages_fr-ylqIoox7.js +0 -1
- package/dist-embed-sighting/sightingSchema-DZCs9lw3.js +0 -1
- package/dist-embed-sighting-editor/CaseEditorMessages_es-DwO2w2Vc.js +0 -1
- package/dist-embed-sighting-editor/CaseEditorMessages_fr-iFzha0wM.js +0 -1
- package/dist-embed-sighting-editor/CaseEditorMessages_it-CjdJSAvo.js +0 -1
- package/dist-embed-sighting-editor/GLTFLoader-DoH7iy3g.js +0 -1
- package/dist-embed-sighting-editor/InterviewEditorElement-BLlyEu8-.js +0 -100
- package/dist-embed-sighting-editor/InterviewMessages_en-yw5Qfw-6.js +0 -1
- package/dist-embed-sighting-editor/InterviewMessages_es-CNKjrohj.js +0 -1
- package/dist-embed-sighting-editor/InterviewMessages_fr-BP99Pg7g.js +0 -1
- package/dist-embed-sighting-editor/InterviewMessages_it-DTIrw8wW.js +0 -1
- package/dist-embed-sighting-editor/ModelSource-BUjV4b8R.js +0 -1
- package/dist-embed-sighting-editor/RailwaySystem-BEdXiuce.js +0 -41
- package/dist-embed-sighting-editor/SightingEditorMessages_es-D6t0QFbB.js +0 -12
- package/dist-embed-sighting-editor/SightingEditorMessages_fr-O5O1g-Ii.js +0 -12
- package/dist-embed-sighting-editor/interviewSchema-m_h5f8H0.js +0 -1
- package/dist-embed-sighting-editor/sightingSchema-DZCs9lw3.js +0 -1
- package/dist-embed-sighting-editor/surroundingsSources-DKH8MbhE.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{aJ as Le,aK as Q,aL as he,aM as Me,aN as v,aO as de,ad as b,ag as pe,ae as F,aP as w,aQ as U,aH as Se,aR as ye,a6 as be,aw as K,aS as we,a8 as C,aT as me,aU as Ne,aV as ge,aW as Ie,aX as Oe,ak as V,aY as Ce,aZ as Te,a_ as Fe,a$ as Pe,b0 as He,b1 as J,b2 as Re,b3 as Z,b4 as ke,b5 as De,az as Ge,b6 as X,b7 as ve,a1 as Ee,aF as Ue,aE as G,b8 as Ke,ai as Be,b9 as je,$ as Ve,ba as Xe,bb as ze,bc as qe,aA as We,X as z,a7 as Ye,ax as Qe,bd as Je,be as Ze,bf as $e,bg as en,bh as nn,bi as tn,bj as xe,ao as sn,bk as ne,bl as te,bm as se,bn as ie,bo as re,bp as rn,bq as on,a2 as an,a3 as cn}from"./rr0-sighting-editor.mjs";function oe(f,n){if(n===Le)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),f;if(n===Q||n===he){let e=f.getIndex();if(e===null){const r=[],a=f.getAttribute("position");if(a!==void 0){for(let o=0;o<a.count;o++)r.push(o);f.setIndex(r),e=f.getIndex()}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),f}const s=e.count-2,t=[];if(n===Q)for(let r=1;r<=s;r++)t.push(e.getX(0)),t.push(e.getX(r)),t.push(e.getX(r+1));else for(let r=0;r<s;r++)r%2===0?(t.push(e.getX(r)),t.push(e.getX(r+1)),t.push(e.getX(r+2))):(t.push(e.getX(r+2)),t.push(e.getX(r+1)),t.push(e.getX(r)));t.length/3!==s&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const i=f.clone();return i.setIndex(t),i.clearGroups(),i}else return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",n),f}class jn extends Me{constructor(n){super(n),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register(function(e){return new dn(e)}),this.register(function(e){return new pn(e)}),this.register(function(e){return new Ln(e)}),this.register(function(e){return new Mn(e)}),this.register(function(e){return new Sn(e)}),this.register(function(e){return new gn(e)}),this.register(function(e){return new Tn(e)}),this.register(function(e){return new Rn(e)}),this.register(function(e){return new En(e)}),this.register(function(e){return new hn(e)}),this.register(function(e){return new xn(e)}),this.register(function(e){return new mn(e)}),this.register(function(e){return new _n(e)}),this.register(function(e){return new An(e)}),this.register(function(e){return new ln(e)}),this.register(function(e){return new ae(e,g.EXT_MESHOPT_COMPRESSION)}),this.register(function(e){return new ae(e,g.KHR_MESHOPT_COMPRESSION)}),this.register(function(e){return new yn(e)})}load(n,e,s,t){const i=this;let r;if(this.resourcePath!=="")r=this.resourcePath;else if(this.path!==""){const c=v.extractUrlBase(n);r=v.resolveURL(c,this.path)}else r=v.extractUrlBase(n);this.manager.itemStart(n);const a=function(c){t?t(c):console.error(c),i.manager.itemError(n),i.manager.itemEnd(n)},o=new de(this.manager);o.setPath(this.path),o.setResponseType("arraybuffer"),o.setRequestHeader(this.requestHeader),o.setWithCredentials(this.withCredentials),o.load(n,function(c){try{i.parse(c,r,function(u){e(u),i.manager.itemEnd(n)},a)}catch(u){a(u)}},s,a)}setDRACOLoader(n){return this.dracoLoader=n,this}setKTX2Loader(n){return this.ktx2Loader=n,this}setMeshoptDecoder(n){return this.meshoptDecoder=n,this}register(n){return this.pluginCallbacks.indexOf(n)===-1&&this.pluginCallbacks.push(n),this}unregister(n){return this.pluginCallbacks.indexOf(n)!==-1&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(n),1),this}parse(n,e,s,t){let i;const r={},a={},o=new TextDecoder;if(typeof n=="string")i=JSON.parse(n);else if(n instanceof ArrayBuffer)if(o.decode(new Uint8Array(n,0,4))===Ae){try{r[g.KHR_BINARY_GLTF]=new bn(n)}catch(l){t&&t(l);return}i=JSON.parse(r[g.KHR_BINARY_GLTF].content)}else i=JSON.parse(o.decode(n));else i=n;if(i.asset===void 0||i.asset.version[0]<2){t&&t(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported."));return}const c=new Un(i,{path:e||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});c.fileLoader.setRequestHeader(this.requestHeader);for(let u=0;u<this.pluginCallbacks.length;u++){const l=this.pluginCallbacks[u](c);l.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),a[l.name]=l,r[l.name]=!0}if(i.extensionsUsed)for(let u=0;u<i.extensionsUsed.length;++u){const l=i.extensionsUsed[u],h=i.extensionsRequired||[];switch(l){case g.KHR_MATERIALS_UNLIT:r[l]=new fn;break;case g.KHR_DRACO_MESH_COMPRESSION:r[l]=new wn(i,this.dracoLoader);break;case g.KHR_TEXTURE_TRANSFORM:r[l]=new Nn;break;case g.KHR_MESH_QUANTIZATION:r[l]=new In;break;default:h.indexOf(l)>=0&&a[l]===void 0&&console.warn('THREE.GLTFLoader: Unknown extension "'+l+'".')}}c.setExtensions(r),c.setPlugins(a),c.parse(s,t)}parseAsync(n,e){const s=this;return new Promise(function(t,i){s.parse(n,e,t,i)})}}function un(){let f={};return{get:function(n){return f[n]},add:function(n,e){f[n]=e},remove:function(n){delete f[n]},removeAll:function(){f={}}}}function _(f,n,e){const s=f.json.materials[n];return s.extensions&&s.extensions[e]?s.extensions[e]:null}const g={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",KHR_MESHOPT_COMPRESSION:"KHR_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};class ln{constructor(n){this.parser=n,this.name=g.KHR_LIGHTS_PUNCTUAL,this.cache={refs:{},uses:{}}}_markDefs(){const n=this.parser,e=this.parser.json.nodes||[];for(let s=0,t=e.length;s<t;s++){const i=e[s];i.extensions&&i.extensions[this.name]&&i.extensions[this.name].light!==void 0&&n._addNodeRef(this.cache,i.extensions[this.name].light)}}_loadLight(n){const e=this.parser,s="light:"+n;let t=e.cache.get(s);if(t)return t;const i=e.json,o=((i.extensions&&i.extensions[this.name]||{}).lights||[])[n];let c;const u=new F(16777215);o.color!==void 0&&u.setRGB(o.color[0],o.color[1],o.color[2],w);const l=o.range!==void 0?o.range:0;switch(o.type){case"directional":c=new be(u),c.target.position.set(0,0,-1),c.add(c.target);break;case"point":c=new ye(u),c.distance=l;break;case"spot":c=new Se(u),c.distance=l,o.spot=o.spot||{},o.spot.innerConeAngle=o.spot.innerConeAngle!==void 0?o.spot.innerConeAngle:0,o.spot.outerConeAngle=o.spot.outerConeAngle!==void 0?o.spot.outerConeAngle:Math.PI/4,c.angle=o.spot.outerConeAngle,c.penumbra=1-o.spot.innerConeAngle/o.spot.outerConeAngle,c.target.position.set(0,0,-1),c.add(c.target);break;default:throw new Error("THREE.GLTFLoader: Unexpected light type: "+o.type)}return c.position.set(0,0,0),y(c,o),o.intensity!==void 0&&(c.intensity=o.intensity),c.name=e.createUniqueName(o.name||"light_"+n),t=Promise.resolve(c),e.cache.add(s,t),t}getDependency(n,e){if(n==="light")return this._loadLight(e)}createNodeAttachment(n){const e=this,s=this.parser,i=s.json.nodes[n],a=(i.extensions&&i.extensions[this.name]||{}).light;return a===void 0?null:this._loadLight(a).then(function(o){return s._getNodeRef(e.cache,a,o)})}}class fn{constructor(){this.name=g.KHR_MATERIALS_UNLIT}getMaterialType(){return G}extendParams(n,e,s){const t=[];n.color=new F(1,1,1),n.opacity=1;const i=e.pbrMetallicRoughness;if(i){if(Array.isArray(i.baseColorFactor)){const r=i.baseColorFactor;n.color.setRGB(r[0],r[1],r[2],w),n.opacity=r[3]}i.baseColorTexture!==void 0&&t.push(s.assignTexture(n,"map",i.baseColorTexture,U))}return Promise.all(t)}}class hn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_EMISSIVE_STRENGTH}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||s.emissiveStrength!==void 0&&(e.emissiveIntensity=s.emissiveStrength),Promise.resolve()}}class dn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_CLEARCOAT}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];if(s.clearcoatFactor!==void 0&&(e.clearcoat=s.clearcoatFactor),s.clearcoatTexture!==void 0&&t.push(this.parser.assignTexture(e,"clearcoatMap",s.clearcoatTexture)),s.clearcoatRoughnessFactor!==void 0&&(e.clearcoatRoughness=s.clearcoatRoughnessFactor),s.clearcoatRoughnessTexture!==void 0&&t.push(this.parser.assignTexture(e,"clearcoatRoughnessMap",s.clearcoatRoughnessTexture)),s.clearcoatNormalTexture!==void 0&&(t.push(this.parser.assignTexture(e,"clearcoatNormalMap",s.clearcoatNormalTexture)),s.clearcoatNormalTexture.scale!==void 0)){const i=s.clearcoatNormalTexture.scale;e.clearcoatNormalScale=new pe(i,i)}return Promise.all(t)}}class pn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_DISPERSION}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||(e.dispersion=s.dispersion!==void 0?s.dispersion:0),Promise.resolve()}}class mn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_IRIDESCENCE}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.iridescenceFactor!==void 0&&(e.iridescence=s.iridescenceFactor),s.iridescenceTexture!==void 0&&t.push(this.parser.assignTexture(e,"iridescenceMap",s.iridescenceTexture)),s.iridescenceIor!==void 0&&(e.iridescenceIOR=s.iridescenceIor),e.iridescenceThicknessRange===void 0&&(e.iridescenceThicknessRange=[100,400]),s.iridescenceThicknessMinimum!==void 0&&(e.iridescenceThicknessRange[0]=s.iridescenceThicknessMinimum),s.iridescenceThicknessMaximum!==void 0&&(e.iridescenceThicknessRange[1]=s.iridescenceThicknessMaximum),s.iridescenceThicknessTexture!==void 0&&t.push(this.parser.assignTexture(e,"iridescenceThicknessMap",s.iridescenceThicknessTexture)),Promise.all(t)}}class gn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_SHEEN}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];if(e.sheenColor=new F(0,0,0),e.sheenRoughness=0,e.sheen=1,s.sheenColorFactor!==void 0){const i=s.sheenColorFactor;e.sheenColor.setRGB(i[0],i[1],i[2],w)}return s.sheenRoughnessFactor!==void 0&&(e.sheenRoughness=s.sheenRoughnessFactor),s.sheenColorTexture!==void 0&&t.push(this.parser.assignTexture(e,"sheenColorMap",s.sheenColorTexture,U)),s.sheenRoughnessTexture!==void 0&&t.push(this.parser.assignTexture(e,"sheenRoughnessMap",s.sheenRoughnessTexture)),Promise.all(t)}}class Tn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_TRANSMISSION}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.transmissionFactor!==void 0&&(e.transmission=s.transmissionFactor),s.transmissionTexture!==void 0&&t.push(this.parser.assignTexture(e,"transmissionMap",s.transmissionTexture)),Promise.all(t)}}class Rn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_VOLUME}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];e.thickness=s.thicknessFactor!==void 0?s.thicknessFactor:0,s.thicknessTexture!==void 0&&t.push(this.parser.assignTexture(e,"thicknessMap",s.thicknessTexture)),e.attenuationDistance=s.attenuationDistance||1/0;const i=s.attenuationColor||[1,1,1];return e.attenuationColor=new F().setRGB(i[0],i[1],i[2],w),Promise.all(t)}}class En{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_IOR}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);return s===null||(e.ior=s.ior!==void 0?s.ior:1.5,e.ior===0&&(e.ior=1e3)),Promise.resolve()}}class xn{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_SPECULAR}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];e.specularIntensity=s.specularFactor!==void 0?s.specularFactor:1,s.specularTexture!==void 0&&t.push(this.parser.assignTexture(e,"specularIntensityMap",s.specularTexture));const i=s.specularColorFactor||[1,1,1];return e.specularColor=new F().setRGB(i[0],i[1],i[2],w),s.specularColorTexture!==void 0&&t.push(this.parser.assignTexture(e,"specularColorMap",s.specularColorTexture,U)),Promise.all(t)}}class An{constructor(n){this.parser=n,this.name=g.EXT_MATERIALS_BUMP}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return e.bumpScale=s.bumpFactor!==void 0?s.bumpFactor:1,s.bumpTexture!==void 0&&t.push(this.parser.assignTexture(e,"bumpMap",s.bumpTexture)),Promise.all(t)}}class _n{constructor(n){this.parser=n,this.name=g.KHR_MATERIALS_ANISOTROPY}getMaterialType(n){return _(this.parser,n,this.name)!==null?b:null}extendMaterialParams(n,e){const s=_(this.parser,n,this.name);if(s===null)return Promise.resolve();const t=[];return s.anisotropyStrength!==void 0&&(e.anisotropy=s.anisotropyStrength),s.anisotropyRotation!==void 0&&(e.anisotropyRotation=s.anisotropyRotation),s.anisotropyTexture!==void 0&&t.push(this.parser.assignTexture(e,"anisotropyMap",s.anisotropyTexture)),Promise.all(t)}}class Ln{constructor(n){this.parser=n,this.name=g.KHR_TEXTURE_BASISU}loadTexture(n){const e=this.parser,s=e.json,t=s.textures[n];if(!t.extensions||!t.extensions[this.name])return null;const i=t.extensions[this.name],r=e.options.ktx2Loader;if(!r){if(s.extensionsRequired&&s.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures");return null}return e.loadTextureImage(n,i.source,r)}}class Mn{constructor(n){this.parser=n,this.name=g.EXT_TEXTURE_WEBP}loadTexture(n){const e=this.name,s=this.parser,t=s.json,i=t.textures[n];if(!i.extensions||!i.extensions[e])return null;const r=i.extensions[e],a=t.images[r.source];let o=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(n,r.source,o)}}class Sn{constructor(n){this.parser=n,this.name=g.EXT_TEXTURE_AVIF}loadTexture(n){const e=this.name,s=this.parser,t=s.json,i=t.textures[n];if(!i.extensions||!i.extensions[e])return null;const r=i.extensions[e],a=t.images[r.source];let o=s.textureLoader;if(a.uri){const c=s.options.manager.getHandler(a.uri);c!==null&&(o=c)}return s.loadTextureImage(n,r.source,o)}}class ae{constructor(n,e){this.name=e,this.parser=n}loadBufferView(n){const e=this.parser.json,s=e.bufferViews[n];if(s.extensions&&s.extensions[this.name]){const t=s.extensions[this.name],i=this.parser.getDependency("buffer",t.buffer),r=this.parser.options.meshoptDecoder;if(!r||!r.supported){if(e.extensionsRequired&&e.extensionsRequired.indexOf(this.name)>=0)throw new Error("THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files");return null}return i.then(function(a){const o=t.byteOffset||0,c=t.byteLength||0,u=t.count,l=t.byteStride,h=new Uint8Array(a,o,c);return r.decodeGltfBufferAsync?r.decodeGltfBufferAsync(u,l,h,t.mode,t.filter).then(function(d){return d.buffer}):r.ready.then(function(){const d=new ArrayBuffer(u*l);return r.decodeGltfBuffer(new Uint8Array(d),u,l,h,t.mode,t.filter),d})})}else return null}}class yn{constructor(n){this.name=g.EXT_MESH_GPU_INSTANCING,this.parser=n}createNodeMesh(n){const e=this.parser.json,s=e.nodes[n];if(!s.extensions||!s.extensions[this.name]||s.mesh===void 0)return null;const t=e.meshes[s.mesh];for(const c of t.primitives)if(c.mode!==M.TRIANGLES&&c.mode!==M.TRIANGLE_STRIP&&c.mode!==M.TRIANGLE_FAN&&c.mode!==void 0)return null;const r=s.extensions[this.name].attributes,a=[],o={};for(const c in r)a.push(this.parser.getDependency("accessor",r[c]).then(u=>(o[c]=u,o[c])));return a.length<1?null:(a.push(this.parser.createNodeMesh(n)),Promise.all(a).then(c=>{const u=c.pop(),l=u.isGroup?u.children:[u],h=c[0].count,d=[];for(const p of l){const R=new K,m=new C,T=new me,A=new C(1,1,1),x=new we(p.geometry,p.material,h);for(let E=0;E<h;E++)o.TRANSLATION&&m.fromBufferAttribute(o.TRANSLATION,E),o.ROTATION&&T.fromBufferAttribute(o.ROTATION,E),o.SCALE&&A.fromBufferAttribute(o.SCALE,E),x.setMatrixAt(E,R.compose(m,T,A));for(const E in o)if(E==="_COLOR_0"){const L=o[E];x.instanceColor=new Ne(L.array,L.itemSize,L.normalized)}else E!=="TRANSLATION"&&E!=="ROTATION"&&E!=="SCALE"&&p.geometry.setAttribute(E,o[E]);ge.prototype.copy.call(x,p),this.parser.assignFinalMaterial(x),d.push(x)}return u.isGroup?(u.clear(),u.add(...d),u):d[0]}))}}const Ae="glTF",D=12,ce={JSON:1313821514,BIN:5130562};class bn{constructor(n){this.name=g.KHR_BINARY_GLTF,this.content=null,this.body=null;const e=new DataView(n,0,D),s=new TextDecoder;if(this.header={magic:s.decode(new Uint8Array(n.slice(0,4))),version:e.getUint32(4,!0),length:e.getUint32(8,!0)},this.header.magic!==Ae)throw new Error("THREE.GLTFLoader: Unsupported glTF-Binary header.");if(this.header.version<2)throw new Error("THREE.GLTFLoader: Legacy binary file detected.");const t=this.header.length-D,i=new DataView(n,D);let r=0;for(;r<t;){const a=i.getUint32(r,!0);r+=4;const o=i.getUint32(r,!0);if(r+=4,o===ce.JSON){const c=new Uint8Array(n,D+r,a);this.content=s.decode(c)}else if(o===ce.BIN){const c=D+r;this.body=n.slice(c,c+a)}r+=a}if(this.content===null)throw new Error("THREE.GLTFLoader: JSON content not found.")}}class wn{constructor(n,e){if(!e)throw new Error("THREE.GLTFLoader: No DRACOLoader instance provided.");this.name=g.KHR_DRACO_MESH_COMPRESSION,this.json=n,this.dracoLoader=e,this.dracoLoader.preload()}decodePrimitive(n,e){const s=this.json,t=this.dracoLoader,i=n.extensions[this.name].bufferView,r=n.extensions[this.name].attributes,a={},o={},c={};for(const u in r){const l=$[u]||u.toLowerCase();a[l]=r[u]}for(const u in n.attributes){const l=$[u]||u.toLowerCase();if(r[u]!==void 0){const h=s.accessors[n.attributes[u]],d=H[h.componentType];c[l]=d.name,o[l]=h.normalized===!0}}return e.getDependency("bufferView",i).then(function(u){return new Promise(function(l,h){t.decodeDracoFile(u,function(d){for(const p in d.attributes){const R=d.attributes[p],m=o[p];m!==void 0&&(R.normalized=m)}l(d)},a,c,w,h)})})}}class Nn{constructor(){this.name=g.KHR_TEXTURE_TRANSFORM}extendTexture(n,e){return(e.texCoord===void 0||e.texCoord===n.channel)&&e.offset===void 0&&e.rotation===void 0&&e.scale===void 0||(n=n.clone(),e.texCoord!==void 0&&(n.channel=e.texCoord),e.offset!==void 0&&n.offset.fromArray(e.offset),e.rotation!==void 0&&(n.rotation=e.rotation),e.scale!==void 0&&n.repeat.fromArray(e.scale),n.needsUpdate=!0),n}}class In{constructor(){this.name=g.KHR_MESH_QUANTIZATION}}class _e extends on{constructor(n,e,s,t){super(n,e,s,t)}copySampleValue_(n){const e=this.resultBuffer,s=this.sampleValues,t=this.valueSize,i=n*t*3+t;for(let r=0;r!==t;r++)e[r]=s[i+r];return e}interpolate_(n,e,s,t){const i=this.resultBuffer,r=this.sampleValues,a=this.valueSize,o=a*2,c=a*3,u=t-e,l=(s-e)/u,h=l*l,d=h*l,p=n*c,R=p-c,m=-2*d+3*h,T=d-h,A=1-m,x=T-h+l;for(let E=0;E!==a;E++){const L=r[R+E+a],N=r[R+E+o]*u,S=r[p+E+a],k=r[p+E]*u;i[E]=A*L+x*N+m*S+T*k}return i}}const On=new me;class Cn extends _e{interpolate_(n,e,s,t){const i=super.interpolate_(n,e,s,t);return On.fromArray(i).normalize().toArray(i),i}}const M={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},H={5120:Int8Array,5121:Uint8Array,5122:Int16Array,5123:Uint16Array,5125:Uint32Array,5126:Float32Array},ue={9728:Re,9729:J,9984:He,9985:Pe,9986:Fe,9987:Te},le={33071:De,33648:ke,10497:Z},q={SCALAR:1,VEC2:2,VEC3:3,VEC4:4,MAT2:4,MAT3:9,MAT4:16},$={POSITION:"position",NORMAL:"normal",TANGENT:"tangent",TEXCOORD_0:"uv",TEXCOORD_1:"uv1",TEXCOORD_2:"uv2",TEXCOORD_3:"uv3",COLOR_0:"color",WEIGHTS_0:"skinWeight",JOINTS_0:"skinIndex"},I={scale:"scale",translation:"position",rotation:"quaternion",weights:"morphTargetInfluences"},Fn={CUBICSPLINE:void 0,LINEAR:xe,STEP:tn},W={OPAQUE:"OPAQUE",MASK:"MASK",BLEND:"BLEND"};function Pn(f){return f.DefaultMaterial===void 0&&(f.DefaultMaterial=new Ee({color:16777215,emissive:0,metalness:1,roughness:1,transparent:!1,depthTest:!0,side:rn})),f.DefaultMaterial}function O(f,n,e){for(const s in e.extensions)f[s]===void 0&&(n.userData.gltfExtensions=n.userData.gltfExtensions||{},n.userData.gltfExtensions[s]=e.extensions[s])}function y(f,n){n.extras!==void 0&&(typeof n.extras=="object"?Object.assign(f.userData,n.extras):console.warn("THREE.GLTFLoader: Ignoring primitive type .extras, "+n.extras))}function Hn(f,n,e){let s=!1,t=!1,i=!1;for(let c=0,u=n.length;c<u;c++){const l=n[c];if(l.POSITION!==void 0&&(s=!0),l.NORMAL!==void 0&&(t=!0),l.COLOR_0!==void 0&&(i=!0),s&&t&&i)break}if(!s&&!t&&!i)return Promise.resolve(f);const r=[],a=[],o=[];for(let c=0,u=n.length;c<u;c++){const l=n[c];if(s){const h=l.POSITION!==void 0?e.getDependency("accessor",l.POSITION):f.attributes.position;r.push(h)}if(t){const h=l.NORMAL!==void 0?e.getDependency("accessor",l.NORMAL):f.attributes.normal;a.push(h)}if(i){const h=l.COLOR_0!==void 0?e.getDependency("accessor",l.COLOR_0):f.attributes.color;o.push(h)}}return Promise.all([Promise.all(r),Promise.all(a),Promise.all(o)]).then(function(c){const u=c[0],l=c[1],h=c[2];return s&&(f.morphAttributes.position=u),t&&(f.morphAttributes.normal=l),i&&(f.morphAttributes.color=h),f.morphTargetsRelative=!0,f})}function kn(f,n){if(f.updateMorphTargets(),n.weights!==void 0)for(let e=0,s=n.weights.length;e<s;e++)f.morphTargetInfluences[e]=n.weights[e];if(n.extras&&Array.isArray(n.extras.targetNames)){const e=n.extras.targetNames;if(f.morphTargetInfluences.length===e.length){f.morphTargetDictionary={};for(let s=0,t=e.length;s<t;s++)f.morphTargetDictionary[e[s]]=s}else console.warn("THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.")}}function Dn(f){let n;const e=f.extensions&&f.extensions[g.KHR_DRACO_MESH_COMPRESSION];if(e?n="draco:"+e.bufferView+":"+e.indices+":"+Y(e.attributes):n=f.indices+":"+Y(f.attributes)+":"+f.mode,f.targets!==void 0)for(let s=0,t=f.targets.length;s<t;s++)n+=":"+Y(f.targets[s]);return n}function Y(f){let n="";const e=Object.keys(f).sort();for(let s=0,t=e.length;s<t;s++)n+=e[s]+":"+f[e[s]]+";";return n}function ee(f){switch(f){case Int8Array:return 1/127;case Uint8Array:return 1/255;case Int16Array:return 1/32767;case Uint16Array:return 1/65535;default:throw new Error("THREE.GLTFLoader: Unsupported normalized accessor component type.")}}function Gn(f){return f.search(/\.jpe?g($|\?)/i)>0||f.search(/^data\:image\/jpeg/)===0?"image/jpeg":f.search(/\.webp($|\?)/i)>0||f.search(/^data\:image\/webp/)===0?"image/webp":f.search(/\.ktx2($|\?)/i)>0||f.search(/^data\:image\/ktx2/)===0?"image/ktx2":"image/png"}const vn=new K;class Un{constructor(n={},e={}){this.json=n,this.extensions={},this.plugins={},this.options=e,this.cache=new un,this.associations=new Map,this.primitiveCache={},this.nodeCache={},this.meshCache={refs:{},uses:{}},this.cameraCache={refs:{},uses:{}},this.lightCache={refs:{},uses:{}},this.sourceCache={},this.textureCache={},this.nodeNamesUsed={};let s=!1,t=-1,i=!1,r=-1;if(typeof navigator<"u"&&typeof navigator.userAgent<"u"){const a=navigator.userAgent;s=/^((?!chrome|android).)*safari/i.test(a)===!0;const o=a.match(/Version\/(\d+)/);t=s&&o?parseInt(o[1],10):-1,i=a.indexOf("Firefox")>-1,r=i?a.match(/Firefox\/([0-9]+)\./)[1]:-1}typeof createImageBitmap>"u"||s&&t<17||i&&r<98?this.textureLoader=new Ie(this.options.manager):this.textureLoader=new Oe(this.options.manager),this.textureLoader.setCrossOrigin(this.options.crossOrigin),this.textureLoader.setRequestHeader(this.options.requestHeader),this.fileLoader=new de(this.options.manager),this.fileLoader.setResponseType("arraybuffer"),this.options.crossOrigin==="use-credentials"&&this.fileLoader.setWithCredentials(!0)}setExtensions(n){this.extensions=n}setPlugins(n){this.plugins=n}parse(n,e){const s=this,t=this.json,i=this.extensions;this.cache.removeAll(),this.nodeCache={},this._invokeAll(function(r){return r._markDefs&&r._markDefs()}),Promise.all(this._invokeAll(function(r){return r.beforeRoot&&r.beforeRoot()})).then(function(){return Promise.all([s.getDependencies("scene"),s.getDependencies("animation"),s.getDependencies("camera")])}).then(function(r){const a={scene:r[0][t.scene||0],scenes:r[0],animations:r[1],cameras:r[2],asset:t.asset,parser:s,userData:{}};return O(i,a,t),y(a,t),Promise.all(s._invokeAll(function(o){return o.afterRoot&&o.afterRoot(a)})).then(function(){for(const o of a.scenes)o.updateMatrixWorld();n(a)})}).catch(e)}_markDefs(){const n=this.json.nodes||[],e=this.json.skins||[],s=this.json.meshes||[];for(let t=0,i=e.length;t<i;t++){const r=e[t].joints;for(let a=0,o=r.length;a<o;a++)n[r[a]].isBone=!0}for(let t=0,i=n.length;t<i;t++){const r=n[t];r.mesh!==void 0&&(this._addNodeRef(this.meshCache,r.mesh),r.skin!==void 0&&(s[r.mesh].isSkinnedMesh=!0)),r.camera!==void 0&&this._addNodeRef(this.cameraCache,r.camera)}}_addNodeRef(n,e){e!==void 0&&(n.refs[e]===void 0&&(n.refs[e]=n.uses[e]=0),n.refs[e]++)}_getNodeRef(n,e,s){if(n.refs[e]<=1)return s;const t=s.clone(),i=(r,a)=>{const o=this.associations.get(r);o!=null&&this.associations.set(a,o);for(const[c,u]of r.children.entries())i(u,a.children[c])};return i(s,t),t.name+="_instance_"+n.uses[e]++,t}_invokeOne(n){const e=Object.values(this.plugins);e.push(this);for(let s=0;s<e.length;s++){const t=n(e[s]);if(t)return t}return null}_invokeAll(n){const e=Object.values(this.plugins);e.unshift(this);const s=[];for(let t=0;t<e.length;t++){const i=n(e[t]);i&&s.push(i)}return s}getDependency(n,e){const s=n+":"+e;let t=this.cache.get(s);if(!t){switch(n){case"scene":t=this.loadScene(e);break;case"node":t=this._invokeOne(function(i){return i.loadNode&&i.loadNode(e)});break;case"mesh":t=this._invokeOne(function(i){return i.loadMesh&&i.loadMesh(e)});break;case"accessor":t=this.loadAccessor(e);break;case"bufferView":t=this._invokeOne(function(i){return i.loadBufferView&&i.loadBufferView(e)});break;case"buffer":t=this.loadBuffer(e);break;case"material":t=this._invokeOne(function(i){return i.loadMaterial&&i.loadMaterial(e)});break;case"texture":t=this._invokeOne(function(i){return i.loadTexture&&i.loadTexture(e)});break;case"skin":t=this.loadSkin(e);break;case"animation":t=this._invokeOne(function(i){return i.loadAnimation&&i.loadAnimation(e)});break;case"camera":t=this.loadCamera(e);break;default:if(t=this._invokeOne(function(i){return i!=this&&i.getDependency&&i.getDependency(n,e)}),!t)throw new Error("Unknown type: "+n);break}this.cache.add(s,t)}return t}getDependencies(n){let e=this.cache.get(n);if(!e){const s=this,t=this.json[n+(n==="mesh"?"es":"s")]||[];e=Promise.all(t.map(function(i,r){return s.getDependency(n,r)})),this.cache.add(n,e)}return e}loadBuffer(n){const e=this.json.buffers[n],s=this.fileLoader;if(e.type&&e.type!=="arraybuffer")throw new Error("THREE.GLTFLoader: "+e.type+" buffer type is not supported.");if(e.uri===void 0&&n===0)return Promise.resolve(this.extensions[g.KHR_BINARY_GLTF].body);const t=this.options;return new Promise(function(i,r){s.load(v.resolveURL(e.uri,t.path),i,void 0,function(){r(new Error('THREE.GLTFLoader: Failed to load buffer "'+e.uri+'".'))})})}loadBufferView(n){const e=this.json.bufferViews[n];return this.getDependency("buffer",e.buffer).then(function(s){const t=e.byteLength||0,i=e.byteOffset||0;return s.slice(i,i+t)})}loadAccessor(n){const e=this,s=this.json,t=this.json.accessors[n];if(t.bufferView===void 0&&t.sparse===void 0){const r=q[t.type],a=H[t.componentType],o=t.normalized===!0,c=new a(t.count*r);return Promise.resolve(new V(c,r,o))}const i=[];return t.bufferView!==void 0?i.push(this.getDependency("bufferView",t.bufferView)):i.push(null),t.sparse!==void 0&&(i.push(this.getDependency("bufferView",t.sparse.indices.bufferView)),i.push(this.getDependency("bufferView",t.sparse.values.bufferView))),Promise.all(i).then(function(r){const a=r[0],o=q[t.type],c=H[t.componentType],u=c.BYTES_PER_ELEMENT,l=u*o,h=t.byteOffset||0,d=t.bufferView!==void 0?s.bufferViews[t.bufferView].byteStride:void 0,p=t.normalized===!0;let R,m;if(d&&d!==l){const T=Math.floor(h/d),A="InterleavedBuffer:"+t.bufferView+":"+t.componentType+":"+T+":"+t.count;let x=e.cache.get(A);x||(R=new c(a,T*d,t.count*d/u),x=new Ce(R,d/u),e.cache.add(A,x)),m=new sn(x,o,h%d/u,p)}else a===null?R=new c(t.count*o):R=new c(a,h,t.count*o),m=new V(R,o,p);if(t.sparse!==void 0){const T=q.SCALAR,A=H[t.sparse.indices.componentType],x=t.sparse.indices.byteOffset||0,E=t.sparse.values.byteOffset||0,L=new A(r[1],x,t.sparse.count*T),N=new c(r[2],E,t.sparse.count*o);a!==null&&(m=new V(m.array.slice(),m.itemSize,m.normalized)),m.normalized=!1;for(let S=0,k=L.length;S<k;S++){const P=L[S];if(m.setX(P,N[S*o]),o>=2&&m.setY(P,N[S*o+1]),o>=3&&m.setZ(P,N[S*o+2]),o>=4&&m.setW(P,N[S*o+3]),o>=5)throw new Error("THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.")}m.normalized=p}return m})}loadTexture(n){const e=this.json,s=this.options,i=e.textures[n].source,r=e.images[i];let a=this.textureLoader;if(r.uri){const o=s.manager.getHandler(r.uri);o!==null&&(a=o)}return this.loadTextureImage(n,i,a)}loadTextureImage(n,e,s){const t=this,i=this.json,r=i.textures[n],a=i.images[e],o=(a.uri||a.bufferView)+":"+r.sampler;if(this.textureCache[o])return this.textureCache[o];const c=this.loadImageSource(e,s).then(function(u){u.flipY=!1,u.name=r.name||a.name||"",u.name===""&&typeof a.uri=="string"&&a.uri.startsWith("data:image/")===!1&&(u.name=a.uri);const h=(i.samplers||{})[r.sampler]||{};return u.magFilter=ue[h.magFilter]||J,u.minFilter=ue[h.minFilter]||Te,u.wrapS=le[h.wrapS]||Z,u.wrapT=le[h.wrapT]||Z,u.generateMipmaps=!u.isCompressedTexture&&u.minFilter!==Re&&u.minFilter!==J,t.associations.set(u,{textures:n}),u}).catch(function(){return null});return this.textureCache[o]=c,c}loadImageSource(n,e){const s=this,t=this.json,i=this.options;if(this.sourceCache[n]!==void 0)return this.sourceCache[n].then(l=>l.clone());const r=t.images[n],a=self.URL||self.webkitURL;let o=r.uri||"",c=!1;if(r.bufferView!==void 0)o=s.getDependency("bufferView",r.bufferView).then(function(l){c=!0;const h=new Blob([l],{type:r.mimeType});return o=a.createObjectURL(h),o});else if(r.uri===void 0)throw new Error("THREE.GLTFLoader: Image "+n+" is missing URI and bufferView");const u=Promise.resolve(o).then(function(l){return new Promise(function(h,d){let p=h;e.isImageBitmapLoader===!0&&(p=function(R){const m=new ne(R);m.needsUpdate=!0,h(m)}),e.load(v.resolveURL(l,i.path),p,void 0,d)})}).then(function(l){return c===!0&&a.revokeObjectURL(o),y(l,r),l.userData.mimeType=r.mimeType||Gn(r.uri),l}).catch(function(l){throw console.error("THREE.GLTFLoader: Couldn't load texture",o),l});return this.sourceCache[n]=u,u}assignTexture(n,e,s,t){const i=this;return this.getDependency("texture",s.index).then(function(r){if(!r)return null;if(s.texCoord!==void 0&&s.texCoord>0&&(r=r.clone(),r.channel=s.texCoord),i.extensions[g.KHR_TEXTURE_TRANSFORM]){const a=s.extensions!==void 0?s.extensions[g.KHR_TEXTURE_TRANSFORM]:void 0;if(a){const o=i.associations.get(r);r=i.extensions[g.KHR_TEXTURE_TRANSFORM].extendTexture(r,a),i.associations.set(r,o)}}return t!==void 0&&(r.colorSpace=t),n[e]=r,r})}assignFinalMaterial(n){const e=n.geometry;let s=n.material;const t=e.attributes.tangent===void 0,i=e.attributes.color!==void 0,r=e.attributes.normal===void 0;if(n.isPoints){const a="PointsMaterial:"+s.uuid;let o=this.cache.get(a);o||(o=new Ge,X.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,o.sizeAttenuation=!1,this.cache.add(a,o)),s=o}else if(n.isLine){const a="LineBasicMaterial:"+s.uuid;let o=this.cache.get(a);o||(o=new ve,X.prototype.copy.call(o,s),o.color.copy(s.color),o.map=s.map,this.cache.add(a,o)),s=o}if(t||i||r){let a="ClonedMaterial:"+s.uuid+":";t&&(a+="derivative-tangents:"),i&&(a+="vertex-colors:"),r&&(a+="flat-shading:");let o=this.cache.get(a);o||(o=s.clone(),i&&(o.vertexColors=!0),r&&(o.flatShading=!0),t&&(o.normalScale&&(o.normalScale.y*=-1),o.clearcoatNormalScale&&(o.clearcoatNormalScale.y*=-1)),this.cache.add(a,o),this.associations.set(o,this.associations.get(s))),s=o}n.material=s}getMaterialType(){return Ee}loadMaterial(n){const e=this,s=this.json,t=this.extensions,i=s.materials[n];let r;const a={},o=i.extensions||{},c=[];if(o[g.KHR_MATERIALS_UNLIT]){const l=t[g.KHR_MATERIALS_UNLIT];r=l.getMaterialType(),c.push(l.extendParams(a,i,e))}else{const l=i.pbrMetallicRoughness||{};if(a.color=new F(1,1,1),a.opacity=1,Array.isArray(l.baseColorFactor)){const h=l.baseColorFactor;a.color.setRGB(h[0],h[1],h[2],w),a.opacity=h[3]}l.baseColorTexture!==void 0&&c.push(e.assignTexture(a,"map",l.baseColorTexture,U)),a.metalness=l.metallicFactor!==void 0?l.metallicFactor:1,a.roughness=l.roughnessFactor!==void 0?l.roughnessFactor:1,l.metallicRoughnessTexture!==void 0&&(c.push(e.assignTexture(a,"metalnessMap",l.metallicRoughnessTexture)),c.push(e.assignTexture(a,"roughnessMap",l.metallicRoughnessTexture))),r=this._invokeOne(function(h){return h.getMaterialType&&h.getMaterialType(n)}),c.push(Promise.all(this._invokeAll(function(h){return h.extendMaterialParams&&h.extendMaterialParams(n,a)})))}i.doubleSided===!0&&(a.side=Ue);const u=i.alphaMode||W.OPAQUE;if(u===W.BLEND?(a.transparent=!0,a.depthWrite=!1):(a.transparent=!1,u===W.MASK&&(a.alphaTest=i.alphaCutoff!==void 0?i.alphaCutoff:.5)),i.normalTexture!==void 0&&r!==G&&(c.push(e.assignTexture(a,"normalMap",i.normalTexture)),a.normalScale=new pe(1,1),i.normalTexture.scale!==void 0)){const l=i.normalTexture.scale;a.normalScale.set(l,l)}if(i.occlusionTexture!==void 0&&r!==G&&(c.push(e.assignTexture(a,"aoMap",i.occlusionTexture)),i.occlusionTexture.strength!==void 0&&(a.aoMapIntensity=i.occlusionTexture.strength)),i.emissiveFactor!==void 0&&r!==G){const l=i.emissiveFactor;a.emissive=new F().setRGB(l[0],l[1],l[2],w)}return i.emissiveTexture!==void 0&&r!==G&&c.push(e.assignTexture(a,"emissiveMap",i.emissiveTexture,U)),Promise.all(c).then(function(){const l=new r(a);return i.name&&(l.name=i.name),y(l,i),e.associations.set(l,{materials:n}),i.extensions&&O(t,l,i),l})}createUniqueName(n){const e=Ke.sanitizeNodeName(n||"");return e in this.nodeNamesUsed?e+"_"+ ++this.nodeNamesUsed[e]:(this.nodeNamesUsed[e]=0,e)}loadGeometries(n){const e=this,s=this.extensions,t=this.primitiveCache;function i(a){return s[g.KHR_DRACO_MESH_COMPRESSION].decodePrimitive(a,e).then(function(o){return fe(o,a,e)})}const r=[];for(let a=0,o=n.length;a<o;a++){const c=n[a],u=Dn(c),l=t[u];if(l)r.push(l.promise);else{let h;c.extensions&&c.extensions[g.KHR_DRACO_MESH_COMPRESSION]?h=i(c):h=fe(new Be,c,e),t[u]={primitive:c,promise:h},r.push(h)}}return Promise.all(r)}loadMesh(n){const e=this,s=this.json,t=this.extensions,i=s.meshes[n],r=i.primitives,a=[];for(let o=0,c=r.length;o<c;o++){const u=r[o].material===void 0?Pn(this.cache):this.getDependency("material",r[o].material);a.push(u)}return a.push(e.loadGeometries(r)),Promise.all(a).then(function(o){const c=o.slice(0,o.length-1),u=o[o.length-1],l=[];for(let d=0,p=u.length;d<p;d++){const R=u[d],m=r[d];let T;const A=c[d];if(m.mode===M.TRIANGLES||m.mode===M.TRIANGLE_STRIP||m.mode===M.TRIANGLE_FAN||m.mode===void 0)T=i.isSkinnedMesh===!0?new je(R,A):new Ve(R,A),T.isSkinnedMesh===!0&&T.normalizeSkinWeights(),m.mode===M.TRIANGLE_STRIP?T.geometry=oe(T.geometry,he):m.mode===M.TRIANGLE_FAN&&(T.geometry=oe(T.geometry,Q));else if(m.mode===M.LINES)T=new Xe(R,A);else if(m.mode===M.LINE_STRIP)T=new ze(R,A);else if(m.mode===M.LINE_LOOP)T=new qe(R,A);else if(m.mode===M.POINTS)T=new We(R,A);else throw new Error("THREE.GLTFLoader: Primitive mode unsupported: "+m.mode);Object.keys(T.geometry.morphAttributes).length>0&&kn(T,i),T.name=e.createUniqueName(i.name||"mesh_"+n),y(T,i),m.extensions&&O(t,T,m),e.assignFinalMaterial(T),l.push(T)}for(let d=0,p=l.length;d<p;d++)e.associations.set(l[d],{meshes:n,primitives:d});if(l.length===1)return i.extensions&&O(t,l[0],i),l[0];const h=new z;i.extensions&&O(t,h,i),e.associations.set(h,{meshes:n});for(let d=0,p=l.length;d<p;d++)h.add(l[d]);return h})}loadCamera(n){let e;const s=this.json.cameras[n],t=s[s.type];if(!t){console.warn("THREE.GLTFLoader: Missing camera parameters.");return}return s.type==="perspective"?e=new Ye(Qe.radToDeg(t.yfov),t.aspectRatio||1,t.znear||1,t.zfar||2e6):s.type==="orthographic"&&(e=new Je(-t.xmag,t.xmag,t.ymag,-t.ymag,t.znear,t.zfar)),s.name&&(e.name=this.createUniqueName(s.name)),y(e,s),Promise.resolve(e)}loadSkin(n){const e=this.json.skins[n],s=[];for(let t=0,i=e.joints.length;t<i;t++)s.push(this._loadNodeShallow(e.joints[t]));return e.inverseBindMatrices!==void 0?s.push(this.getDependency("accessor",e.inverseBindMatrices)):s.push(null),Promise.all(s).then(function(t){const i=t.pop(),r=t,a=[],o=[];for(let c=0,u=r.length;c<u;c++){const l=r[c];if(l){a.push(l);const h=new K;i!==null&&h.fromArray(i.array,c*16),o.push(h)}else console.warn('THREE.GLTFLoader: Joint "%s" could not be found.',e.joints[c])}return new Ze(a,o)})}loadAnimation(n){const e=this.json,s=this,t=e.animations[n],i=t.name?t.name:"animation_"+n,r=[],a=[],o=[],c=[],u=[];for(let l=0,h=t.channels.length;l<h;l++){const d=t.channels[l],p=t.samplers[d.sampler],R=d.target,m=R.node,T=t.parameters!==void 0?t.parameters[p.input]:p.input,A=t.parameters!==void 0?t.parameters[p.output]:p.output;R.node!==void 0&&(r.push(this.getDependency("node",m)),a.push(this.getDependency("accessor",T)),o.push(this.getDependency("accessor",A)),c.push(p),u.push(R))}return Promise.all([Promise.all(r),Promise.all(a),Promise.all(o),Promise.all(c),Promise.all(u)]).then(function(l){const h=l[0],d=l[1],p=l[2],R=l[3],m=l[4],T=[];for(let x=0,E=h.length;x<E;x++){const L=h[x],N=d[x],S=p[x],k=R[x],P=m[x];if(L===void 0)continue;L.updateMatrix&&L.updateMatrix();const B=s._createAnimationTracks(L,N,S,k,P);if(B)for(let j=0;j<B.length;j++)T.push(B[j])}const A=new $e(i,void 0,T);return y(A,t),A})}createNodeMesh(n){const e=this.json,s=this,t=e.nodes[n];return t.mesh===void 0?null:s.getDependency("mesh",t.mesh).then(function(i){const r=s._getNodeRef(s.meshCache,t.mesh,i);return t.weights!==void 0&&r.traverse(function(a){if(a.isMesh)for(let o=0,c=t.weights.length;o<c;o++)a.morphTargetInfluences[o]=t.weights[o]}),r})}loadNode(n){const e=this.json,s=this,t=e.nodes[n],i=s._loadNodeShallow(n),r=[],a=t.children||[];for(let c=0,u=a.length;c<u;c++)r.push(s.getDependency("node",a[c]));const o=t.skin===void 0?Promise.resolve(null):s.getDependency("skin",t.skin);return Promise.all([i,Promise.all(r),o]).then(function(c){const u=c[0],l=c[1],h=c[2];h!==null&&u.traverse(function(d){d.isSkinnedMesh&&d.bind(h,vn)});for(let d=0,p=l.length;d<p;d++)u.add(l[d]);if(u.userData.pivot!==void 0&&l.length>0){const d=u.userData.pivot,p=l[0];u.pivot=new C().fromArray(d),u.position.x-=d[0],u.position.y-=d[1],u.position.z-=d[2],p.position.set(0,0,0),delete u.userData.pivot}return u})}_loadNodeShallow(n){const e=this.json,s=this.extensions,t=this;if(this.nodeCache[n]!==void 0)return this.nodeCache[n];const i=e.nodes[n],r=i.name?t.createUniqueName(i.name):"",a=[],o=t._invokeOne(function(c){return c.createNodeMesh&&c.createNodeMesh(n)});return o&&a.push(o),i.camera!==void 0&&a.push(t.getDependency("camera",i.camera).then(function(c){return t._getNodeRef(t.cameraCache,i.camera,c)})),t._invokeAll(function(c){return c.createNodeAttachment&&c.createNodeAttachment(n)}).forEach(function(c){a.push(c)}),this.nodeCache[n]=Promise.all(a).then(function(c){let u;if(i.isBone===!0?u=new en:c.length>1?u=new z:c.length===1?u=c[0]:u=new ge,u!==c[0])for(let l=0,h=c.length;l<h;l++)u.add(c[l]);if(i.name&&(u.userData.name=i.name,u.name=r),y(u,i),i.extensions&&O(s,u,i),i.matrix!==void 0){const l=new K;l.fromArray(i.matrix),u.applyMatrix4(l)}else i.translation!==void 0&&u.position.fromArray(i.translation),i.rotation!==void 0&&u.quaternion.fromArray(i.rotation),i.scale!==void 0&&u.scale.fromArray(i.scale);if(!t.associations.has(u))t.associations.set(u,{});else if(i.mesh!==void 0&&t.meshCache.refs[i.mesh]>1){const l=t.associations.get(u);t.associations.set(u,{...l})}return t.associations.get(u).nodes=n,u}),this.nodeCache[n]}loadScene(n){const e=this.extensions,s=this.json.scenes[n],t=this,i=new z;s.name&&(i.name=t.createUniqueName(s.name)),y(i,s),s.extensions&&O(e,i,s);const r=s.nodes||[],a=[];for(let o=0,c=r.length;o<c;o++)a.push(t.getDependency("node",r[o]));return Promise.all(a).then(function(o){for(let u=0,l=o.length;u<l;u++){const h=o[u];h.parent!==null?i.add(nn(h)):i.add(h)}const c=u=>{const l=new Map;for(const[h,d]of t.associations)(h instanceof X||h instanceof ne)&&l.set(h,d);return u.traverse(h=>{const d=t.associations.get(h);d!=null&&l.set(h,d)}),l};return t.associations=c(i),i})}_createAnimationTracks(n,e,s,t,i){const r=[],a=n.name?n.name:n.uuid,o=[];function c(d){d.morphTargetInfluences&&o.push(d.name?d.name:d.uuid)}I[i.path]===I.weights?(c(n),n.isGroup&&n.children.forEach(c)):o.push(a);let u;switch(I[i.path]){case I.weights:u=se;break;case I.rotation:u=ie;break;case I.translation:case I.scale:u=te;break;default:switch(s.itemSize){case 1:u=se;break;case 2:case 3:default:u=te;break}break}const l=t.interpolation!==void 0?Fn[t.interpolation]:xe,h=this._getArrayFromAccessor(s);for(let d=0,p=o.length;d<p;d++){const R=new u(o[d]+"."+I[i.path],e.array,h,l);t.interpolation==="CUBICSPLINE"&&this._createCubicSplineTrackInterpolant(R),r.push(R)}return r}_getArrayFromAccessor(n){let e=n.array;if(n.normalized){const s=ee(e.constructor),t=new Float32Array(e.length);for(let i=0,r=e.length;i<r;i++)t[i]=e[i]*s;e=t}return e}_createCubicSplineTrackInterpolant(n){n.createInterpolant=function(s){const t=this instanceof ie?Cn:_e;return new t(this.times,this.values,this.getValueSize()/3,s)},n.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline=!0}}function Kn(f,n,e){const s=n.attributes,t=new an;if(s.POSITION!==void 0){const a=e.json.accessors[s.POSITION],o=a.min,c=a.max;if(o!==void 0&&c!==void 0){if(t.set(new C(o[0],o[1],o[2]),new C(c[0],c[1],c[2])),a.normalized){const u=ee(H[a.componentType]);t.min.multiplyScalar(u),t.max.multiplyScalar(u)}}else{console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.");return}}else return;const i=n.targets;if(i!==void 0){const a=new C,o=new C;for(let c=0,u=i.length;c<u;c++){const l=i[c];if(l.POSITION!==void 0){const h=e.json.accessors[l.POSITION],d=h.min,p=h.max;if(d!==void 0&&p!==void 0){if(o.setX(Math.max(Math.abs(d[0]),Math.abs(p[0]))),o.setY(Math.max(Math.abs(d[1]),Math.abs(p[1]))),o.setZ(Math.max(Math.abs(d[2]),Math.abs(p[2]))),h.normalized){const R=ee(H[h.componentType]);o.multiplyScalar(R)}a.max(o)}else console.warn("THREE.GLTFLoader: Missing min/max properties for accessor POSITION.")}}t.expandByVector(a)}f.boundingBox=t;const r=new cn;t.getCenter(r.center),r.radius=t.min.distanceTo(t.max)/2,f.boundingSphere=r}function fe(f,n,e){const s=n.attributes,t=[];function i(r,a){return e.getDependency("accessor",r).then(function(o){f.setAttribute(a,o)})}for(const r in s){const a=$[r]||r.toLowerCase();a in f.attributes||t.push(i(s[r],a))}if(n.indices!==void 0&&!f.index){const r=e.getDependency("accessor",n.indices).then(function(a){f.setIndex(a)});t.push(r)}return re.workingColorSpace!==w&&"COLOR_0"in s&&console.warn(`THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${re.workingColorSpace}" not supported.`),y(f,n),Kn(f,n,e),Promise.all(t).then(function(){return n.targets!==void 0?Hn(f,n.targets,e):f})}export{jn as GLTFLoader};
|
package/dist-embed-sighting-editor/{HeadlightSystem-Dyh8W52L.js → HeadlightSystem-BEWiubrn.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{aH as b,$ as g,a8 as P,aI as m,ai as C,ak as E,aq as L,ae as x,aF as I,aG as R}from"./rr0-sighting-editor.mjs";class i{constructor(e){this.scene=e}static REAL_BEAMS=4;static LAMPS=2;static DISTANCE_M=500;static AIR_LENGTH_M=90;static CLEAR_AIR_SCATTER_PER_M=2e-4;static SHADOW_MAP_PX=1024;beams=new Map;static airGeometry;has(e){return this.beams.has(e)}get size(){return this.beams.size}lamps(e){return this.beams.get(e)?.lamps??[]}airMeshes(e){return this.beams.get(e)?.air??[]}add(e){if(this.beams.has(e))return!0;if(this.beams.size>=i.REAL_BEAMS)return!1;const t=[],r=[];for(let n=0;n<i.LAMPS;n++){const a=new b(16777215,0,i.DISTANCE_M,Math.PI/8,.5,2);a.castShadow=e==="observer",a.shadow.mapSize.set(i.SHADOW_MAP_PX,i.SHADOW_MAP_PX),a.shadow.camera.near=.4,a.shadow.camera.far=110,a.shadow.bias=-4e-4,a.shadow.normalBias=.04,a.shadow.radius=2,this.scene.add(a),this.scene.add(a.target),t.push(a);const o=new g(i.airCone(),i.airMaterial());o.visible=!1,o.frustumCulled=!1,o.renderOrder=8,o.castShadow=!1,o.receiveShadow=!1,o.name="headlight air",this.scene.add(o),r.push(o)}return this.beams.set(e,{lamps:t,air:r}),!0}remove(e){const t=this.beams.get(e);if(t){for(const r of t.lamps)r.removeFromParent(),r.target.removeFromParent(),r.dispose();for(const r of t.air)r.removeFromParent(),r.material.dispose();this.beams.delete(e)}}clear(e){for(const t of[...this.beams.keys()])e&&t==="observer"||this.remove(t)}dispose(){this.clear(!1),i.airGeometry?.dispose(),i.airGeometry=void 0}aim(e,t,r,n,a,o,u){const c=this.beams.get(e),w=Math.max(u,i.CLEAR_AIR_SCATTER_PER_M);if(!c)return;const l=m.BEAMS[t],v=new P(-n.z,0,n.x),A=e==="observer"&&l!==void 0;c.lamps.forEach((s,d)=>{if(!l){s.intensity=0,c.air[d].visible=!1,s.shadow.autoUpdate=!1;return}const f=d===0?-1:1,h=l.pitchDeg*Math.PI/180,p=l.candela*m.DISPLAY_GAIN*o/c.lamps.length;s.color.set(l.color),s.intensity=p,s.angle=l.halfAngleDeg*Math.PI/180,s.penumbra=l.penumbra,A?(s.shadow.autoUpdate||(s.shadow.needsUpdate=!0),s.shadow.autoUpdate=!0):s.shadow.autoUpdate=!1,s.position.copy(r).addScaledVector(v,f*a);const M=n.clone().addScaledVector(v,-f*Math.tan(m.TOE_IN_DEG*Math.PI/180)).normalize();s.target.position.set(s.position.x+M.x*Math.cos(h)*50,s.position.y-Math.sin(h)*50,s.position.z+M.z*Math.cos(h)*50),s.target.updateMatrixWorld(),this.aimAir(c.air[d],s,l.color,p,w)})}aimAir(e,t,r,n,a){if(e.visible=a*n>1e-4,!e.visible)return;const o=i.AIR_LENGTH_M,u=o*Math.tan(t.angle);e.position.copy(t.position),e.scale.set(u,u,o),e.lookAt(t.target.position),e.updateMatrixWorld();const c=e.material.uniforms;c.uColor.value.set(r),c.uCandela.value=n,c.uScatter.value=a,c.uLength.value=o,c.uRadius.value=u}static airCone(){if(i.airGeometry)return i.airGeometry;const e=24,t=new Float32Array((e+1)*3);for(let a=0;a<e;a++){const o=a/e*Math.PI*2;t.set([Math.cos(o),Math.sin(o),1],(a+1)*3)}const r=[];for(let a=0;a<e;a++)r.push(0,1+a,1+(a+1)%e);const n=new C;return n.setAttribute("position",new E(t,3)),n.setIndex(r),i.airGeometry=n,n}static airMaterial(){return new L({transparent:!0,depthWrite:!1,depthTest:!0,blending:R,side:I,uniforms:{uColor:{value:new x(1,1,1)},uCandela:{value:0},uScatter:{value:0},uLength:{value:90},uRadius:{value:20}},vertexShader:`
|
|
2
2
|
varying vec3 vLocal;
|
|
3
3
|
varying vec3 vNormalView;
|
|
4
4
|
varying vec3 vViewDir;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{aa as r,ab as c,ac as l}from"./rr0-sighting-editor.mjs";const v=-6,p=150;class o{about="temporal";async assess(e){const t=o.daylight(e),i=e.decor.map((s,n)=>({object:s,index:n})).filter(({object:s})=>s.kind==="entity"),a=o.nearest(e),d=a!==void 0&&a<=p;return{verdict:i.length>0?"ce3":d?"ce1":t===void 0?void 0:t?"dd":"nl",criteria:[{id:"entities",basis:i.length>0?"stated":void 0,paths:i.map(({index:s})=>`decor.${s}`)},{id:"traces",paths:[],unsupported:!0},{id:"proximity",basis:a===void 0?void 0:"derived",paths:a===void 0?[]:["timeline","observerTrack"]},{id:"radar",paths:[],unsupported:!0},{id:"daylight",basis:t===void 0?void 0:"derived",paths:t===void 0?[]:["time","place"]}]}}static nearest(e){const t=e.timeline.sourceIds.map(i=>r.of(e,i)?.nearestM).filter(i=>i!==void 0);return t.length>0?Math.min(...t):void 0}static daylight(e){const t=e.event.place?.[0],i=e.event.time;if(!t||!i)return;const a=c(i,t.lng,e.event.utcOffsetHours);if(a)return l("Sun",a,{lat:t.lat,lng:t.lng,elevationM:0}).altitudeDeg>v}}export{o as HynekAssessor};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./SightingFileEditor-LAzFduCJ.js","./sightingSchema-DfbuP60Y.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{S as L,a as T,H as j,s as P,U as H,l as I,I as W,P as z,b as y,W as O,r as J,c as D,E as C,A as U,d as E,M as q,_ as A,e as V}from"./rr0-sighting-editor.mjs";import{interviewMessages_en as S}from"./InterviewMessages_en-CRvWVmlL.js";import{InterviewMedia as N}from"./InterviewMedia-CvAxC62V.js";import{InterviewFile as b}from"./interviewJson-CfwBPiuG.js";const F="rr0-interview",G=`
|
|
3
|
+
rr0-interview { display: block; --rr0-interview-line: color-mix(in srgb, currentColor 35%, transparent); }
|
|
4
|
+
rr0-interview [hidden] { display: none !important; }
|
|
5
|
+
rr0-interview .rr0-interview-status { font-size: .85em; opacity: .85; margin: 0 0 .5em; }
|
|
6
|
+
/* Scrolling only where a height is asked for: a box that scrolls keeps clear of the page's floated figures for all its height. */
|
|
7
|
+
rr0-interview .rr0-interview-turns { max-height: var(--rr0-interview-max-height, none); overflow-y: var(--rr0-interview-overflow, visible); }
|
|
8
|
+
/* An intervention: what one speaker says before another speaks, one turn or several; pointed at as a whole. */
|
|
9
|
+
rr0-interview .intervention { margin: 0 0 .4em; border-left: 3px solid var(--speaker); --speaker: hsl(var(--speaker-hue, 0) 55% 38%); transition: background-color .15s; }
|
|
10
|
+
@media (prefers-color-scheme: dark) { rr0-interview .intervention { --speaker: hsl(var(--speaker-hue, 0) 65% 70%); } }
|
|
11
|
+
rr0-interview .intervention:hover { background: color-mix(in srgb, var(--speaker) 7%, transparent); }
|
|
12
|
+
rr0-interview .turn { position: relative; padding: .2em .5em; }
|
|
13
|
+
rr0-interview .turn.flash { background: color-mix(in srgb, #fc3 28%, transparent); }
|
|
14
|
+
rr0-interview .turn .who { font-size: .85em; font-weight: 600; color: var(--speaker); overflow-wrap: anywhere; }
|
|
15
|
+
rr0-interview .turn.is-redacted .who, rr0-interview .turn.goes-on .who { display: none; }
|
|
16
|
+
rr0-interview .turn .said, rr0-interview .turn .redacted { margin: 0; padding: 0; text-indent: 0; white-space: pre-wrap; }
|
|
17
|
+
rr0-interview .turn .said::before, rr0-interview .turn .said::after { content: none; }
|
|
18
|
+
/* Tooltips drawn here rather than left to the browser's own, which some hosts (an embedded pane) never show. */
|
|
19
|
+
rr0-interview .turn[data-time]:hover:not(:has(.bar:hover, .bar:focus, .said a:hover))::after { content: attr(data-time); position: absolute; right: .3em; top: .2em; z-index: 2;
|
|
20
|
+
padding: 0 .4em; border-radius: 3px; font-size: .8em; font-variant-numeric: tabular-nums; background: #222; color: #fff; pointer-events: none; }
|
|
21
|
+
rr0-interview .bar { position: relative; display: inline-block; width: 3em; height: .9em; vertical-align: -.1em; border-radius: 2px; background: currentColor; margin: 0 .2em; cursor: help; }
|
|
22
|
+
rr0-interview .bar::after { content: attr(data-tip); display: none; position: absolute; left: 0; top: 1.4em; z-index: 3; width: max-content; max-width: 22em; padding: .3em .5em;
|
|
23
|
+
border-radius: 4px; background: #222; color: #fff; font-size: .85em; line-height: 1.3; white-space: normal; }
|
|
24
|
+
rr0-interview .bar:hover::after, rr0-interview .bar:focus::after { display: block; }
|
|
25
|
+
rr0-interview .turn .refs { display: flex; flex-wrap: wrap; gap: .25em; }
|
|
26
|
+
rr0-interview .turn .ref { font: inherit; font-size: .8em; cursor: pointer; border: 1px solid var(--rr0-interview-line); border-radius: 999px; background: transparent; color: inherit;
|
|
27
|
+
padding: 0 .35em; font-variant-numeric: tabular-nums; white-space: nowrap; display: inline-flex; align-items: center; gap: .15em; }
|
|
28
|
+
rr0-interview .turn .ref svg { width: 1.1em; height: 1.1em; }
|
|
29
|
+
`;class R extends HTMLElement{messages=S;said=new L(["en"]);localeToken=0;loadToken=0;json;loading;base;status=document.createElement("p");turns=document.createElement("div");blocks=new Map;constructor(){super(),this.status.className="rr0-interview-status",this.status.setAttribute("role","status"),this.turns.className="rr0-interview-turns"}static get observedAttributes(){return["src"]}attributeChangedCallback(e,t,r){e==="src"&&r!==t&&this.isConnected&&this.load()}connectedCallback(){R.styleRoot(this.getRootNode()),this.contains(this.turns)||this.replaceChildren(this.status,this.turns),this.loadLocale(),this.hasAttribute("src")&&this.json===void 0&&this.loading!==this.getAttribute("src")&&this.load()}get interview(){return this.json}set interview(e){this.loadToken++,this.json=e,this.draw()}set documentUrl(e){this.base=e}static styleRoot(e){const t=e instanceof ShadowRoot?e:document.head;if(t.querySelector("style[data-rr0-interview]"))return;const r=document.createElement("style");r.dataset.rr0Interview="",r.textContent=G,t.append(r)}async load(){const e=this.getAttribute("src"),t=++this.loadToken;if(this.loading=e??void 0,!e)return;const r=new URL(e,location.href).href;let s;try{s=await T.json(r)}catch{s=void 0}t===this.loadToken&&(this.base=r,this.json=s,this.draw())}async loadLocale(){const e=++this.localeToken,t=j.preferencesFor(this),r=P(t,H),s=r==="en"?S:await I(r);e===this.localeToken&&(this.said=new L(t),this.messages=s,this.draw())}speakerName(e,t){const r=b.speakerName(e,t),s=e.speakers?.[t]?.role;return r===s&&s in this.messages.roles?this.messages.roles[s]:r}seek(e,t){const r=this.json,s=t?b.said(t):void 0,i={sighting:e.sighting??b.sightingsOf(r)[0],at:e.at,...s?{quote:s}:{}};this.dispatchEvent(new CustomEvent(W,{bubbles:!0,composed:!0,detail:i}));const a=this.getAttribute("player");if(!a)return;const l=this.getRootNode().getElementById?.(a);typeof l?.seekTo=="function"&&(l.scrollIntoView?.({block:"center",behavior:"smooth"}),l.seekTo(i.at,i.sighting))}gap(e,t){const r=document.createElement(t),s=document.createElement("span");s.className="bar";const i=`${this.messages.redacted} : ${this.said.read(e)??""}`;return s.dataset.tip=i,s.tabIndex=0,s.setAttribute("role","img"),s.setAttribute("aria-label",i),r.append(s),r}saidNodes(e){if(!/[<&]/.test(e))return[document.createTextNode(e)];const t=document.createElement("template");t.innerHTML=e;for(const r of t.content.querySelectorAll("*")){if(["SCRIPT","STYLE","IFRAME","OBJECT","EMBED"].includes(r.tagName)){r.remove();continue}for(const s of[...r.attributes])if(/^on/i.test(s.name)||/^\s*javascript:/i.test(s.value))r.removeAttribute(s.name);else if(["href","src"].includes(s.name))try{s.value=new URL(s.value,this.base??location.href).href}catch{}}return[...t.content.childNodes]}draw(){const e=this.messages,t=this.json;this.blocks.clear();const r=Array.isArray(t?.segments)?t.segments:[];if(!t||r.length===0){this.status.hidden=!0;const d=document.createElement("p");d.textContent=e.exchangesEmpty,this.turns.replaceChildren(d);return}const s=t.speakers??{},i=Object.keys(s);if(t.proofreading){const d=i.filter(h=>!["approved","covered"].includes(t.proofreading?.[h]?.status??""));this.status.textContent=d.length===0?e.proofreadAll:e.proofreadPending.replace("{names}",d.map(h=>this.speakerName(t,h)).join(", ")),this.status.hidden=!1}else this.status.hidden=!0;const a=[];let n,l=!1,c,o;r.forEach((d,h)=>{const u=d.redacted?JSON.stringify(d.redacted.reason):void 0;if(u!==void 0&&c?.reason===u){this.blocks.set(h,c.block),d.speaker!==o&&(o=void 0);return}const p=document.createElement("div");p.className="turn",p.dataset.segment=String(h);const g=document.createElement("div");g.className="who";const x=document.createElement("span");if(x.textContent=d.redacted?"":this.speakerName(t,d.speaker),d.start!==void 0&&(p.dataset.time=b.clock(d.start,!0)),o!==d.speaker&&(n=document.createElement("div"),n.className="intervention",n.style.setProperty("--speaker-hue",String((Math.max(0,i.indexOf(d.speaker))*67+210)%360)),a.push(n),l=!1),d.redacted||(l&&p.classList.add("goes-on"),l=!0),n.append(p),o=d.speaker,g.append(x),d.redacted){p.classList.add("is-redacted");const v=this.gap(d.redacted.reason,"p");v.className="redacted",c={block:p,reason:u},p.append(g,v)}else{const v=document.createElement("p");if(v.className="said",d.parts){let k="";for(const w of d.parts){const M="redacted"in w?"▮":b.plain(w.text);/[\p{L}\p{N}.,;:!?)»”…▮]$/u.test(k)&&/^[\p{L}\p{N}(«“▮]/u.test(M)&&v.append(" "),"redacted"in w?v.append(this.gap(w.redacted.reason,"span")):v.append(...this.saidNodes(w.text)),k=M}}else v.append(...this.saidNodes(d.text??""));c=void 0,p.append(g,v)}if(d.refs?.length){const v=document.createElement("div");v.className="refs";for(const k of d.refs){const w=document.createElement("button");w.type="button",w.className="ref",w.innerHTML=z.PLAY,w.append(b.clock(k.at,!0)),w.addEventListener("click",()=>this.seek(k,d)),v.append(w)}p.append(v)}this.blocks.set(h,p)}),this.turns.replaceChildren(...a)}revealSegment(e){const t=this.blocks.get(e);t&&(t.scrollIntoView?.({block:"center"}),t.classList.add("flash"),window.setTimeout(()=>t.classList.remove("flash"),1600))}}function Y(){customElements.get(F)||customElements.define(F,R)}class f{static partsOf(e){return e.parts?e.parts:e.redacted?[]:[{text:e.text??""}]}static shownRanges(e){const t=[];let r="",s=0;return e.forEach((i,a)=>{const n="redacted"in i?"▮":b.plain(i.text);/[\p{L}\p{N}.,;:!?)»”…▮]$/u.test(r)&&/^[\p{L}\p{N}(«“▮]/u.test(n)&&(s+=1);const l="redacted"in i?0:n.length;t.push({part:a,from:s,to:s+l}),s+=l,r=n}),t}static words(e){return e.trim()===""?0:e.trim().split(/\s+/u).length}static redact(e,t,r,s){const i=[...f.partsOf(e)],a=f.shownRanges(i).find(x=>!("redacted"in i[x.part])&&t>=x.from&&r<=x.to);if(!a)return;const n=b.plain(i[a.part].text),l=/[\p{L}\p{N}'’-]/u;let c=t-a.from,o=r-a.from;for(;c>0&&l.test(n[c-1])&&l.test(n[c]);)c--;for(;o<n.length&&l.test(n[o])&&l.test(n[o-1]);)o++;const d=n.slice(c,o);if(d.trim()==="")return;const h=n.slice(0,c).trimEnd(),u=n.slice(o).trimStart(),p=[...h!==""?[{text:h}]:[],{redacted:{reason:s,words:f.words(d)}},...u!==""?[{text:u}]:[]],g=i.slice(0,a.part).filter(x=>"redacted"in x).length;return i.splice(a.part,1,...p),f.setParts(e,i),{text:d.trim(),nth:g}}static redactWhole(e,t){const r=JSON.stringify({text:e.text,parts:e.parts}),s=f.partsOf(e).reduce((i,a)=>i+("redacted"in a?a.redacted.words??0:f.words(b.plain(a.text))),0);if(delete e.text,delete e.parts,e.redacted={reason:t,...s>0?{words:s}:{}},e.refs)for(const i of e.refs)delete i.range;return r}static restoreWhole(e,t){const{text:r,parts:s}=JSON.parse(t);delete e.redacted,s?e.parts=s:e.text=r??""}static restorePart(e,t,r){const s=[...f.partsOf(e)];let i=-1;const a=s.findIndex(n=>"redacted"in n&&++i===t);a!==-1&&(s.splice(a,1,{text:r}),f.setParts(e,s))}static raw(e,t=()=>{}){let r=-1,s="",i="";for(const a of f.partsOf(e)){const n="redacted"in a?`⟦${t(++r)??"…"}⟧`:a.text;s!==""&&!/\s$/u.test(i)&&!/^\s/u.test(n)&&(s+=" "),s+=n,i=n}return s}static fromRaw(e,t,r){const s=f.partsOf(e).filter(l=>"redacted"in l),i=[],a=new Map;let n=-1;return t.split(/⟦([^⟧]*)⟧/u).forEach((l,c)=>{if(c%2===0){l.trim()!==""&&i.push({text:l.trim()});return}n++;const o=l.trim();o===""||o==="…"||o==="..."?i.push({redacted:s[n]?.redacted??{reason:r}}):(i.push({redacted:{reason:r,words:f.words(o)}}),a.set(n,o))}),delete e.redacted,f.setParts(e,i),a}static setParts(e,t){const r=[];for(const s of t){const i=r[r.length-1],a=!("redacted"in s)&&/^[,.;:!?)»”…]/u.test(s.text)?"":" ";i&&!("redacted"in i)&&!("redacted"in s)?r[r.length-1]={text:`${i.text}${a}${s.text}`.replace(/\s+/gu," ").trim()}:r.push(s)}if(r.some(s=>"redacted"in s)){if(e.parts=r,delete e.text,e.refs)for(const s of e.refs)delete s.range}else e.text=r.map(s=>s.text).join(" "),delete e.parts}}class B{constructor(e,t,r){this.host=t,this.messages=r,e.classList.add("player"),e.innerHTML=`<div class="player-video" hidden></div>
|
|
30
|
+
<div class="player-bar">
|
|
31
|
+
<button type="button" class="icon-btn player-play" disabled>${y.PLAY}</button>
|
|
32
|
+
<span class="player-time">0:00</span>
|
|
33
|
+
<div class="speaker-track" role="slider" tabindex="0" aria-valuemin="0"></div>
|
|
34
|
+
<span class="player-time player-end">0:00</span>
|
|
35
|
+
<button type="button" class="pill-btn player-recordings"></button>
|
|
36
|
+
</div>
|
|
37
|
+
<p class="player-empty"></p>
|
|
38
|
+
<dialog class="recordings-window"><h3></h3><div class="recording-rows"></div><button type="button" class="pill-btn recording-add">${y.PLUS}<span></span></button></dialog>`,this.play=e.querySelector(".player-play"),this.time=e.querySelector(".player-time"),this.end=e.querySelector(".player-end"),this.track=e.querySelector(".speaker-track"),this.video=e.querySelector(".player-video"),this.empty=e.querySelector(".player-empty"),this.open=e.querySelector(".player-recordings"),this.window=e.querySelector(".recordings-window"),this.play.addEventListener("click",()=>{this.media&&(this.media.paused?this.media.play().catch(()=>{}):this.media.pause())}),this.track.addEventListener("pointerdown",s=>{const i=this.track.getBoundingClientRect();i.width>0&&this.seek((s.clientX-i.left)/i.width*this.duration)}),this.track.addEventListener("keydown",s=>{(s.key==="ArrowRight"||s.key==="ArrowLeft")&&this.seek(this.now+(s.key==="ArrowRight"?5:-5))}),this.open.addEventListener("click",()=>this.showWindow()),e.querySelector(".recording-add").addEventListener("click",()=>this.edit(s=>s.push({kind:"audio",src:""}))),O.dialog(this.window,r.close,()=>this.window.close())}static CSS=`
|
|
39
|
+
.player { margin: 0 0 4px; border-radius: 12px; }
|
|
40
|
+
.player-video { aspect-ratio: 16 / 9; margin-bottom: 8px; border-radius: 10px; overflow: hidden; background: #0b1020; }
|
|
41
|
+
.player-video video { width: 100%; height: 100%; display: block; }
|
|
42
|
+
.player-bar { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--ground-sunken); }
|
|
43
|
+
.player-time { font: 500 13px/1 var(--mono); color: var(--ink-dim); font-variant-numeric: tabular-nums; }
|
|
44
|
+
.speaker-track { position: relative; flex: 1 1 auto; height: 28px; border-radius: 6px; cursor: pointer; overflow: hidden;
|
|
45
|
+
background: repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 4px); }
|
|
46
|
+
.speaker-track .seg { position: absolute; top: 4px; bottom: 4px; border-radius: 2px; }
|
|
47
|
+
.speaker-track .seg[data-role="witness"] { background: #c9a14a; }
|
|
48
|
+
.speaker-track .seg[data-role="interviewer"] { background: #5b8fc4; }
|
|
49
|
+
.speaker-track .seg[data-role="other"] { background: var(--ink-faint); }
|
|
50
|
+
.speaker-track .seg.redacted { background: repeating-linear-gradient(135deg, var(--ink-faint) 0 3px, transparent 3px 6px); }
|
|
51
|
+
.speaker-track .head { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: #f5c451; }
|
|
52
|
+
.player-empty { margin: 6px 2px 0; font-size: 13px; color: var(--ink-faint); }
|
|
53
|
+
.recordings-window { max-width: min(36em, 94vw); padding: 18px 20px; border: 1px solid var(--line-strong); border-radius: 12px; background: var(--ground-raised); color: var(--ink); }
|
|
54
|
+
.recordings-window::backdrop { background: rgba(7, 10, 18, .5); }
|
|
55
|
+
.recordings-window h3 { margin: 0 0 12px; font: 600 19px/1.3 var(--serif); }
|
|
56
|
+
.recording-row { display: grid; grid-template-columns: 8em minmax(0, 1fr) 6em auto; gap: 8px; align-items: end; margin-bottom: 10px; }
|
|
57
|
+
.recording-row label { display: flex; flex-direction: column; gap: 4px; font: 600 12px/1.3 var(--sans); color: var(--ink-dim); }
|
|
58
|
+
.recording-row input, .recording-row select { box-sizing: border-box; width: 100%; font-weight: 400; }
|
|
59
|
+
.recording-file { display: flex; gap: 6px; }
|
|
60
|
+
.recording-status { grid-column: 1 / -1; margin: -4px 0 0; font-size: 12px; color: var(--ink-faint); }
|
|
61
|
+
.recording-status.error { color: var(--error); }
|
|
62
|
+
`;json;base;media;mediaFor="";picked=new Map;messages;play;time;end;track;video;empty;open;window;setMessages(e){this.messages=e,this.render()}show(e,t){this.json=e,this.base=t,this.render()}get now(){return this.media?Math.max(0,this.media.currentTime-(this.recordings[0]?.offset??0)):this.position}seek(e){this.position=Math.min(this.duration,Math.max(0,e)),this.media&&(this.media.currentTime=this.position+(this.recordings[0]?.offset??0)),this.placeHead(),this.host.timeChanged(this.position)}position=0;get recordings(){return Array.isArray(this.json?.recordings)?this.json.recordings:[]}get duration(){const e=this.media&&Number.isFinite(this.media.duration)?this.media.duration-(this.recordings[0]?.offset??0):0,t=Math.max(0,...(this.json?.segments??[]).map(r=>r.end??r.start??0));return Math.max(1,e,t)}render(){const e=this.messages,t=this.recordings;this.open.innerHTML='<svg class="icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M6 12V3.5l7-1.5V10.5"/><circle cx="4.5" cy="12" r="1.5"/><circle cx="11.5" cy="10.5" r="1.5"/></svg>',this.open.append(e.recordings.replace("{n}",String(t.length))),this.empty.textContent=t.length===0?e.noRecording:"",this.empty.hidden=t.length>0,this.play.title=e.play,this.play.setAttribute("aria-label",e.play),this.track.setAttribute("aria-label",e.recordingsTitle),this.ensureMedia(),this.drawTrack(),this.window.open&&this.drawRows()}ensureMedia(){const e=this.recordings[0],t=e?`${e.kind}|${e.src}`:"";if(t===this.mediaFor||(this.mediaFor=t,this.media?.pause(),this.media=void 0,this.video.replaceChildren(),this.video.hidden=!0,this.play.disabled=!0,!e||e.src===""))return;const r=document.createElement(e.kind==="video"?"video":"audio");r.preload="metadata",r.src=this.urlOf(e.src),r.addEventListener("loadedmetadata",()=>this.drawTrack()),r.addEventListener("timeupdate",()=>{this.placeHead(),this.host.timeChanged(this.now)});const s=()=>{const i=!r.paused;this.play.innerHTML=i?y.PAUSE:y.PLAY;const a=i?this.messages.pause:this.messages.play;this.play.title=a,this.play.setAttribute("aria-label",a)};r.addEventListener("play",s),r.addEventListener("pause",s),e.kind==="video"&&(this.video.append(r),this.video.hidden=!1),this.media=r,this.play.disabled=!1}urlOf(e){const t=this.picked.get(e);if(t)return t;try{return new URL(e,this.base??location.href).href}catch{return e}}drawTrack(){const e=this.json,t=this.duration,r=(e?.segments??[]).filter(i=>i.start!==void 0);this.track.replaceChildren(...r.map(i=>{const a=document.createElement("span"),n=e?.speakers?.[i.speaker]?.role;a.className=i.redacted?"seg redacted":"seg",a.dataset.role=n==="witness"||n==="interviewer"?n:"other";const l=i.start??0,c=i.end??l+1;return a.style.left=`${l/t*100}%`,a.style.width=`${Math.max(.3,(c-l)/t*100)}%`,a}));const s=document.createElement("span");s.className="head",this.track.append(s),this.track.setAttribute("aria-valuemax",String(Math.round(t))),this.end.textContent=b.clock(t),this.placeHead()}placeHead(){const e=this.now,t=this.track.querySelector(".head");t&&(t.style.left=`${Math.min(e,this.duration)/this.duration*100}%`),this.time.textContent=b.clock(Math.floor(e)),this.track.setAttribute("aria-valuenow",String(Math.round(e)))}showWindow(){this.drawRows(),typeof this.window.showModal=="function"?this.window.showModal():this.window.setAttribute("open","")}drawRows(){const e=this.messages;this.window.querySelector("h3").textContent=e.recordingsTitle,this.window.querySelector(".recording-add span").textContent=e.recordingAdd,O.dialog(this.window,e.close,()=>this.window.close()),this.window.querySelector(".recording-rows").replaceChildren(...this.recordings.map((r,s)=>{const i=document.createElement("div");i.className="recording-row";const a=document.createElement("select");a.append(new Option(e.recordingAudio,"audio"),new Option(e.recordingVideo,"video")),a.value=r.kind,a.addEventListener("change",()=>this.edit(p=>{p[s].kind=a.value}));const n=document.createElement("input");n.type="text",n.value=r.src,n.placeholder="interview.mp3",n.addEventListener("change",()=>this.edit(p=>{p[s].src=n.value.trim()}));const l=document.createElement("input");l.type="file",l.accept="audio/*,video/*",l.hidden=!0,l.addEventListener("change",()=>{const p=l.files?.[0];p&&(this.picked.set(p.name,URL.createObjectURL(p)),this.edit(g=>{g[s].src=p.name,p.type.startsWith("video/")&&(g[s].kind="video")}))});const c=document.createElement("button");c.type="button",c.className="icon-btn",c.title=e.recordingFile,c.setAttribute("aria-label",e.recordingFile),c.innerHTML='<svg class="icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M2.5 4.5h4l1.5 1.5h5.5v6.5h-11z"/></svg>',c.addEventListener("click",()=>l.click());const o=document.createElement("span");o.className="recording-file",o.append(n,c,l);const d=document.createElement("input");d.type="number",d.step="0.1",d.value=r.offset!==void 0?String(r.offset):"",d.placeholder="0",d.addEventListener("change",()=>this.edit(p=>{const g=Number(d.value);d.value.trim()===""||!Number.isFinite(g)||g===0?delete p[s].offset:p[s].offset=g}));const h=document.createElement("button");h.type="button",h.className="icon-btn",h.innerHTML=y.TRASH,h.title=e.recordingRemove,h.setAttribute("aria-label",e.recordingRemove),h.addEventListener("click",()=>this.edit(p=>{p.splice(s,1)}));const u=document.createElement("p");return u.className="recording-status",this.check(r,u),i.append(this.labelled(e.recordingKind,a),this.labelled(e.recordingFile,o),this.labelled(e.recordingOffset,d),h,u),i}))}labelled(e,t){const r=document.createElement("label"),s=document.createElement("span");return s.textContent=e,r.append(s,t),r}check(e,t){if(e.src==="")return;const r=document.createElement(e.kind==="video"?"video":"audio");r.preload="metadata",r.addEventListener("loadedmetadata",()=>{t.textContent=b.clock(Math.round(r.duration)),t.classList.remove("error")}),r.addEventListener("error",()=>{t.textContent=this.messages.loadFailed,t.classList.add("error")}),r.src=this.urlOf(e.src)}edit(e){const t=structuredClone(this.recordings);e(t),this.host.recordingsChanged(t)}}const $="rr0-interview-editor",K=`
|
|
63
|
+
<style>
|
|
64
|
+
:host { display: block; }
|
|
65
|
+
/* The colours of the transcript's text editor (see SightingFileEditor): a key, a string, a number or a word, and a mistake. Dark mode redefines them. */
|
|
66
|
+
:host { --file-key: #1a5fb4; --file-string: #26662f; --file-literal: #a5321f; --rr0-alert: #c33; }
|
|
67
|
+
@media (prefers-color-scheme: dark) { :host { --file-key: #8cb8ff; --file-string: #8fd39a; --file-literal: #ffa08a; } }
|
|
68
|
+
[hidden] { display: none !important; }
|
|
69
|
+
/* Two groups as the recording's editor has its own (see sightingEditorTemplate): the open tab raised and joined to its panel. */
|
|
70
|
+
.group-tabs { --tab-line: color-mix(in srgb, CanvasText 35%, transparent); --tab-surface: color-mix(in srgb, CanvasText 5%, Canvas);
|
|
71
|
+
--tab-recessed: color-mix(in srgb, CanvasText 11%, Canvas); --tab-accent: #4a9eff;
|
|
72
|
+
display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0; margin: 0; padding: 0; border-bottom: 1px solid var(--tab-line); }
|
|
73
|
+
.group-tab { font: inherit; font-weight: 600; cursor: pointer; color: color-mix(in srgb, CanvasText 70%, transparent); background: var(--tab-recessed);
|
|
74
|
+
border: 1px solid var(--tab-line); border-radius: 8px 8px 0 0; padding: .4em .6em; margin: 0 0 -1px -1px; position: relative; }
|
|
75
|
+
.group-tab:hover { color: CanvasText; background: color-mix(in srgb, CanvasText 16%, Canvas); }
|
|
76
|
+
.group-tab[aria-expanded="true"] { color: CanvasText; background: var(--tab-surface); border-bottom-color: var(--tab-surface); box-shadow: inset 0 2px 0 var(--tab-accent); z-index: 1; }
|
|
77
|
+
.group-tab:focus-visible { outline: 2px solid #4af; outline-offset: -2px; }
|
|
78
|
+
.group-panel { border: 1px solid var(--tab-line, color-mix(in srgb, CanvasText 35%, transparent)); border-top: 0; border-radius: 0 0 4px 4px;
|
|
79
|
+
background: color-mix(in srgb, CanvasText 5%, Canvas); padding: .5em .75em; margin: 0 0 .5em; }
|
|
80
|
+
.row { display: flex; align-items: center; gap: .5em; flex-wrap: wrap; margin-bottom: .5em; }
|
|
81
|
+
.group-panel > .row:last-child { margin-bottom: 0; }
|
|
82
|
+
label { display: flex; align-items: center; gap: .4em; }
|
|
83
|
+
label.wide { flex: 1 1 100%; align-items: flex-start; }
|
|
84
|
+
label.wide textarea { flex: 1 1 auto; min-width: 0; min-height: 9em; }
|
|
85
|
+
label.fill { flex: 1 1 100%; }
|
|
86
|
+
label.fill input { flex: 1 1 auto; }
|
|
87
|
+
input[type="text"] { min-width: 0; }
|
|
88
|
+
#by { width: 16em; }
|
|
89
|
+
input[type="url"] { width: 18em; max-width: 100%; }
|
|
90
|
+
${D.CSS}
|
|
91
|
+
select { min-width: 0; max-width: 100%; text-overflow: ellipsis; }
|
|
92
|
+
fieldset.witnesses { display: flex; flex-wrap: wrap; align-items: center; gap: .25em .75em; border: 0; margin: 0; padding: 0; min-width: 0; }
|
|
93
|
+
fieldset.witnesses legend { float: left; padding: 0; margin-right: .4em; }
|
|
94
|
+
#exchanges { --rr0-interview-max-height: 32em; --rr0-interview-overflow: auto; }
|
|
95
|
+
.file-note { margin: .3em 0; }
|
|
96
|
+
${q.rules([".file-note"])}
|
|
97
|
+
.file-editor { min-height: 18em; margin-top: .5em; }
|
|
98
|
+
/* ---- The design handoff's look (design_handoff_editeurs_ufoathome, §2 and §5) ---- */
|
|
99
|
+
:host {
|
|
100
|
+
${C.TOKENS}
|
|
101
|
+
--rr0-field-radius: 8px;
|
|
102
|
+
--rr0-input-font-size: 15px;
|
|
103
|
+
container-type: inline-size;
|
|
104
|
+
font: 400 15px/1.5 var(--sans);
|
|
105
|
+
color: var(--ink);
|
|
106
|
+
}
|
|
107
|
+
${C.HEAD}
|
|
108
|
+
${C.fields(".interview-app")}
|
|
109
|
+
.recordings-window :is(button, input, select) { font: inherit; }
|
|
110
|
+
.recordings-window .pill-btn { min-height: 36px; }
|
|
111
|
+
/* Its parts, underlined, as the case's are. */
|
|
112
|
+
#tabs { display: flex; gap: 6px; padding: 0; border-bottom: 1px solid var(--line); }
|
|
113
|
+
#tabs .group-tab {
|
|
114
|
+
display: inline-flex; align-items: center; gap: 8px; min-height: 0; margin: 0 0 -1px; padding: 12px 10px;
|
|
115
|
+
border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: none; box-shadow: none; color: var(--ink-dim); font: 600 15px/1.2 var(--sans);
|
|
116
|
+
}
|
|
117
|
+
#tabs .group-tab:hover { background: none; color: var(--ink); }
|
|
118
|
+
#tabs .group-tab[aria-expanded="true"] { color: var(--ink); border-bottom-color: var(--glow-solid); background: none; box-shadow: none; }
|
|
119
|
+
.interview-app > .group-panel { margin: 0; padding: 18px 0 0; border: 0; border-radius: 0; background: none; color: var(--ink); }
|
|
120
|
+
/* Fields: the label above, the value under it, on a grid that fills the width; the title and what was established the whole width. */
|
|
121
|
+
#group-summary { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px 16px; }
|
|
122
|
+
#group-summary > .row { display: contents; }
|
|
123
|
+
#group-summary label, #group-transcript label { display: flex; flex-direction: column; align-items: stretch; gap: 6px; font: 600 13px/1.3 var(--sans); color: var(--ink-dim); }
|
|
124
|
+
#group-summary :is(label.fill, label.wide) { grid-column: 1 / -1; }
|
|
125
|
+
#group-summary :is(input, select, textarea), #group-transcript input[type="text"] { box-sizing: border-box; width: 100%; font-weight: 400; }
|
|
126
|
+
#group-summary input[type="text"], #group-transcript input[type="text"] { height: 38px; }
|
|
127
|
+
#group-summary textarea { min-height: 9em; }
|
|
128
|
+
fieldset.witnesses { flex-direction: column; align-items: flex-start; gap: 6px; font: 600 13px/1.3 var(--sans); color: var(--ink-dim); }
|
|
129
|
+
#group-summary fieldset.witnesses label { flex-direction: row; align-items: center; gap: 8px; font-weight: 400; color: var(--ink); }
|
|
130
|
+
/* The exchanges, one card an intervention, the speaker's colour down its side: a list that scrolls past 520 px (440 on a phone). */
|
|
131
|
+
#exchanges { --rr0-interview-max-height: 520px; --rr0-interview-line: var(--line-strong); }
|
|
132
|
+
#exchanges .rr0-interview-turns { padding-right: 4px; }
|
|
133
|
+
#exchanges .intervention { margin: 0 0 10px; padding: 6px 4px; border: 1px solid var(--line-strong); border-left: 3px solid var(--speaker); border-radius: 10px; background: var(--ground); }
|
|
134
|
+
#exchanges .intervention:hover { background: var(--ground-sunken); }
|
|
135
|
+
#exchanges .turn .who { display: inline-block; margin-bottom: 4px; padding: 1px 9px; border-radius: 999px; background: color-mix(in srgb, var(--speaker) 18%, transparent); color: var(--ink); font: 700 12px/1.5 var(--sans); }
|
|
136
|
+
#exchanges .turn .said { font-size: 15px; line-height: 1.55; color: var(--ink); }
|
|
137
|
+
#exchanges .turn .ref { border-color: var(--glow-dim); background: var(--warn-bg); color: var(--ink); font: 600 12px/1.6 var(--sans); padding: 1px 9px; }
|
|
138
|
+
#exchanges .turn.flash { background: var(--warn-bg); }
|
|
139
|
+
#exchanges .rr0-interview-status { padding: 8px 12px; border-radius: 8px; background: var(--warn-bg); color: var(--ink-dim); font-size: 13px; }
|
|
140
|
+
#group-transcript > .row { margin-bottom: 12px; }
|
|
141
|
+
@container (max-width: 640px) { #exchanges { --rr0-interview-max-height: 440px; } }
|
|
142
|
+
${B.CSS}
|
|
143
|
+
${O.CSS}
|
|
144
|
+
${U.CSS}
|
|
145
|
+
${y.CSS}
|
|
146
|
+
/* Who has proofread it, said once above the exchanges, with a box each to say they have (see renderReview); the reader's own line goes. */
|
|
147
|
+
#exchanges .rr0-interview-status { display: none; }
|
|
148
|
+
.review { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin: 0 0 10px; padding: 10px 14px;
|
|
149
|
+
border-radius: 10px; background: var(--warn-bg); font-size: 13px; color: var(--ink-dim); }
|
|
150
|
+
.review[data-done] { background: var(--neutral-bg); }
|
|
151
|
+
.review-boxes { display: flex; flex-wrap: wrap; gap: 14px; }
|
|
152
|
+
.review-boxes label { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); }
|
|
153
|
+
.redact-row { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
|
|
154
|
+
.redact-note { font-size: 13px; color: var(--ink-faint); }
|
|
155
|
+
.redact-note.error { color: var(--error); }
|
|
156
|
+
/* Each turn: its time, which plays from there; what is taken out as a label that says how much, and puts it back while it is known. */
|
|
157
|
+
#exchanges .turn { display: grid; grid-template-columns: 7.5em minmax(0, 1fr); column-gap: 14px; padding: 8px 10px; }
|
|
158
|
+
#exchanges .turn > .turn-time { grid-row: 1; grid-column: 1; }
|
|
159
|
+
#exchanges .turn > .who { grid-column: 1; align-self: start; }
|
|
160
|
+
#exchanges .turn > :not(.who, .turn-time) { grid-column: 2; }
|
|
161
|
+
#exchanges .turn > .said, #exchanges .turn > .redacted { grid-row: 1 / span 2; }
|
|
162
|
+
#exchanges .turn.goes-on > .who, #exchanges .turn.is-redacted > .who { display: block; visibility: hidden; }
|
|
163
|
+
/* The time is on the turn itself here: the reader's tooltip of it would say it twice. */
|
|
164
|
+
#exchanges .turn[data-time]::after { content: none !important; display: none !important; }
|
|
165
|
+
.turn-time { justify-self: start; min-height: 0; padding: 0; border: 0; background: none; color: var(--sky); font: 600 13px/1.4 var(--mono); cursor: pointer; }
|
|
166
|
+
.turn-time:hover:not(:disabled) { background: none; text-decoration: underline; }
|
|
167
|
+
#exchanges .bar.redacted-label { width: auto; height: auto; padding: 0 8px; border: 1px dashed var(--line-strong); border-radius: 999px; background: none; color: var(--ink-faint);
|
|
168
|
+
font: 600 12px/1.6 var(--sans); vertical-align: baseline; cursor: default; }
|
|
169
|
+
#exchanges .bar.redacted-label[data-restorable] { cursor: pointer; }
|
|
170
|
+
#exchanges .bar.redacted-label[data-restorable]:hover { border-color: var(--glow-dim); color: var(--ink); }
|
|
171
|
+
.turn-tools { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 12px; margin-top: 6px; }
|
|
172
|
+
.turn-tools button { min-height: 0; padding: 2px 4px; border: 0; background: none; color: var(--ink-faint); font: 600 13px/1.4 var(--sans); }
|
|
173
|
+
.turn-tools button:hover:not(:disabled) { background: none; color: var(--ink); }
|
|
174
|
+
.turn-tools .icon-btn { min-width: 0; }
|
|
175
|
+
#exchanges .turn.current { background: var(--warn-bg); border-radius: 8px; }
|
|
176
|
+
#exchanges .intervention:has(.turn.current) { border-color: var(--glow-dim); }
|
|
177
|
+
#exchanges .turn .refs { align-items: center; }
|
|
178
|
+
#exchanges .turn .ref { display: inline-block; max-width: calc(100% - 2em); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
179
|
+
#exchanges .turn .ref .moment-letter { display: inline-grid; place-items: center; width: 1.4em; height: 1.4em; margin-right: 4px; border-radius: 50%; background: var(--glow-solid); color: var(--glow-on-solid); font: 700 11px/1 var(--sans); }
|
|
180
|
+
#exchanges .turn .ref-unlink { min-height: 0; padding: 0 4px; border: 0; background: none; color: var(--ink-faint); font: 600 13px/1 var(--sans); }
|
|
181
|
+
.turn-edit { display: flex; flex-direction: column; gap: 6px; }
|
|
182
|
+
.turn-edit textarea { box-sizing: border-box; width: 100%; min-height: 6em; }
|
|
183
|
+
.turn-edit .hint { font-size: 12px; color: var(--ink-faint); }
|
|
184
|
+
.turn-edit .buttons { display: flex; gap: 8px; }
|
|
185
|
+
</style>
|
|
186
|
+
<div class="interview-app">
|
|
187
|
+
<!-- The player: what plays the interview's recordings, with who speaks along it (see InterviewPlayer). -->
|
|
188
|
+
<div id="player"></div>
|
|
189
|
+
<div id="tabs" class="group-tabs">
|
|
190
|
+
<button class="group-tab" type="button" aria-controls="group-summary" aria-expanded="true"><span id="label-summary-group">Summary</span></button>
|
|
191
|
+
<button class="group-tab" type="button" aria-controls="group-exchanges" aria-expanded="false"><span id="label-exchanges-group">Exchanges</span></button>
|
|
192
|
+
<button class="group-tab" type="button" aria-controls="group-transcript" aria-expanded="false"><span id="label-file-group">File</span></button>
|
|
193
|
+
</div>
|
|
194
|
+
<section class="group-panel" id="group-summary" aria-labelledby="label-summary-group">
|
|
195
|
+
<div class="row">
|
|
196
|
+
<label class="fill"><span id="label-title">Title</span> <input id="title" type="text"/></label>
|
|
197
|
+
</div>
|
|
198
|
+
<div class="row">
|
|
199
|
+
<fieldset id="witness" class="witnesses"><legend id="label-witness">Witness</legend></fieldset>
|
|
200
|
+
<label><span id="label-medium">Medium</span> <select id="medium"></select></label>
|
|
201
|
+
<label><span id="label-time">When</span> <input id="time" type="text" size="16" placeholder="2026-10-13 21:27"/></label>
|
|
202
|
+
<label><span id="label-by">Interviewer</span> <input id="by" type="text" autocomplete="off" spellcheck="false"/></label>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="row">
|
|
205
|
+
<label class="wide"><span id="label-summary">What it established</span> <textarea id="summary"></textarea></label>
|
|
206
|
+
</div>
|
|
207
|
+
</section>
|
|
208
|
+
<section class="group-panel" id="group-exchanges" aria-labelledby="label-exchanges-group" hidden>
|
|
209
|
+
<div id="review" class="review" hidden></div>
|
|
210
|
+
<div class="redact-row">
|
|
211
|
+
<button id="redact-selection" type="button" class="pill-btn">Take out the selection</button>
|
|
212
|
+
<span id="redact-note" class="redact-note" role="status"></span>
|
|
213
|
+
</div>
|
|
214
|
+
<rr0-interview id="exchanges"></rr0-interview>
|
|
215
|
+
</section>
|
|
216
|
+
<section class="group-panel" id="group-transcript" aria-labelledby="label-file-group" hidden>
|
|
217
|
+
<div class="row">
|
|
218
|
+
<label class="fill"><span id="label-url">Transcript</span> <input id="url" type="text" autocomplete="off" spellcheck="false" placeholder="interview-….json"/></label>
|
|
219
|
+
</div>
|
|
220
|
+
<div class="row toolbar">
|
|
221
|
+
<span class="input-file-row"><span id="label-import-file">Load a file (JSON, text, WebVTT, SRT)</span> <rr0-input-file id="import" name="import" accept="application/json,.json,.txt,.md,.vtt,.srt,text/*" placeholder="https://…/interview.json"></rr0-input-file></span>
|
|
222
|
+
<button id="save" type="button">Save</button>
|
|
223
|
+
</div>
|
|
224
|
+
<p id="file-note" class="file-note" hidden role="status"></p>
|
|
225
|
+
<div id="file-editor" class="file-editor"></div>
|
|
226
|
+
</section>
|
|
227
|
+
</div>
|
|
228
|
+
`;class m extends HTMLElement{shadow=this.attachShadow({mode:"open"});get importInput(){return this.shadow.getElementById("import")}messages=S;said=new L(["en"]);language="en";localeToken=0;current;options=[];group="summary";base;text;fileEditor;fileEditorLoading;shownFor;player;drawn;takenOut=new Map;constructor(){super(),this.shadow.innerHTML=K,customElements.upgrade(this.shadow),this.importInput.build();for(const e of["title","time","by","url","summary","witness","medium"])this.shadow.getElementById(e).addEventListener(e==="witness"||e==="medium"?"change":"input",()=>this.write(e));for(const e of this.shadow.querySelectorAll("#tabs .group-tab"))e.addEventListener("click",()=>this.openGroup(m.GROUPS[e.getAttribute("aria-controls")]??"summary"));this.shadow.getElementById("url").addEventListener("change",()=>{this.shownFor=void 0,this.text===void 0&&this.group==="file"&&this.showTranscript()}),this.importInput.addEventListener("filepick",e=>{const t=e.detail;t.file?this.importFromFile(t.file):this.importFromUrl(t.url)}),this.shadow.getElementById("save").addEventListener("click",()=>this.save()),this.player=new B(this.shadow.getElementById("player"),{timeChanged:e=>this.markCurrentTurn(e),recordingsChanged:e=>void this.editTranscript(t=>{e.length===0?delete t.recordings:t.recordings=e})},this.messages),this.shadow.getElementById("redact-selection").addEventListener("click",()=>void this.redactSelection()),this.shadow.getElementById("exchanges").addEventListener("click",e=>{const t=e.target.closest(".bar[data-restorable]");t&&this.restore(t.dataset.restorable)})}static GROUPS={"group-summary":"summary","group-exchanges":"exchanges","group-transcript":"file"};static get observedAttributes(){return["readonly"]}attributeChangedCallback(){this.applyReadonly()}connectedCallback(){this.loadLocale()}disconnectedCallback(){queueMicrotask(()=>{this.isConnected||this.releaseFileEditor()})}releaseFileEditor(){this.fileEditor&&(this.text=this.fileEditor.text,this.fileEditor.destroy(),this.fileEditor=void 0,this.fileEditorLoading=void 0,this.shownFor=void 0)}get event(){return this.current}set event(e){e!==this.current&&(this.shownFor=void 0),this.current=e,this.render(),this.takenOut.clear(),this.group==="file"&&this.showTranscript(),queueMicrotask(()=>{this.current===e&&this.showExchanges()})}set witnesses(e){this.options=e,this.render()}set documentUrl(e){this.base=e}get transcriptText(){return this.text}set transcriptText(e){this.text=e,this.shownFor=void 0}field(e){return this.shadow.getElementById(e)}async loadLocale(){const e=++this.localeToken,t=j.preferencesFor(this),r=P(t,H),s=r==="en"?S:await I(r);e===this.localeToken&&(this.language=r,this.said=new L(t),this.messages=s,this.render())}applyReadonly(){const e=this.hasAttribute("readonly");for(const t of["title","time","by","url","summary"])this.field(t).readOnly=e;for(const t of this.shadow.querySelectorAll("#witness input"))t.disabled=e;this.field("medium").disabled=e,this.importInput.disabled=e}static byText(e){return(e??[]).map(t=>"people"in t?t.people:"org"in t?t.org:t.title??"").filter(t=>t!=="").join(", ")}render(){const e=this.messages,t=(o,d)=>{this.shadow.getElementById(o).textContent=d};t("label-summary-group",e.summaryTab),t("label-file-group",e.fileTab),t("label-exchanges-group",e.exchangesTab),t("label-title",e.title),t("label-witness",e.witness),t("label-medium",e.medium),t("label-time",e.time),t("label-by",e.by),t("label-summary",e.summary),t("label-url",e.transcript),t("label-import-file",e.importFile),t("redact-selection",e.redactSelection),this.player?.setMessages(e),this.importInput.messages=e,t("save",e.saveButton),this.field("url").title=e.transcriptHint,this.field("by").title=e.byHint;const r=this.current,s=this.shadow.activeElement,i=(o,d)=>{this.field(o)!==s&&(this.field(o).value=d)};i("title",this.said.read(r?.title)??""),i("time",r?.time??""),i("by",m.byText(r?.by)),i("url",r?.url??""),i("summary",this.said.read(r?.summary)??"");const a=[r?.interviewOf].flat().filter(o=>typeof o=="string"),n=this.shadow.getElementById("witness"),l=[...this.options,...a.filter(o=>!this.options.some(d=>d.id===o)).map(o=>({id:o,label:o}))];n.replaceChildren(n.querySelector("legend"),...l.map(o=>{const d=document.createElement("label"),h=document.createElement("input");return h.type="checkbox",h.value=o.id,h.checked=a.includes(o.id),d.append(h,o.label),d}));const c=this.shadow.getElementById("medium");if(c.replaceChildren(...N.ALL.map(o=>new Option(N.label(o,this.language),o))),r?.medium!==void 0&&!N.ALL.includes(r.medium)&&c.append(new Option(String(r.medium),String(r.medium))),r?.medium===void 0){const o=new Option(e.witnessNone,"");o.disabled=!0,o.hidden=!0,c.prepend(o)}c.value=r?.medium??"",this.applyReadonly()}write(e){const t=this.current;if(!t)return;const r=e==="witness"?"":this.field(e).value;switch(e){case"title":{const s=this.said.write(t.title,r,this.language);s===void 0?delete t.title:t.title=s;break}case"summary":{const s=this.said.write(t.summary,r,this.language);s===void 0?delete t.summary:t.summary=s;break}case"time":r.trim()===""?delete t.time:t.time=r.trim();break;case"url":r.trim()===""?delete t.url:t.url=r.trim();break;case"by":{const s=r.split(",").map(i=>i.trim()).filter(i=>i!=="");s.length===0?delete t.by:t.by=s.map(i=>({people:i}));break}case"witness":{const s=[...this.shadow.querySelectorAll("#witness input:checked")].map(i=>i.value);if(s.length===0){this.render();return}t.interviewOf=s.length===1?s[0]:s;break}case"medium":r===""?delete t.medium:t.medium=r;break}this.dispatchEvent(new CustomEvent(E,{bubbles:!0,composed:!0,detail:{field:e,event:t}})),e==="medium"&&this.render(),e!=="url"&&this.syncFileFromEvent()}openGroup(e){this.group=e;const t={summary:"group-summary",exchanges:"group-exchanges",file:"group-transcript"};for(const r of this.shadow.querySelectorAll("#tabs .group-tab"))r.setAttribute("aria-expanded",String(r.getAttribute("aria-controls")===t[e]));for(const[r,s]of Object.entries(t))this.shadow.getElementById(s).hidden=r!==e;e==="file"&&this.showTranscript(),e==="exchanges"&&this.showExchanges()}exchangesToken=0;async transcriptJson(e){try{const t=this.fileEditor?.text??this.text;if(t!==void 0)return JSON.parse(t);const r=this.transcriptUrl(e);if(r!==void 0)return await T.json(r)}catch{}}async showExchanges(){const e=this.current;if(!e)return;const t=++this.exchangesToken,r=await this.transcriptJson(e);t!==this.exchangesToken||this.current!==e||this.drawExchanges(r)}drawExchanges(e){const t=this.shadow.getElementById("exchanges");t.documentUrl=this.current?this.transcriptUrl(this.current):void 0,t.interview=e,this.drawn=e,this.player.show(e,this.current?this.transcriptUrl(this.current):void 0),this.renderReview(e),this.decorateExchanges(e)}async editTranscript(e){const t=this.current;if(!t||this.hasAttribute("readonly"))return;const r=await this.transcriptJson(t)??JSON.parse(this.template(t));Array.isArray(r.segments)||(r.segments=[]),e(r);const s=m.pretty(m.withEventFields(r,t));this.fileEditor?.replaceText(s,!1),this.onEdited(s)}get redactReason(){return this.said.write(void 0,this.messages.redactReason,this.language)??this.messages.redactReason}speakerLabel(e,t){const r=b.speakerName(e,t),s=e.speakers?.[t]?.role;return r===s&&s in this.messages.roles?this.messages.roles[s]:r}renderReview(e){const t=this.shadow.getElementById("review"),r=Object.keys(e?.speakers??{});if(t.hidden=!e||r.length===0,!e||r.length===0)return;const s=l=>["approved","covered"].includes(e.proofreading?.[l]?.status??""),i=r.filter(l=>!s(l)),a=document.createElement("span");a.textContent=i.length===0?this.messages.proofreadAll:this.messages.proofreadPending.replace("{names}",i.map(l=>this.speakerLabel(e,l)).join(", ")),t.toggleAttribute("data-done",i.length===0);const n=document.createElement("span");n.className="review-boxes";for(const l of r){const c=document.createElement("label"),o=document.createElement("input");o.type="checkbox",o.checked=s(l),o.disabled=this.hasAttribute("readonly"),o.addEventListener("change",()=>void this.editTranscript(d=>{d.proofreading??={},o.checked?d.proofreading[l]={status:"approved",date:new Date().toISOString().slice(0,10)}:d.proofreading[l]={status:"pending"}})),c.append(o,this.messages.reviewedBy.replace("{name}",this.speakerLabel(e,l))),n.append(c)}t.replaceChildren(a,n)}momentsOf(e,t){const r=e.speakers?.[t]?.of??b.sightingsOf(e)[0];return this.options.find(s=>s.id===r)?.moments??this.options.flatMap(s=>s.moments??[])}decorateExchanges(e){if(!e)return;const t=this.messages,r=this.hasAttribute("readonly");for(const s of this.shadow.querySelectorAll("#exchanges .turn[data-segment]")){const i=Number(s.dataset.segment),a=e.segments[i];if(!a)continue;if(a.start!==void 0){const c=document.createElement("button");c.type="button",c.className="turn-time",c.textContent=b.clock(a.start),c.addEventListener("click",()=>this.player.seek(a.start)),s.prepend(c)}const n=a.redacted?[a.redacted]:f.partsOf(a).flatMap(c=>"redacted"in c?[c.redacted]:[]);s.querySelectorAll(".bar").forEach((c,o)=>{const d=n[o]?.words;c.textContent=d!==void 0?t.redactedWords.replace("{n}",String(d)):t.redacted,c.classList.add("redacted-label");const h=a.redacted?`${i}:all`:`${i}:${o}`;this.takenOut.has(h)&&(c.dataset.restorable=h)});const l=this.momentsOf(e,a.speaker);s.querySelectorAll(".ref").forEach((c,o)=>{const d=a.refs?.[o];if(!d)return;const h=l.find(p=>Math.abs(p.at-d.at)<.05);if(h){const p=document.createElement("span");p.className="moment-letter",p.textContent=h.label.slice(0,2),c.replaceChildren(p,t.momentLabel.replace("{k}",h.label).replace("{text}",h.note??b.clock(d.at)))}if(r)return;const u=document.createElement("button");u.type="button",u.className="ref-unlink",u.textContent="×",u.title=t.unlinkMoment,u.setAttribute("aria-label",t.unlinkMoment),u.addEventListener("click",()=>void this.editTranscript(p=>{p.segments[i].refs?.splice(o,1),p.segments[i].refs?.length===0&&delete p.segments[i].refs})),c.after(u)}),r||s.append(this.turnTools(e,i,a,l))}}turnTools(e,t,r,s){const i=this.messages,a=document.createElement("div");a.className="turn-tools";const n=(o,d)=>{const h=document.createElement("button");return h.type="button",h.textContent=o,h.addEventListener("click",d),h};if(e.speakers?.[r.speaker]?.role==="witness"&&!r.redacted){const o=n(i.linkMoment,()=>{});a.append(o),new U(o,`moment-menu-${t}`,h=>void this.editTranscript(u=>{const p=u.segments[t].refs??[];p.some(g=>Math.abs(g.at-Number(h))<.05)||p.push({at:Number(h)}),u.segments[t].refs=p}),h=>`moment-${t}-${h}`).setKinds(s.length>0?s.map(h=>({value:String(h.at),label:i.momentLabel.replace("{k}",h.label).replace("{text}",h.note??b.clock(h.at))})):[{value:"",label:i.noMoments,disabledReason:i.noMoments}])}r.redacted||a.append(n(i.editTurn,()=>this.editTurn(t)));const l=this.takenOut.has(`${t}:all`)||[...this.takenOut.keys()].some(o=>o.startsWith(`${t}:`));if(r.redacted||r.parts&&l){const o=n(i.restoreAll,()=>void this.restoreAll(t));o.disabled=!l,a.append(o)}else a.append(n(i.redactAll,()=>void this.editTranscript(o=>{this.forget(t),this.takenOut.set(`${t}:all`,f.redactWhole(o.segments[t],this.redactReason))})));const c=n("",()=>void this.editTranscript(o=>{o.segments.splice(t,1),this.shiftTakenOut(t)}));return c.className="icon-btn",c.innerHTML=y.TRASH,c.title=i.deleteTurn,c.setAttribute("aria-label",i.deleteTurn),a.append(c),a}async redactSelection(){const e=this.messages,t=this.shadow.getElementById("redact-note"),r=(h,u=!1)=>{t.textContent=h,t.classList.toggle("error",u)},s=this.shadow.getSelection?.()??document.getSelection(),i=s&&s.rangeCount>0?s.getRangeAt(0):void 0;if(!i||i.collapsed){r(e.selectionNone);return}const a=h=>h instanceof Element?h:h.parentElement,n=a(i.startContainer)?.closest(".said");if(!n||a(i.endContainer)?.closest(".said")!==n||a(i.startContainer)?.closest(".bar")||a(i.endContainer)?.closest(".bar")){r(e.selectionOnePassage,!0);return}const l=Number(n.closest(".turn").dataset.segment),c=m.offsetIn(n,i.startContainer,i.startOffset),o=m.offsetIn(n,i.endContainer,i.endOffset);let d=!1;await this.editTranscript(h=>{const u=f.redact(h.segments[l],Math.min(c,o),Math.max(c,o),this.redactReason);u&&(d=!0,this.shiftParts(l,u.nth),this.takenOut.set(`${l}:${u.nth}`,u.text))}),s?.removeAllRanges(),r(d?"":e.selectionOnePassage,!d)}static offsetIn(e,t,r){let s=0;const i=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,{acceptNode:a=>a.parentElement?.closest(".bar")?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT});for(let a=i.nextNode();a;a=i.nextNode()){if(a===t)return s+r;if(t.contains(a)&&t!==a){const l=[...t.childNodes].slice(0,r);return s+l.reduce((c,o)=>c+(o instanceof Element&&o.closest(".bar")?0:(o.textContent??"").length),0)}s+=(a.textContent??"").length}return s}async restore(e){const t=this.takenOut.get(e);if(t===void 0)return;const[r,s]=e.split(":"),i=Number(r);await this.editTranscript(a=>{s==="all"?f.restoreWhole(a.segments[i],t):(f.restorePart(a.segments[i],Number(s),t),this.shiftParts(i,Number(s),-1)),this.takenOut.delete(e)})}async restoreAll(e){if(this.takenOut.has(`${e}:all`)){await this.restore(`${e}:all`);return}const t=[...this.takenOut.keys()].filter(r=>r.startsWith(`${e}:`)).map(r=>Number(r.split(":")[1])).sort((r,s)=>s-r);for(const r of t)await this.restore(`${e}:${r}`)}editTurn(e){const r=this.drawn?.segments[e],s=this.shadow.querySelector(`#exchanges .turn[data-segment="${e}"] .said`);if(!r||!s)return;const i=this.messages,a=document.createElement("div");a.className="turn-edit";const n=document.createElement("textarea");n.value=f.raw(r,h=>this.takenOut.get(`${e}:${h}`));const l=document.createElement("span");l.className="hint",l.textContent=i.turnEditHint;const c=document.createElement("div");c.className="buttons";const o=document.createElement("button");o.type="button",o.className="pill-btn primary",o.textContent=i.saveTurn,o.addEventListener("click",()=>void this.editTranscript(h=>{const u=f.fromRaw(h.segments[e],n.value,this.redactReason);this.forget(e);for(const[p,g]of u)this.takenOut.set(`${e}:${p}`,g)}));const d=document.createElement("button");d.type="button",d.className="pill-btn",d.textContent=i.cancelTurn,d.addEventListener("click",()=>this.drawExchanges(this.drawn)),c.append(o,d),a.append(n,l,c),s.replaceWith(a),n.focus()}forget(e){for(const t of[...this.takenOut.keys()])t.startsWith(`${e}:`)&&this.takenOut.delete(t)}shiftParts(e,t,r=1){const s=[...this.takenOut].filter(([i])=>i.startsWith(`${e}:`)&&i!==`${e}:all`&&Number(i.split(":")[1])>=t+(r<0?1:0));for(const[i]of s)this.takenOut.delete(i);for(const[i,a]of s)this.takenOut.set(`${e}:${Number(i.split(":")[1])+r}`,a)}shiftTakenOut(e){const t=[...this.takenOut];this.takenOut.clear();for(const[r,s]of t){const[i,a]=r.split(":"),n=Number(i);n<e?this.takenOut.set(r,s):n>e&&this.takenOut.set(`${n-1}:${a}`,s)}}markCurrentTurn(e){const t=this.drawn?.segments??[];let r=-1;t.forEach((a,n)=>{a.start!==void 0&&a.start<=e&&(r=n)});for(const a of this.shadow.querySelectorAll("#exchanges .turn.current"))a.classList.remove("current");const s=this.shadow.querySelector(`#exchanges .turn[data-segment="${r}"]`);if(!s)return;s.classList.add("current");const i=s.closest(".rr0-interview-turns");i&&(s.offsetTop<i.scrollTop||s.offsetTop>i.scrollTop+i.clientHeight-s.offsetHeight)&&i.scrollTo({top:s.offsetTop-i.clientHeight/3,behavior:"smooth"})}async revealSegment(e){this.openGroup("exchanges"),await this.showExchanges(),this.shadow.getElementById("exchanges").revealSegment(e)}note(e,t="info"){q.show(this.shadow.getElementById("file-note"),e,t)}transcriptUrl(e){return e.url?new URL(e.url,this.base??location.href).href:void 0}static pretty(e){return JSON.stringify(e,null,2)+`
|
|
229
|
+
`}static SHARED=["title","time","medium","by","interviewOf","summary"];static ORDER=["version","id","language","title","time","medium","by","interviewOf","summary","speakers","transcription","proofreading","anonymization","recordings","segments"];static ordered(e){const t={};for(const r of m.ORDER)r in e&&(t[r]=e[r]);for(const r of Object.keys(e))r in t||(t[r]=e[r]);return t}static witnessesOf(e){return[e].flat().filter(t=>typeof t=="string")}static withEventFields(e,t){const r={...e};for(const i of m.SHARED)t[i]===void 0?delete r[i]:r[i]=structuredClone(t[i]);const s=r.speakers;if(typeof s=="object"&&s!==null){const i={...s},a=(n,l,c)=>{c.forEach((o,d)=>{const h=d===0?n:`${n}${d+1}`;i[h]?i[h]={...i[h],[l]:o}:d>0&&(i[h]={role:n,[l]:o})})};a("interviewer","by",t.by??[]),a("witness","of",m.witnessesOf(t.interviewOf)),r.speakers=i}return m.ordered(r)}applyFileToEvent(e,t){const r=this.current;if(!r)return!1;const s=JSON.stringify(m.SHARED.map(n=>r[n])),i=n=>typeof n=="string"||typeof n=="object"&&n!==null&&!Array.isArray(n),a={title:i,summary:i,time:n=>typeof n=="string",medium:n=>typeof n=="string",by:n=>Array.isArray(n),interviewOf:n=>typeof n=="string"||Array.isArray(n)};for(const n of m.SHARED){const l=e[n];l!==void 0&&a[n](l)?r[n]=structuredClone(l):t&&delete r[n]}return JSON.stringify(m.SHARED.map(n=>r[n]))!==s}syncFileFromEvent(){const e=this.current,t=this.fileEditor?.text??this.text;if(!e||t===void 0)return;let r;try{r=JSON.parse(t)}catch{return}if(typeof r!="object"||r===null||Array.isArray(r))return;const s=m.pretty(m.withEventFields(r,e));s!==t&&(this.text=s,this.fileEditor?.replaceText(s,!1),this.dispatchEvent(new CustomEvent(E,{bubbles:!0,composed:!0,detail:{field:"transcript",event:e,text:s}})))}template(e){return m.pretty(m.withEventFields({version:1,language:this.language,speakers:{interviewer:{role:"interviewer"},witness:{role:"witness"}},segments:[]},e))}loadFileEditor(e){return this.fileEditorLoading??=(async()=>{try{const[{SightingFileEditor:t},{default:r},s]=await Promise.all([A(()=>import("./SightingFileEditor-LAzFduCJ.js"),__vite__mapDeps([0,1]),import.meta.url),A(()=>import("./interviewSchema-7rMvPyAl.js"),[],import.meta.url),V(this.language)]);return this.fileEditor=new t(this.shadow.getElementById("file-editor"),e,i=>this.onEdited(i),this.messages.editorLabel,{baseline:e,phrases:s.fileSearchPhrases,schema:r}),this.fileEditor}catch(t){throw this.fileEditorLoading=void 0,t}})(),this.fileEditorLoading}async showTranscript(){const e=this.current;if(!e||this.shownFor===e)return;this.note(this.messages.loading);let t=this.text;if(t===void 0){const r=this.transcriptUrl(e);if(r!==void 0)try{const s=await T.json(r);this.current===e&&typeof s=="object"&&s!==null&&!Array.isArray(s)?(this.applyFileToEvent(s,!1)&&this.fileChangedEvent(),t=m.pretty(m.withEventFields(s,e))):t=m.pretty(s)}catch{this.note(this.messages.loadFailed,"error")}t??=this.template(e)}if(this.current===e)try{const r=await this.loadFileEditor(t);if(this.current!==e)return;r.replaceText(t,!1),this.shownFor=e,this.text!==void 0||this.transcriptUrl(e)===void 0?this.note(void 0):this.shadow.getElementById("file-note").textContent===this.messages.loading&&this.note(void 0)}catch{this.note(this.messages.loadFailed,"error")}}onEdited(e){this.text=e;let t,r=!0;try{t=JSON.parse(e)}catch{r=!1}this.note(r?void 0:this.messages.invalid,"error");const s=this.current;if(r&&s&&typeof t=="object"&&t!==null&&!Array.isArray(t)&&this.applyFileToEvent(t,!0)&&this.fileChangedEvent(),s&&!s.url&&e.trim()!==""){const i=s.id??"1";s.url=`${i.startsWith("interview")?i:`interview-${i}`}.json`,this.field("url").value=s.url,this.dispatchEvent(new CustomEvent(E,{bubbles:!0,composed:!0,detail:{field:"url",event:s}}))}this.dispatchEvent(new CustomEvent(E,{bubbles:!0,composed:!0,detail:{field:"transcript",event:s,text:e}})),this.showExchanges()}fileChangedEvent(){this.render(),this.dispatchEvent(new CustomEvent(E,{bubbles:!0,composed:!0,detail:{field:"file",event:this.current}}))}async take(e){if(typeof e!="object"||e===null||!Array.isArray(e.segments)){this.note(this.messages.notATranscript,"error");return}const t=this.current;t&&this.applyFileToEvent(e,!1)&&this.fileChangedEvent();const r=m.pretty(t?m.withEventFields(e,t):e);await this.loadFileEditor(r).then(s=>s.replaceText(r,!1),()=>{}),this.shownFor=this.current,this.note(void 0),this.onEdited(r)}async importFromFile(e){try{const t=await e.text();let r;try{r=JSON.parse(t)}catch{r=void 0}if(typeof r!="object"||r===null){const{InterviewImport:s}=await A(async()=>{const{InterviewImport:l}=await import("./interviewImport-C-TiARLK.js");return{InterviewImport:l}},[],import.meta.url),i=this.current,a=[i?.interviewOf].flat().filter(l=>typeof l=="string"),n=s.parse(t,{by:(i?.by??[]).map(l=>m.byText([l])).filter(l=>l!==""),witnesses:this.options.filter(l=>a.length===0||a.includes(l.id))});r=n&&{...n,transcription:{note:`Imported from ${e.name}: who speaks and when are as the file gave them, to be checked.`}}}r===void 0?this.note(this.messages.notATranscript,"error"):await this.take(r)}catch{this.note(this.messages.loadFailed,"error")}}async importFromUrl(e){try{await this.take(await T.json(new URL(e,this.base??location.href).href))}catch{this.note(this.messages.loadFailed,"error")}}save(){const e=this.fileEditor?.text??this.text;if(e===void 0)return;const t=(this.current?.url??"").split("/").pop()||`${this.current?.id??"interview"}.json`,r=URL.createObjectURL(new Blob([e],{type:"application/json"})),s=document.createElement("a");s.href=r,s.download=t,s.click(),URL.revokeObjectURL(r)}}function te(){Y(),J(),customElements.get($)||customElements.define($,m)}export{E as INTERVIEW_CHANGE_EVENT,$ as INTERVIEW_EDITOR_ELEMENT_NAME,W as INTERVIEW_SEEK_EVENT,m as InterviewEditorElement,te as register};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={title:"Title",time:"When",by:"Interviewer",medium:"Medium",witness:"Witness",witnessNone:"—",summary:"Description",transcript:"Transcript",transcriptHint:"Address of the anonymised transcript file (optional)",summaryTab:"Summary",fileTab:"File",importFile:"Load a file (JSON, text, WebVTT, SRT)",inputFileFromFile:"from your disk",inputFileFromUrl:"from an address",inputFileModeHint:"Click to give it the other way: a file of yours, or an address",inputFileLoad:"Load",saveButton:"Save",loading:"Loading the transcript…",invalid:"This text is not valid JSON yet: the interview keeps the last transcript it understood.",notATranscript:"That file is not an interview transcript (it has no segments).",loadFailed:"That transcript could not be read.",editorLabel:"Interview transcript as JSON",byHint:"RR0 people ids, separated by commas",exchangesTab:"Exchanges",exchangesEmpty:"Nothing was said yet.",redacted:"Passage removed",proofreadAll:"Proofread by everyone.",proofreadPending:"Not proofread yet by: {names}",play:"Play",pause:"Pause",recordings:"Recordings ({n})",recordingsTitle:"Recordings",recordingKind:"Type",recordingAudio:"Audio",recordingVideo:"Video",recordingFile:"File",recordingOffset:"Offset (s)",recordingRemove:"Remove",recordingAdd:"Add a recording",close:"Close",noRecording:"No recording: add the audio or video file of the interview to listen to it.",redactSelection:"Take out the selection",redactedWords:"passage taken out · {n} word(s)",redactAll:"Take all out",restoreAll:"Restore all",editTurn:"Edit",deleteTurn:"Delete this turn",saveTurn:"Save",cancelTurn:"Cancel",turnEditHint:"⟦ … ⟧ marks a passage taken out",selectionOnePassage:"The selection has to stay within one passage not taken out.",selectionNone:"Select words of a passage to take them out.",reviewedBy:"{name} has proofread",linkMoment:"Link to a moment…",momentLabel:"Moment {k} · {text}",unlinkMoment:"Remove this link",noMoments:"The observation has no named moment yet.",redactReason:"taken out at proofreading",roles:{interviewer:"Interviewer",interviewee:"Interviewee",witness:"Witness"}};export{e as interviewMessages_en};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={title:"Título",time:"Fecha",by:"Entrevistador",medium:"Medio",witness:"Testigo",witnessNone:"—",summary:"Descripción",transcript:"Transcripción",transcriptHint:"Dirección del archivo de transcripción anonimizada (opcional)",summaryTab:"Resumen",fileTab:"Archivo",importFile:"Cargar un archivo (JSON, texto, WebVTT, SRT)",inputFileFromFile:"desde su disco",inputFileFromUrl:"desde una dirección",inputFileModeHint:"Pulsar para darlo de la otra forma: un archivo suyo o una dirección",inputFileLoad:"Cargar",saveButton:"Guardar",loading:"Cargando la transcripción…",invalid:"Este texto aún no es JSON válido: la entrevista conserva la última transcripción que entendió.",notATranscript:"Ese archivo no es una transcripción de entrevista (no tiene turnos de palabra).",loadFailed:"No se pudo leer esa transcripción.",editorLabel:"Transcripción de la entrevista en JSON",byHint:"Identificadores de personas de RR0, separados por comas",exchangesTab:"Intercambios",exchangesEmpty:"Todavía no se ha dicho nada.",redacted:"Pasaje eliminado",proofreadAll:"Revisado por todos.",proofreadPending:"Aún no revisado por: {names}",play:"Reproducir",pause:"Pausa",recordings:"Grabaciones ({n})",recordingsTitle:"Grabaciones",recordingKind:"Tipo",recordingAudio:"Audio",recordingVideo:"Vídeo",recordingFile:"Archivo",recordingOffset:"Desfase (s)",recordingRemove:"Quitar",recordingAdd:"Añadir una grabación",close:"Cerrar",noRecording:"Sin grabación: añada el archivo de audio o vídeo de la entrevista para poder escucharla.",redactSelection:"Retirar la selección",redactedWords:"pasaje retirado · {n} palabra(s)",redactAll:"Retirar todo",restoreAll:"Restablecer todo",editTurn:"Modificar",deleteTurn:"Eliminar este turno de palabra",saveTurn:"Guardar",cancelTurn:"Cancelar",turnEditHint:"⟦ … ⟧ marca un pasaje retirado",selectionOnePassage:"La selección debe caber en un solo pasaje no retirado.",selectionNone:"Seleccione palabras de un pasaje para retirarlas.",reviewedBy:"{name} ha revisado",linkMoment:"Vincular a un momento…",momentLabel:"Momento {k} · {text}",unlinkMoment:"Quitar este vínculo",noMoments:"La observación aún no tiene momentos con nombre.",redactReason:"retirado en la revisión",roles:{interviewer:"Entrevistador",interviewee:"Entrevistado",witness:"Testigo"}};export{e as interviewMessages_es};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={title:"Titre",time:"Date",by:"Enquêteur",medium:"Moyen",witness:"Témoin",witnessNone:"—",summary:"Description",transcript:"Transcription",transcriptHint:"Adresse du fichier de transcription anonymisée (facultative)",summaryTab:"Résumé",fileTab:"Fichier",importFile:"Charger un fichier (JSON, texte, WebVTT, SRT)",inputFileFromFile:"depuis votre disque",inputFileFromUrl:"depuis une adresse",inputFileModeHint:"Cliquer pour le donner autrement : un fichier à vous, ou une adresse",inputFileLoad:"Charger",saveButton:"Sauver",loading:"Chargement de la transcription…",invalid:"Ce texte n'est pas encore du JSON valide : l'interview garde la dernière transcription qu'elle a comprise.",notATranscript:"Ce fichier n'est pas une transcription d'interview (il n'a pas de tours de parole).",loadFailed:"Cette transcription n'a pas pu être lue.",editorLabel:"Transcription de l'interview en JSON",byHint:"Identifiants de personnes RR0, séparés par des virgules",exchangesTab:"Échanges",exchangesEmpty:"Rien n'a encore été dit.",redacted:"Passage retiré",proofreadAll:"Relu par tous les participants.",proofreadPending:"Pas encore relu par : {names}",play:"Lecture",pause:"Pause",recordings:"Enregistrements ({n})",recordingsTitle:"Enregistrements",recordingKind:"Type",recordingAudio:"Audio",recordingVideo:"Vidéo",recordingFile:"Fichier",recordingOffset:"Décalage (s)",recordingRemove:"Retirer",recordingAdd:"Ajouter un enregistrement",close:"Fermer",noRecording:"Aucun enregistrement : ajoutez le fichier audio ou vidéo de l'entretien pour pouvoir l'écouter.",redactSelection:"Retirer la sélection",redactedWords:"passage retiré · {n} mot(s)",redactAll:"Retirer tout",restoreAll:"Rétablir tout",editTurn:"Modifier",deleteTurn:"Supprimer ce tour de parole",saveTurn:"Enregistrer",cancelTurn:"Annuler",turnEditHint:"⟦ … ⟧ marque un passage retiré",selectionOnePassage:"La sélection doit tenir dans un seul passage non retiré.",selectionNone:"Sélectionnez des mots d'un passage pour les retirer.",reviewedBy:"{name} a relu",linkMoment:"Relier à un moment…",momentLabel:"Moment {k} · {text}",unlinkMoment:"Retirer ce lien",noMoments:"L'observation n'a pas encore de moment nommé.",redactReason:"retiré à la relecture",roles:{interviewer:"Intervieweur",interviewee:"Interviewé",witness:"Témoin"}};export{e as interviewMessages_fr};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i={title:"Titolo",time:"Data",by:"Intervistatore",medium:"Mezzo",witness:"Testimone",witnessNone:"—",summary:"Descrizione",transcript:"Trascrizione",transcriptHint:"Indirizzo del file di trascrizione anonimizzata (facoltativo)",summaryTab:"Riepilogo",fileTab:"File",importFile:"Carica un file (JSON, testo, WebVTT, SRT)",inputFileFromFile:"dal proprio disco",inputFileFromUrl:"da un indirizzo",inputFileModeHint:"Fare clic per darlo nell'altro modo: un proprio file o un indirizzo",inputFileLoad:"Carica",saveButton:"Salva",loading:"Caricamento della trascrizione…",invalid:"Questo testo non è ancora JSON valido: l'intervista conserva l'ultima trascrizione che ha capito.",notATranscript:"Quel file non è una trascrizione di intervista (non ha turni di parola).",loadFailed:"Impossibile leggere quella trascrizione.",editorLabel:"Trascrizione dell'intervista in JSON",byHint:"Identificatori di persone RR0, separati da virgole",exchangesTab:"Scambi",exchangesEmpty:"Non è stato ancora detto nulla.",redacted:"Passaggio rimosso",proofreadAll:"Rivisto da tutti.",proofreadPending:"Non ancora rivisto da: {names}",play:"Riproduci",pause:"Pausa",recordings:"Registrazioni ({n})",recordingsTitle:"Registrazioni",recordingKind:"Tipo",recordingAudio:"Audio",recordingVideo:"Video",recordingFile:"File",recordingOffset:"Scarto (s)",recordingRemove:"Rimuovi",recordingAdd:"Aggiungi una registrazione",close:"Chiudi",noRecording:"Nessuna registrazione: aggiungi il file audio o video dell'intervista per poterla ascoltare.",redactSelection:"Rimuovi la selezione",redactedWords:"passaggio rimosso · {n} parola/e",redactAll:"Rimuovi tutto",restoreAll:"Ripristina tutto",editTurn:"Modifica",deleteTurn:"Elimina questo turno",saveTurn:"Salva",cancelTurn:"Annulla",turnEditHint:"⟦ … ⟧ indica un passaggio rimosso",selectionOnePassage:"La selezione deve restare in un solo passaggio non rimosso.",selectionNone:"Seleziona parole di un passaggio per rimuoverle.",reviewedBy:"{name} ha riletto",linkMoment:"Collega a un momento…",momentLabel:"Momento {k} · {text}",unlinkMoment:"Rimuovi questo collegamento",noMoments:"L'osservazione non ha ancora momenti con nome.",redactReason:"rimosso in rilettura",roles:{interviewer:"Intervistatore",interviewee:"Intervistato",witness:"Testimone"}};export{i as interviewMessages_it};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as g,
|
|
1
|
+
import{R as g,w as T,V as y}from"./rr0-sighting-editor.mjs";class s{static DEFAULT_DIVERGENCE_MRAD=.1;static DEFAULT_APERTURE_M=.01;static AEROSOL_SINGLE_SCATTERING_ALBEDO=.9;static AEROSOL_ASYMMETRY=.7;static STEP_M=25;static MAX_SAMPLES=2e3;static viewsAt(t,c,n,e){return s.onAt(t,c).map(o=>({id:o.id,wavelengthNm:o.wavelengthNm,samples:s.samplesOf(o,n,e)}))}static onAt(t,c){return t.filter(n=>n.path.length>=2&&(n.fromT===void 0||c>=n.fromT)&&(n.untilT===void 0||c<=n.untilT))}static samplesOf(t,c,n){const e=g.ecef({lat:c.lat,lng:c.lng,heightM:0}),o=c.lat*Math.PI/180,M=c.lng*Math.PI/180,u=a=>{const l=a[0]-e[0],r=a[1]-e[1],i=a[2]-e[2];return[-Math.sin(M)*l+Math.cos(M)*r,-Math.sin(o)*Math.cos(M)*l-Math.sin(o)*Math.sin(M)*r+Math.cos(o)*i,Math.cos(o)*Math.cos(M)*l+Math.cos(o)*Math.sin(M)*r+Math.sin(o)*i]},w=(t.divergenceMrad??s.DEFAULT_DIVERGENCE_MRAD)/1e3,x=t.apertureM??s.DEFAULT_APERTURE_M,p=[];let A=0,O=t.powerW,D=0;for(let a=0;a+1<t.path.length;a++){const l=t.path[a],r=t.path[a+1],i=g.ecef({lat:l.lat,lng:l.lng,heightM:l.altitudeM}),E=g.ecef({lat:r.lat,lng:r.lng,heightM:r.altitudeM}),f=Math.hypot(E[0]-i[0],E[1]-i[1],E[2]-i[2]),S=Math.max(1,Math.min(s.MAX_SAMPLES,Math.ceil(f/s.STEP_M)));for(let d=a===0?0:1;d<=S;d++){const P=d/S,N=[0,1,2].map(h=>i[h]+(E[h]-i[h])*P),R=P*f,I=l.altitudeM+(r.altitudeM-l.altitudeM)*P+s.bulgeM(R,f);if(d>0){const h=p[p.length-1],v=R+A-h.fromSourceM,C=s.extinctionAt(n,t.wavelengthNm,(h.altitudeM+I)/2);D+=C*v,O=t.powerW*Math.exp(-D)}const[_,G,U]=u(N);p.push({eastM:_,northM:G,upM:U,altitudeM:I,fromSourceM:A+R,widthM:x+w*(A+R),powerW:O})}A+=f}return p}static bulgeM(t,c){return t*(c-t)/(2*6371e3)}static extinctionAt(t,c,n){const{rayleighPerM:e,aerosolPerM:o}=s.coefficientsAt(t,c,n);return e+o}static coefficientsAt(t,c,n){const e=T.rayleighAt(c)*T.rayleighDensity(n),o=t.aerosol[1]*(c/550)**-1.3*T.aerosolDensity(n);return{rayleighPerM:e,aerosolPerM:o}}static phasedScattering(t,c){const n=3/(16*Math.PI)*(1+c*c),e=s.AEROSOL_ASYMMETRY,o=(1-e*e)/(4*Math.PI*(1+e*e-2*e*c)**1.5);return t.rayleighPerM*n+t.aerosolPerM*s.AEROSOL_SINGLE_SCATTERING_ALBEDO*o}static efficacy(t){return 683*Math.max(0,y.colourMatching(t)[1])}static colourOf(t){const[c,n,e]=y.colourMatching(t);if(n<=0)return[0,0,0];const o=y.linearSrgbOf([c/n,1,e/n]).map(u=>Math.max(0,u)),M=.2126*o[0]+.7152*o[1]+.0722*o[2];return o.map(u=>u/M)}static luminanceCdM2(t,c,n,e,o){return s.efficacy(c)*t*n/(e*Math.max(o,.001))}}export{s as L};
|