UNPKG

ca-web-components

Version:

web components for Clínica Alemana

63 lines (59 loc) 6.39 kB
var v=Object.defineProperty;var x=(c,h,t)=>h in c?v(c,h,{enumerable:!0,configurable:!0,writable:!0,value:t}):c[h]=t;var d=(c,h,t)=>x(c,typeof h!="symbol"?h+"":h,t);import{i as k,x as m,r as y,o as T}from"../assets/unsafe-html-DS3AO1W7.js";const S=k` :host { display: block; color: #203442; } .container { display: flex; align-items: center; gap: 8px; } button { position: relative; width: 32px; height: 32px; border-radius: 50%; border: 0; background-color: #EEECFB; color: currentColor; cursor: pointer; transition: .2s ease; display: flex; align-items: center; justify-content: center; } button:after { position: absolute; content: ''; display: block; width: 110%; height: 110%; border-radius: 50%; border: 2px solid transparent; transition: .2s ease; } button.focus:after { border-color: #857BE2; } `;class f extends y{constructor(){super();d(this,"handleSelectVoice",(t=[])=>{const i=this.shadowRoot.querySelector("select");if(!i)return null;i.innerHTML=t.map(e=>`<option value="${e.name}">${e.name}</option>`).join(""),i.addEventListener("change",e=>{const r=e.target.value;e.target.name;const s=t.find(o=>o.name===r);this.utterance.voice=s,this.voice=s})});this.supported="speechSynthesis"in window,this.text="",this.textHTML="",this.currentTime=0,this.totalTime=0,this.timer=null,this.synth=window.speechSynthesis,this.utterance=null,this.voice=null,this.speaking=!1,this.currentSpeech=null,this.synth.getVoices(),this.synth.onvoiceschanged=()=>{const t=this.synth.getVoices(),i=t.filter(e=>e.lang.includes("es"));this.voice=t.find(e=>e.name==="Google español de Estados Unidos"&&e.lang==="es-US"),this.handleSelectVoice(i.reverse())},window.addEventListener("beforeunload",()=>{this.synth.cancel()})}speak(){if(this.currentSpeech)return null;this.currentTime=0;const t=this.splitText(this.text);this.speakFragments(t)}pause(){this.synth.pause(),this.stopSpeaking()}resume(){this.synth.resume(),this.startSpeaking()}startSpeaking(){this.speaking=!0,this.timer=setInterval(()=>{this.speaking&&this.currentTime++},1e3),this.requestUpdate()}stopSpeaking(){this.speaking=!1,clearInterval(this.timer),this.requestUpdate()}splitText(t,i=200){const e=[];let r=0;for(;r<t.length;){let s=r+i,o=!1;const n=t.indexOf(` `,r);if(n!==-1&&n<=s&&(s=n,o=!0),!o&&s<t.length){const l=new RegExp("(?<=[.!?])\\s"),a=t.slice(r,s+1).match(l);if(a)s=r+a.index+1;else{let u=t.lastIndexOf(" ",s);s=u===-1?s:u+1}}e.push(t.slice(r,s).trim()),r=o?s+2:s}return e}speakFragments(t){let i=0;const e=()=>{if(i<t.length){const r=t[i];this.utterance=new SpeechSynthesisUtterance(r),this.utterance.rate=1.2,this.voice&&(this.utterance.voice=this.voice),this.utterance.onstart=s=>{i===0&&(this.startSpeaking(),this.currentSpeech=this.synth.speaking,console.log("onstart",s),this.requestUpdate())},this.utterance.onend=()=>{i===t.length-1?(this.stopSpeaking(),this.currentSpeech=this.synth.speaking,console.log("onend, last fragment"),this.currentTime=this.totalTime,this.requestUpdate()):(i++,e())},this.utterance.onerror=s=>{console.error("Error en la síntesis de voz:",s.error)},this.synth.speak(this.utterance)}};e()}estimateDuration(t,i=150){const r=t.split(" ").length/i*60;return Math.round(r)}formatTime(t){const i=Math.floor(t/60),e=t%60;return`${i.toString().padStart(2,"0")}:${e.toString().padStart(2,"0")}`}htmlToText(t){return new DOMParser().parseFromString(t,"text/html").body.textContent||""}splitAndStructureText(t){const e=new DOMParser().parseFromString(t,"text/html"),r=[];function s(n,l=!1){if(n.nodeType===Node.ELEMENT_NODE){let a="",u=` `;if(!l&&["div","p","h1","h2","h3","h4","h5","h6","ul","ol","section"].includes(n.tagName.toLowerCase())&&(a=` `),!n.children.length||n.tagName.toLowerCase()==="a"){let p=n.textContent.trim();["h1","h2","h3","h4","h5","h6"].includes(n.tagName.toLowerCase())&&(u=` `),(n.tagName.toLowerCase()==="li"||n.tagName.toLowerCase()==="p")&&(n.querySelector("a")&&(p="",Array.from(n.childNodes).forEach(g=>{s(g,!0)})),n.tagName.toLowerCase()==="li"&&(a="- ")),p&&r.push(`${a}${p}${u}`)}else Array.from(n.childNodes).forEach(p=>s(p,l))}else if(n.nodeType===Node.TEXT_NODE&&!l){let a=n.textContent.trim();a&&r.push(`${a} `)}}s(e.body);let o=r.join("");return o=o.replace(/\n{2,}/g,` `),o=o.trim(),o}firstUpdated(){this.textHTML&&(this.text=this.splitAndStructureText(this.textHTML)),this.totalTime=this.estimateDuration(this.text);const t=this.shadowRoot.querySelector("button");t.addEventListener("focus",()=>{t.classList.add("focus")}),t.addEventListener("blur",()=>{t.classList.remove("focus")})}render(){const t=this.formatTime(this.currentTime),i=this.formatTime(this.totalTime),e=()=>{this.currentSpeech?this.speaking?this.pause():this.resume():this.speak()};return this.supported?m` <!-- <cas-text variant="footnote2">${this.text}</cas-text>--> <article class="container"> <button @click="${()=>e()}">${this.speaking?b:w}</button> <cas-text variant="footnote2">${t} / ${i}</cas-text> <select style="display: none" name="voice" id="select-voice"></select> </article> <!-- ${T(this.textHTML)}--> `:(console.log("El navegador no soporta la síntesis de voz"),null)}}d(f,"styles",S),d(f,"properties",{text:{type:String},textHTML:{type:String},currentTime:{type:Number},totalTime:{type:Number}});customElements.get("ca-speech-text")||customElements.define("ca-speech-text",f);const w=m`<svg class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M6 4v16a1 1 0 0 0 1.524 .852l13 -8a1 1 0 0 0 0 -1.704l-13 -8a1 1 0 0 0 -1.524 .852z" stroke-width="0" fill="currentColor"></path> </svg>`,b=m`<svg class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M9 4h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h2a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2z" stroke-width="0" fill="currentColor"></path> <path d="M17 4h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h2a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2z" stroke-width="0" fill="currentColor"></path> </svg>`;