dictate-button
Version:
Dictate Button (Web Component)
37 lines (31 loc) • 16 kB
JavaScript
;const rt=(t,e)=>t===e,O={equals:rt};let it=X;const C=1,P=2,G={owned:null,cleanups:null,context:null,owner:null};var g=null;let F=null,ot=null,u=null,p=null,w=null,M=0;function lt(t,e){const n=u,r=g,s=t.length===0,i=e===void 0?r:e,l=s?G:{owned:null,cleanups:null,context:i?i.context:null,owner:i},o=s?t:()=>t(()=>U(()=>A(l)));g=l,u=null;try{return m(o,!0)}finally{u=n,g=r}}function H(t,e){e=e?Object.assign({},O,e):O;const n={value:t,observers:null,observerSlots:null,comparator:e.equals||void 0},r=s=>(typeof s=="function"&&(s=s(n.value)),J(n,s));return[Z.bind(n),r]}function j(t,e,n){const r=Q(t,e,!1,C);R(r)}function ct(t,e,n){n=n?Object.assign({},O,n):O;const r=Q(t,e,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,R(r),Z.bind(r)}function U(t){if(u===null)return t();const e=u;u=null;try{return t()}finally{u=e}}function Z(){if(this.sources&&this.state)if(this.state===C)R(this);else{const t=p;p=null,m(()=>N(this),!1),p=t}if(u){const t=this.observers?this.observers.length:0;u.sources?(u.sources.push(this),u.sourceSlots.push(t)):(u.sources=[this],u.sourceSlots=[t]),this.observers?(this.observers.push(u),this.observerSlots.push(u.sources.length-1)):(this.observers=[u],this.observerSlots=[u.sources.length-1])}return this.value}function J(t,e,n){let r=t.value;return(!t.comparator||!t.comparator(r,e))&&(t.value=e,t.observers&&t.observers.length&&m(()=>{for(let s=0;s<t.observers.length;s+=1){const i=t.observers[s],l=F&&F.running;l&&F.disposed.has(i),(l?!i.tState:!i.state)&&(i.pure?p.push(i):w.push(i),i.observers&&Y(i)),l||(i.state=C)}if(p.length>1e6)throw p=[],new Error},!1)),e}function R(t){if(!t.fn)return;A(t);const e=M;at(t,t.value,e)}function at(t,e,n){let r;const s=g,i=u;u=g=t;try{r=t.fn(e)}catch(l){return t.pure&&(t.state=C,t.owned&&t.owned.forEach(A),t.owned=null),t.updatedAt=n+1,tt(l)}finally{u=i,g=s}(!t.updatedAt||t.updatedAt<=n)&&(t.updatedAt!=null&&"observers"in t?J(t,r):t.value=r,t.updatedAt=n)}function Q(t,e,n,r=C,s){const i={fn:t,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:e,owner:g,context:g?g.context:null,pure:n};return g===null||g!==G&&(g.owned?g.owned.push(i):g.owned=[i]),i}function W(t){if(t.state===0)return;if(t.state===P)return N(t);if(t.suspense&&U(t.suspense.inFallback))return t.suspense.effects.push(t);const e=[t];for(;(t=t.owner)&&(!t.updatedAt||t.updatedAt<M);)t.state&&e.push(t);for(let n=e.length-1;n>=0;n--)if(t=e[n],t.state===C)R(t);else if(t.state===P){const r=p;p=null,m(()=>N(t,e[0]),!1),p=r}}function m(t,e){if(p)return t();let n=!1;e||(p=[]),w?n=!0:w=[],M++;try{const r=t();return ut(n),r}catch(r){n||(w=null),p=null,tt(r)}}function ut(t){if(p&&(X(p),p=null),t)return;const e=w;w=null,e.length&&m(()=>it(e),!1)}function X(t){for(let e=0;e<t.length;e++)W(t[e])}function N(t,e){t.state=0;for(let n=0;n<t.sources.length;n+=1){const r=t.sources[n];if(r.sources){const s=r.state;s===C?r!==e&&(!r.updatedAt||r.updatedAt<M)&&W(r):s===P&&N(r,e)}}}function Y(t){for(let e=0;e<t.observers.length;e+=1){const n=t.observers[e];n.state||(n.state=P,n.pure?p.push(n):w.push(n),n.observers&&Y(n))}}function A(t){let e;if(t.sources)for(;t.sources.length;){const n=t.sources.pop(),r=t.sourceSlots.pop(),s=n.observers;if(s&&s.length){const i=s.pop(),l=n.observerSlots.pop();r<s.length&&(i.sourceSlots[l]=r,s[r]=i,n.observerSlots[r]=l)}}if(t.tOwned){for(e=t.tOwned.length-1;e>=0;e--)A(t.tOwned[e]);delete t.tOwned}if(t.owned){for(e=t.owned.length-1;e>=0;e--)A(t.owned[e]);t.owned=null}if(t.cleanups){for(e=t.cleanups.length-1;e>=0;e--)t.cleanups[e]();t.cleanups=null}t.state=0}function ft(t){return t instanceof Error?t:new Error(typeof t=="string"?t:"Unknown error",{cause:t})}function tt(t,e=g){throw ft(t)}function $(t,e){return U(()=>t(e||{}))}const k=t=>ct(()=>t());function dt(t,e,n){let r=n.length,s=e.length,i=r,l=0,o=0,c=e[s-1].nextSibling,a=null;for(;l<s||o<i;){if(e[l]===n[o]){l++,o++;continue}for(;e[s-1]===n[i-1];)s--,i--;if(s===l){const f=i<r?o?n[o-1].nextSibling:n[i-o]:c;for(;o<i;)t.insertBefore(n[o++],f)}else if(i===o)for(;l<s;)(!a||!a.has(e[l]))&&e[l].remove(),l++;else if(e[l]===n[i-1]&&n[o]===e[s-1]){const f=e[--s].nextSibling;t.insertBefore(n[o++],e[l++].nextSibling),t.insertBefore(n[--i],f),e[s]=n[i]}else{if(!a){a=new Map;let b=o;for(;b<i;)a.set(n[b],b++)}const f=a.get(e[l]);if(f!=null)if(o<f&&f<i){let b=l,y=1,_;for(;++b<s&&b<i&&!((_=a.get(e[b]))==null||_!==f+y);)y++;if(y>f-o){const d=e[l];for(;o<f;)t.insertBefore(n[o++],d)}else t.replaceChild(n[o++],e[l++])}else l++;else e[l++].remove()}}}const D="_$DX_DELEGATE";function x(t,e,n,r){let s;const i=()=>{const o=document.createElement("template");return o.innerHTML=t,o.content.firstChild},l=()=>(s||(s=i())).cloneNode(!0);return l.cloneNode=l,l}function ht(t,e=window.document){const n=e[D]||(e[D]=new Set);for(let r=0,s=t.length;r<s;r++){const i=t[r];n.has(i)||(n.add(i),e.addEventListener(i,gt))}}function et(t,e,n){n==null?t.removeAttribute(e):t.setAttribute(e,n)}function pt(t,e,n){if(!e)return n?et(t,"style"):e;const r=t.style;if(typeof e=="string")return r.cssText=e;typeof n=="string"&&(r.cssText=n=void 0),n||(n={}),e||(e={});let s,i;for(i in n)e[i]==null&&r.removeProperty(i),delete n[i];for(i in e)s=e[i],s!==n[i]&&(r.setProperty(i,s),n[i]=s);return n}function E(t,e,n,r){if(n!==void 0&&!r&&(r=[]),typeof e!="function")return B(t,e,r,n);j(s=>B(t,e(),s,n),r)}function gt(t){let e=t.target;const n=`$$${t.type}`,r=t.target,s=t.currentTarget,i=c=>Object.defineProperty(t,"target",{configurable:!0,value:c}),l=()=>{const c=e[n];if(c&&!e.disabled){const a=e[`${n}Data`];if(a!==void 0?c.call(e,a,t):c.call(e,t),t.cancelBubble)return}return e.host&&typeof e.host!="string"&&!e.host._$host&&e.contains(t.target)&&i(e.host),!0},o=()=>{for(;l()&&(e=e._$host||e.parentNode||e.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return e||document}}),t.composedPath){const c=t.composedPath();i(c[0]);for(let a=0;a<c.length-2&&(e=c[a],!!l());a++){if(e._$host){e=e._$host,o();break}if(e.parentNode===s)break}}else o();i(r)}function B(t,e,n,r,s){for(;typeof n=="function";)n=n();if(e===n)return n;const i=typeof e,l=r!==void 0;if(t=l&&n[0]&&n[0].parentNode||t,i==="string"||i==="number"){if(i==="number"&&(e=e.toString(),e===n))return n;if(l){let o=n[0];o&&o.nodeType===3?o.data!==e&&(o.data=e):o=document.createTextNode(e),n=v(t,n,r,o)}else n!==""&&typeof n=="string"?n=t.firstChild.data=e:n=t.textContent=e}else if(e==null||i==="boolean")n=v(t,n,r);else{if(i==="function")return j(()=>{let o=e();for(;typeof o=="function";)o=o();n=B(t,o,n,r)}),()=>n;if(Array.isArray(e)){const o=[],c=n&&Array.isArray(n);if(K(o,e,n,s))return j(()=>n=B(t,o,n,r,!0)),()=>n;if(o.length===0){if(n=v(t,n,r),l)return n}else c?n.length===0?q(t,o,r):dt(t,n,o):(n&&v(t),q(t,o));n=o}else if(e.nodeType){if(Array.isArray(n)){if(l)return n=v(t,n,r,e);v(t,n,null,e)}else n==null||n===""||!t.firstChild?t.appendChild(e):t.replaceChild(e,t.firstChild);n=e}}return n}function K(t,e,n,r){let s=!1;for(let i=0,l=e.length;i<l;i++){let o=e[i],c=n&&n[t.length],a;if(!(o==null||o===!0||o===!1))if((a=typeof o)=="object"&&o.nodeType)t.push(o);else if(Array.isArray(o))s=K(t,o,c)||s;else if(a==="function")if(r){for(;typeof o=="function";)o=o();s=K(t,Array.isArray(o)?o:[o],Array.isArray(c)?c:[c])||s}else t.push(o),s=!0;else{const f=String(o);c&&c.nodeType===3&&c.data===f?t.push(c):t.push(document.createTextNode(f))}}return s}function q(t,e,n=null){for(let r=0,s=e.length;r<s;r++)t.insertBefore(e[r],n)}function v(t,e,n,r){if(n===void 0)return t.textContent="";const s=r||document.createTextNode("");if(e.length){let i=!1;for(let l=e.length-1;l>=0;l--){const o=e[l];if(s!==o){const c=o.parentNode===t;!i&&!l?c?t.replaceChild(s,o):t.insertBefore(s,n):c&&o.remove()}else i=!0}}else t.insertBefore(s,n);return[s]}function bt(t){return Object.keys(t).reduce((n,r)=>{const s=t[r];return n[r]=Object.assign({},s),st(s.value)&&!vt(s.value)&&!Array.isArray(s.value)&&(n[r].value=Object.assign({},s.value)),Array.isArray(s.value)&&(n[r].value=s.value.slice(0)),n},{})}function yt(t){return t?Object.keys(t).reduce((n,r)=>{const s=t[r];return n[r]=st(s)&&"value"in s?s:{value:s},n[r].attribute||(n[r].attribute=Ct(r)),n[r].parse="parse"in n[r]?n[r].parse:typeof n[r].value!="string",n},{}):{}}function _t(t){return Object.keys(t).reduce((n,r)=>(n[r]=t[r].value,n),{})}function wt(t,e){const n=bt(e);return Object.keys(e).forEach(s=>{const i=n[s],l=t.getAttribute(i.attribute),o=t[s];l!=null&&(i.value=i.parse?nt(l):l),o!=null&&(i.value=Array.isArray(o)?o.slice(0):o),i.reflect&&z(t,i.attribute,i.value,!!i.parse),Object.defineProperty(t,s,{get(){return i.value},set(c){const a=i.value;i.value=c,i.reflect&&z(this,i.attribute,i.value,!!i.parse);for(let f=0,b=this.__propertyChangedCallbacks.length;f<b;f++)this.__propertyChangedCallbacks[f](s,c,a)},enumerable:!0,configurable:!0})}),n}function nt(t){if(t)try{return JSON.parse(t)}catch{return t}}function z(t,e,n,r){if(n==null||n===!1)return t.removeAttribute(e);let s=r?JSON.stringify(n):n;t.__updating[e]=!0,s==="true"&&(s=""),t.setAttribute(e,s),Promise.resolve().then(()=>delete t.__updating[e])}function Ct(t){return t.replace(/\.?([A-Z]+)/g,(e,n)=>"-"+n.toLowerCase()).replace("_","-").replace(/^-/,"")}function st(t){return t!=null&&(typeof t=="object"||typeof t=="function")}function vt(t){return Object.prototype.toString.call(t)==="[object Function]"}function St(t){return typeof t=="function"&&t.toString().indexOf("class")===0}let L;function Et(t,e){const n=Object.keys(e);return class extends t{static get observedAttributes(){return n.map(s=>e[s].attribute)}constructor(){super(),this.__initialized=!1,this.__released=!1,this.__releaseCallbacks=[],this.__propertyChangedCallbacks=[],this.__updating={},this.props={}}connectedCallback(){if(this.__initialized)return;this.__releaseCallbacks=[],this.__propertyChangedCallbacks=[],this.__updating={},this.props=wt(this,e);const s=_t(this.props),i=this.Component,l=L;try{L=this,this.__initialized=!0,St(i)?new i(s,{element:this}):i(s,{element:this})}finally{L=l}}async disconnectedCallback(){if(await Promise.resolve(),this.isConnected)return;this.__propertyChangedCallbacks.length=0;let s=null;for(;s=this.__releaseCallbacks.pop();)s(this);delete this.__initialized,this.__released=!0}attributeChangedCallback(s,i,l){if(this.__initialized&&!this.__updating[s]&&(s=this.lookupProp(s),s in e)){if(l==null&&!this[s])return;this[s]=e[s].parse?nt(l):l}}lookupProp(s){if(e)return n.find(i=>s===i||s===e[i].attribute)}get renderRoot(){return this.shadowRoot||this.attachShadow({mode:"open"})}addReleaseCallback(s){this.__releaseCallbacks.push(s)}addPropertyChangedCallback(s){this.__propertyChangedCallbacks.push(s)}}}function At(t,e={},n={}){const{BaseElement:r=HTMLElement,extension:s,customElements:i=window.customElements}=n;return l=>{let o=i.get(t);return o?(o.prototype.Component=l,o):(o=Et(r,yt(e)),o.prototype.Component=l,o.prototype.registeredTag=t,i.define(t,o,s),o)}}function mt(t){const e=Object.keys(t),n={};for(let r=0;r<e.length;r++){const[s,i]=H(t[e[r]]);Object.defineProperty(n,e[r],{get:s,set(l){i(()=>l)}})}return n}function xt(t){if(t.assignedSlot&&t.assignedSlot._$owner)return t.assignedSlot._$owner;let e=t.parentNode;for(;e&&!e._$owner&&!(e.assignedSlot&&e.assignedSlot._$owner);)e=e.parentNode;return e&&e.assignedSlot?e.assignedSlot._$owner:t._$owner}function $t(t){return(e,n)=>{const{element:r}=n;return lt(s=>{const i=mt(e);r.addPropertyChangedCallback((o,c)=>i[o]=c),r.addReleaseCallback(()=>{r.renderRoot.textContent="",s()});const l=t(i,n);return E(r.renderRoot,l)},xt(r))}}function kt(t,e,n){return arguments.length===2&&(n=e,e={}),At(t,e)($t(n))}const Tt=`
:host([theme="dark"]) {
color-scheme: only dark;
}
:host([theme="light"]) {
color-scheme: only light;
}
:host .dictate-button__container {
margin: 5px;
}
:host .dictate-button__button {
cursor: pointer;
padding: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
opacity: 0.8;
transition: opacity 0.2s ease-in-out;
}
:host .dictate-button__button .dictate-button__icon {
width: 100%;
height: 100%;
}
:host .dictate-button__button .dictate-button__icon.dictate-button__icon--processing {
animation: dictate-button-rotate 1s linear infinite;
}
@keyframes dictate-button-rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;var Ot=x("<div part=container class=dictate-button__container><style></style><button part=button class=dictate-button__button>"),Pt=x('<svg part=icon class="dictate-button__icon dictate-button__icon--idle"fill=none viewBox="0 0 24 24"stroke-width=1.5 stroke=currentColor><path stroke-linecap=round stroke-linejoin=round d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z">'),jt=x('<svg part=icon class="dictate-button__icon dictate-button__icon--recording"viewBox="0 0 24 24"fill=currentColor><path fill-rule=evenodd d="M4.5 7.5a3 3 0 0 1 3-3h9a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-9a3 3 0 0 1-3-3v-9Z"clip-rule=evenodd>'),Nt=x('<svg part=icon class="dictate-button__icon dictate-button__icon--processing"fill=none viewBox="0 0 24 24"stroke-width=1.5 stroke=currentColor><path stroke-linecap=round stroke-linejoin=round d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99">'),Bt=x('<svg part=icon class="dictate-button__icon dictate-button__icon--error"fill=none viewBox="0 0 24 24"stroke-width=1.5 stroke=currentColor><path stroke-linecap=round stroke-linejoin=round d="M6 18 18 6M6 6l12 12">');console.debug("dictate-button version:","0.3.0");const Mt="https://api.dictate-button.io/transcribe",T="dictate-button.io";kt("dictate-button",{size:24,apiEndpoint:Mt,language:void 0},(t,{element:e})=>{const{size:n,apiEndpoint:r,language:s}=t;console.debug("api",r);const[i,l]=H("idle");let o=null,c=[];const a=()=>{o&&o.state!=="inactive"&&o.stop(),c=[]};e.addEventListener("disconnected",a);const f=async()=>{if(a(),i()==="idle")try{const y=await navigator.mediaDevices.getUserMedia({audio:!0});o=new MediaRecorder(y,{mimeType:"audio/webm"}),c=[],o.ondataavailable=_=>{c.push(_.data)},o.onstop=async()=>{l("processing"),S(e,"transcribing:started","Started transcribing");const _=new Blob(c,{type:"audio/webm"});try{const d=new FormData;d.append("audio",_,"recording.webm"),d.append("origin",window?.location?.origin),s&&d.append("language",s);const h=await fetch(r,{method:"POST",body:d});if(!h.ok)throw new Error("Failed to transcribe audio");const I=await h.json();if(i()!=="processing")return;S(e,"transcribing:finished",I.text),l("idle")}catch(d){console.error("Failed to transcribe audio:",d),S(e,"transcribing:failed","Failed to transcribe audio"),b()}},o.start(),S(e,"recording:started","Started recording"),l("recording")}catch(y){console.error("Failed to start recording:",y),S(e,"recording:failed","Failed to start recording"),b()}else S(e,"recording:stopped","Stopped recording"),l("idle")},b=()=>{l("error"),setTimeout(()=>l("idle"),2e3)};return(()=>{var y=Ot(),_=y.firstChild,d=_.nextSibling;return E(_,Tt),d.$$click=f,E(d,(()=>{var h=k(()=>i()==="idle");return()=>h()&&$(It,{})})(),null),E(d,(()=>{var h=k(()=>i()==="recording");return()=>h()&&$(Ft,{})})(),null),E(d,(()=>{var h=k(()=>i()==="processing");return()=>h()&&$(Lt,{})})(),null),E(d,(()=>{var h=k(()=>i()==="error");return()=>h()&&$(Kt,{})})(),null),j(h=>{var I=`width:${n}px;height:${n}px"`,V=Rt(i());return h.e=pt(d,I,h.e),V!==h.t&&et(d,"title",h.t=V),h},{e:void 0,t:void 0}),y})()});const Rt=t=>{switch(t){case"idle":return`Start dictation (${T})`;case"recording":return`Stop dictation (${T})`;case"processing":return`Stop processing (${T})`;case"error":return`Click to reset (${T})`}},S=(t,e,n)=>{t.dispatchEvent(new CustomEvent(e,{detail:n,bubbles:!0,composed:!0}))},It=()=>Pt(),Ft=()=>jt(),Lt=()=>Nt(),Kt=()=>Bt();ht(["click"]);