dictate-button
Version:
Dictate Button (Web Component)
687 lines (681 loc) • 21.6 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 = /* @__PURE__ */ 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] = /* @__PURE__ */ 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 = /* @__PURE__ */ x("<div part=container class=dictate-button__container><style></style><button part=button class=dictate-button__button>"), Pt = /* @__PURE__ */ 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 = /* @__PURE__ */ 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 = /* @__PURE__ */ 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 = /* @__PURE__ */ 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"]);