@corti/dictation-web 0.1.1 → 0.1.3

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/bundle.js ADDED
@@ -0,0 +1,1691 @@
1
+ // node_modules/tslib/tslib.es6.mjs
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
6
+ return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
7
+ }
8
+
9
+ // node_modules/@lit/reactive-element/css-tag.js
10
+ var t = globalThis;
11
+ var e = t.ShadowRoot && (void 0 === t.ShadyCSS || t.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype;
12
+ var s = Symbol();
13
+ var o = /* @__PURE__ */ new WeakMap();
14
+ var n = class {
15
+ constructor(t4, e5, o5) {
16
+ if (this._$cssResult$ = true, o5 !== s) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");
17
+ this.cssText = t4, this.t = e5;
18
+ }
19
+ get styleSheet() {
20
+ let t4 = this.o;
21
+ const s3 = this.t;
22
+ if (e && void 0 === t4) {
23
+ const e5 = void 0 !== s3 && 1 === s3.length;
24
+ e5 && (t4 = o.get(s3)), void 0 === t4 && ((this.o = t4 = new CSSStyleSheet()).replaceSync(this.cssText), e5 && o.set(s3, t4));
25
+ }
26
+ return t4;
27
+ }
28
+ toString() {
29
+ return this.cssText;
30
+ }
31
+ };
32
+ var r = (t4) => new n("string" == typeof t4 ? t4 : t4 + "", void 0, s);
33
+ var i = (t4, ...e5) => {
34
+ const o5 = 1 === t4.length ? t4[0] : e5.reduce((e6, s3, o6) => e6 + ((t5) => {
35
+ if (true === t5._$cssResult$) return t5.cssText;
36
+ if ("number" == typeof t5) return t5;
37
+ throw Error("Value passed to 'css' function must be a 'css' function result: " + t5 + ". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.");
38
+ })(s3) + t4[o6 + 1], t4[0]);
39
+ return new n(o5, t4, s);
40
+ };
41
+ var S = (s3, o5) => {
42
+ if (e) s3.adoptedStyleSheets = o5.map((t4) => t4 instanceof CSSStyleSheet ? t4 : t4.styleSheet);
43
+ else for (const e5 of o5) {
44
+ const o6 = document.createElement("style"), n5 = t.litNonce;
45
+ void 0 !== n5 && o6.setAttribute("nonce", n5), o6.textContent = e5.cssText, s3.appendChild(o6);
46
+ }
47
+ };
48
+ var c = e ? (t4) => t4 : (t4) => t4 instanceof CSSStyleSheet ? ((t5) => {
49
+ let e5 = "";
50
+ for (const s3 of t5.cssRules) e5 += s3.cssText;
51
+ return r(e5);
52
+ })(t4) : t4;
53
+
54
+ // node_modules/@lit/reactive-element/reactive-element.js
55
+ var { is: i2, defineProperty: e2, getOwnPropertyDescriptor: r2, getOwnPropertyNames: h, getOwnPropertySymbols: o2, getPrototypeOf: n2 } = Object;
56
+ var a = globalThis;
57
+ var c2 = a.trustedTypes;
58
+ var l = c2 ? c2.emptyScript : "";
59
+ var p = a.reactiveElementPolyfillSupport;
60
+ var d = (t4, s3) => t4;
61
+ var u = { toAttribute(t4, s3) {
62
+ switch (s3) {
63
+ case Boolean:
64
+ t4 = t4 ? l : null;
65
+ break;
66
+ case Object:
67
+ case Array:
68
+ t4 = null == t4 ? t4 : JSON.stringify(t4);
69
+ }
70
+ return t4;
71
+ }, fromAttribute(t4, s3) {
72
+ let i5 = t4;
73
+ switch (s3) {
74
+ case Boolean:
75
+ i5 = null !== t4;
76
+ break;
77
+ case Number:
78
+ i5 = null === t4 ? null : Number(t4);
79
+ break;
80
+ case Object:
81
+ case Array:
82
+ try {
83
+ i5 = JSON.parse(t4);
84
+ } catch (t5) {
85
+ i5 = null;
86
+ }
87
+ }
88
+ return i5;
89
+ } };
90
+ var f = (t4, s3) => !i2(t4, s3);
91
+ var y = { attribute: true, type: String, converter: u, reflect: false, hasChanged: f };
92
+ Symbol.metadata ??= Symbol("metadata"), a.litPropertyMetadata ??= /* @__PURE__ */ new WeakMap();
93
+ var b = class extends HTMLElement {
94
+ static addInitializer(t4) {
95
+ this._$Ei(), (this.l ??= []).push(t4);
96
+ }
97
+ static get observedAttributes() {
98
+ return this.finalize(), this._$Eh && [...this._$Eh.keys()];
99
+ }
100
+ static createProperty(t4, s3 = y) {
101
+ if (s3.state && (s3.attribute = false), this._$Ei(), this.elementProperties.set(t4, s3), !s3.noAccessor) {
102
+ const i5 = Symbol(), r7 = this.getPropertyDescriptor(t4, i5, s3);
103
+ void 0 !== r7 && e2(this.prototype, t4, r7);
104
+ }
105
+ }
106
+ static getPropertyDescriptor(t4, s3, i5) {
107
+ const { get: e5, set: h3 } = r2(this.prototype, t4) ?? { get() {
108
+ return this[s3];
109
+ }, set(t5) {
110
+ this[s3] = t5;
111
+ } };
112
+ return { get() {
113
+ return e5?.call(this);
114
+ }, set(s4) {
115
+ const r7 = e5?.call(this);
116
+ h3.call(this, s4), this.requestUpdate(t4, r7, i5);
117
+ }, configurable: true, enumerable: true };
118
+ }
119
+ static getPropertyOptions(t4) {
120
+ return this.elementProperties.get(t4) ?? y;
121
+ }
122
+ static _$Ei() {
123
+ if (this.hasOwnProperty(d("elementProperties"))) return;
124
+ const t4 = n2(this);
125
+ t4.finalize(), void 0 !== t4.l && (this.l = [...t4.l]), this.elementProperties = new Map(t4.elementProperties);
126
+ }
127
+ static finalize() {
128
+ if (this.hasOwnProperty(d("finalized"))) return;
129
+ if (this.finalized = true, this._$Ei(), this.hasOwnProperty(d("properties"))) {
130
+ const t5 = this.properties, s3 = [...h(t5), ...o2(t5)];
131
+ for (const i5 of s3) this.createProperty(i5, t5[i5]);
132
+ }
133
+ const t4 = this[Symbol.metadata];
134
+ if (null !== t4) {
135
+ const s3 = litPropertyMetadata.get(t4);
136
+ if (void 0 !== s3) for (const [t5, i5] of s3) this.elementProperties.set(t5, i5);
137
+ }
138
+ this._$Eh = /* @__PURE__ */ new Map();
139
+ for (const [t5, s3] of this.elementProperties) {
140
+ const i5 = this._$Eu(t5, s3);
141
+ void 0 !== i5 && this._$Eh.set(i5, t5);
142
+ }
143
+ this.elementStyles = this.finalizeStyles(this.styles);
144
+ }
145
+ static finalizeStyles(s3) {
146
+ const i5 = [];
147
+ if (Array.isArray(s3)) {
148
+ const e5 = new Set(s3.flat(1 / 0).reverse());
149
+ for (const s4 of e5) i5.unshift(c(s4));
150
+ } else void 0 !== s3 && i5.push(c(s3));
151
+ return i5;
152
+ }
153
+ static _$Eu(t4, s3) {
154
+ const i5 = s3.attribute;
155
+ return false === i5 ? void 0 : "string" == typeof i5 ? i5 : "string" == typeof t4 ? t4.toLowerCase() : void 0;
156
+ }
157
+ constructor() {
158
+ super(), this._$Ep = void 0, this.isUpdatePending = false, this.hasUpdated = false, this._$Em = null, this._$Ev();
159
+ }
160
+ _$Ev() {
161
+ this._$ES = new Promise((t4) => this.enableUpdating = t4), this._$AL = /* @__PURE__ */ new Map(), this._$E_(), this.requestUpdate(), this.constructor.l?.forEach((t4) => t4(this));
162
+ }
163
+ addController(t4) {
164
+ (this._$EO ??= /* @__PURE__ */ new Set()).add(t4), void 0 !== this.renderRoot && this.isConnected && t4.hostConnected?.();
165
+ }
166
+ removeController(t4) {
167
+ this._$EO?.delete(t4);
168
+ }
169
+ _$E_() {
170
+ const t4 = /* @__PURE__ */ new Map(), s3 = this.constructor.elementProperties;
171
+ for (const i5 of s3.keys()) this.hasOwnProperty(i5) && (t4.set(i5, this[i5]), delete this[i5]);
172
+ t4.size > 0 && (this._$Ep = t4);
173
+ }
174
+ createRenderRoot() {
175
+ const t4 = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions);
176
+ return S(t4, this.constructor.elementStyles), t4;
177
+ }
178
+ connectedCallback() {
179
+ this.renderRoot ??= this.createRenderRoot(), this.enableUpdating(true), this._$EO?.forEach((t4) => t4.hostConnected?.());
180
+ }
181
+ enableUpdating(t4) {
182
+ }
183
+ disconnectedCallback() {
184
+ this._$EO?.forEach((t4) => t4.hostDisconnected?.());
185
+ }
186
+ attributeChangedCallback(t4, s3, i5) {
187
+ this._$AK(t4, i5);
188
+ }
189
+ _$EC(t4, s3) {
190
+ const i5 = this.constructor.elementProperties.get(t4), e5 = this.constructor._$Eu(t4, i5);
191
+ if (void 0 !== e5 && true === i5.reflect) {
192
+ const r7 = (void 0 !== i5.converter?.toAttribute ? i5.converter : u).toAttribute(s3, i5.type);
193
+ this._$Em = t4, null == r7 ? this.removeAttribute(e5) : this.setAttribute(e5, r7), this._$Em = null;
194
+ }
195
+ }
196
+ _$AK(t4, s3) {
197
+ const i5 = this.constructor, e5 = i5._$Eh.get(t4);
198
+ if (void 0 !== e5 && this._$Em !== e5) {
199
+ const t5 = i5.getPropertyOptions(e5), r7 = "function" == typeof t5.converter ? { fromAttribute: t5.converter } : void 0 !== t5.converter?.fromAttribute ? t5.converter : u;
200
+ this._$Em = e5, this[e5] = r7.fromAttribute(s3, t5.type), this._$Em = null;
201
+ }
202
+ }
203
+ requestUpdate(t4, s3, i5) {
204
+ if (void 0 !== t4) {
205
+ if (i5 ??= this.constructor.getPropertyOptions(t4), !(i5.hasChanged ?? f)(this[t4], s3)) return;
206
+ this.P(t4, s3, i5);
207
+ }
208
+ false === this.isUpdatePending && (this._$ES = this._$ET());
209
+ }
210
+ P(t4, s3, i5) {
211
+ this._$AL.has(t4) || this._$AL.set(t4, s3), true === i5.reflect && this._$Em !== t4 && (this._$Ej ??= /* @__PURE__ */ new Set()).add(t4);
212
+ }
213
+ async _$ET() {
214
+ this.isUpdatePending = true;
215
+ try {
216
+ await this._$ES;
217
+ } catch (t5) {
218
+ Promise.reject(t5);
219
+ }
220
+ const t4 = this.scheduleUpdate();
221
+ return null != t4 && await t4, !this.isUpdatePending;
222
+ }
223
+ scheduleUpdate() {
224
+ return this.performUpdate();
225
+ }
226
+ performUpdate() {
227
+ if (!this.isUpdatePending) return;
228
+ if (!this.hasUpdated) {
229
+ if (this.renderRoot ??= this.createRenderRoot(), this._$Ep) {
230
+ for (const [t6, s4] of this._$Ep) this[t6] = s4;
231
+ this._$Ep = void 0;
232
+ }
233
+ const t5 = this.constructor.elementProperties;
234
+ if (t5.size > 0) for (const [s4, i5] of t5) true !== i5.wrapped || this._$AL.has(s4) || void 0 === this[s4] || this.P(s4, this[s4], i5);
235
+ }
236
+ let t4 = false;
237
+ const s3 = this._$AL;
238
+ try {
239
+ t4 = this.shouldUpdate(s3), t4 ? (this.willUpdate(s3), this._$EO?.forEach((t5) => t5.hostUpdate?.()), this.update(s3)) : this._$EU();
240
+ } catch (s4) {
241
+ throw t4 = false, this._$EU(), s4;
242
+ }
243
+ t4 && this._$AE(s3);
244
+ }
245
+ willUpdate(t4) {
246
+ }
247
+ _$AE(t4) {
248
+ this._$EO?.forEach((t5) => t5.hostUpdated?.()), this.hasUpdated || (this.hasUpdated = true, this.firstUpdated(t4)), this.updated(t4);
249
+ }
250
+ _$EU() {
251
+ this._$AL = /* @__PURE__ */ new Map(), this.isUpdatePending = false;
252
+ }
253
+ get updateComplete() {
254
+ return this.getUpdateComplete();
255
+ }
256
+ getUpdateComplete() {
257
+ return this._$ES;
258
+ }
259
+ shouldUpdate(t4) {
260
+ return true;
261
+ }
262
+ update(t4) {
263
+ this._$Ej &&= this._$Ej.forEach((t5) => this._$EC(t5, this[t5])), this._$EU();
264
+ }
265
+ updated(t4) {
266
+ }
267
+ firstUpdated(t4) {
268
+ }
269
+ };
270
+ b.elementStyles = [], b.shadowRootOptions = { mode: "open" }, b[d("elementProperties")] = /* @__PURE__ */ new Map(), b[d("finalized")] = /* @__PURE__ */ new Map(), p?.({ ReactiveElement: b }), (a.reactiveElementVersions ??= []).push("2.0.4");
271
+
272
+ // node_modules/lit-html/lit-html.js
273
+ var t2 = globalThis;
274
+ var i3 = t2.trustedTypes;
275
+ var s2 = i3 ? i3.createPolicy("lit-html", { createHTML: (t4) => t4 }) : void 0;
276
+ var e3 = "$lit$";
277
+ var h2 = `lit$${Math.random().toFixed(9).slice(2)}$`;
278
+ var o3 = "?" + h2;
279
+ var n3 = `<${o3}>`;
280
+ var r3 = document;
281
+ var l2 = () => r3.createComment("");
282
+ var c3 = (t4) => null === t4 || "object" != typeof t4 && "function" != typeof t4;
283
+ var a2 = Array.isArray;
284
+ var u2 = (t4) => a2(t4) || "function" == typeof t4?.[Symbol.iterator];
285
+ var d2 = "[ \n\f\r]";
286
+ var f2 = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g;
287
+ var v = /-->/g;
288
+ var _ = />/g;
289
+ var m = RegExp(`>|${d2}(?:([^\\s"'>=/]+)(${d2}*=${d2}*(?:[^
290
+ \f\r"'\`<>=]|("|')|))|$)`, "g");
291
+ var p2 = /'/g;
292
+ var g = /"/g;
293
+ var $ = /^(?:script|style|textarea|title)$/i;
294
+ var y2 = (t4) => (i5, ...s3) => ({ _$litType$: t4, strings: i5, values: s3 });
295
+ var x = y2(1);
296
+ var b2 = y2(2);
297
+ var w = y2(3);
298
+ var T = Symbol.for("lit-noChange");
299
+ var E = Symbol.for("lit-nothing");
300
+ var A = /* @__PURE__ */ new WeakMap();
301
+ var C = r3.createTreeWalker(r3, 129);
302
+ function P(t4, i5) {
303
+ if (!a2(t4) || !t4.hasOwnProperty("raw")) throw Error("invalid template strings array");
304
+ return void 0 !== s2 ? s2.createHTML(i5) : i5;
305
+ }
306
+ var V = (t4, i5) => {
307
+ const s3 = t4.length - 1, o5 = [];
308
+ let r7, l3 = 2 === i5 ? "<svg>" : 3 === i5 ? "<math>" : "", c4 = f2;
309
+ for (let i6 = 0; i6 < s3; i6++) {
310
+ const s4 = t4[i6];
311
+ let a3, u3, d3 = -1, y3 = 0;
312
+ for (; y3 < s4.length && (c4.lastIndex = y3, u3 = c4.exec(s4), null !== u3); ) y3 = c4.lastIndex, c4 === f2 ? "!--" === u3[1] ? c4 = v : void 0 !== u3[1] ? c4 = _ : void 0 !== u3[2] ? ($.test(u3[2]) && (r7 = RegExp("</" + u3[2], "g")), c4 = m) : void 0 !== u3[3] && (c4 = m) : c4 === m ? ">" === u3[0] ? (c4 = r7 ?? f2, d3 = -1) : void 0 === u3[1] ? d3 = -2 : (d3 = c4.lastIndex - u3[2].length, a3 = u3[1], c4 = void 0 === u3[3] ? m : '"' === u3[3] ? g : p2) : c4 === g || c4 === p2 ? c4 = m : c4 === v || c4 === _ ? c4 = f2 : (c4 = m, r7 = void 0);
313
+ const x2 = c4 === m && t4[i6 + 1].startsWith("/>") ? " " : "";
314
+ l3 += c4 === f2 ? s4 + n3 : d3 >= 0 ? (o5.push(a3), s4.slice(0, d3) + e3 + s4.slice(d3) + h2 + x2) : s4 + h2 + (-2 === d3 ? i6 : x2);
315
+ }
316
+ return [P(t4, l3 + (t4[s3] || "<?>") + (2 === i5 ? "</svg>" : 3 === i5 ? "</math>" : "")), o5];
317
+ };
318
+ var N = class _N {
319
+ constructor({ strings: t4, _$litType$: s3 }, n5) {
320
+ let r7;
321
+ this.parts = [];
322
+ let c4 = 0, a3 = 0;
323
+ const u3 = t4.length - 1, d3 = this.parts, [f3, v2] = V(t4, s3);
324
+ if (this.el = _N.createElement(f3, n5), C.currentNode = this.el.content, 2 === s3 || 3 === s3) {
325
+ const t5 = this.el.content.firstChild;
326
+ t5.replaceWith(...t5.childNodes);
327
+ }
328
+ for (; null !== (r7 = C.nextNode()) && d3.length < u3; ) {
329
+ if (1 === r7.nodeType) {
330
+ if (r7.hasAttributes()) for (const t5 of r7.getAttributeNames()) if (t5.endsWith(e3)) {
331
+ const i5 = v2[a3++], s4 = r7.getAttribute(t5).split(h2), e5 = /([.?@])?(.*)/.exec(i5);
332
+ d3.push({ type: 1, index: c4, name: e5[2], strings: s4, ctor: "." === e5[1] ? H : "?" === e5[1] ? I : "@" === e5[1] ? L : k }), r7.removeAttribute(t5);
333
+ } else t5.startsWith(h2) && (d3.push({ type: 6, index: c4 }), r7.removeAttribute(t5));
334
+ if ($.test(r7.tagName)) {
335
+ const t5 = r7.textContent.split(h2), s4 = t5.length - 1;
336
+ if (s4 > 0) {
337
+ r7.textContent = i3 ? i3.emptyScript : "";
338
+ for (let i5 = 0; i5 < s4; i5++) r7.append(t5[i5], l2()), C.nextNode(), d3.push({ type: 2, index: ++c4 });
339
+ r7.append(t5[s4], l2());
340
+ }
341
+ }
342
+ } else if (8 === r7.nodeType) if (r7.data === o3) d3.push({ type: 2, index: c4 });
343
+ else {
344
+ let t5 = -1;
345
+ for (; -1 !== (t5 = r7.data.indexOf(h2, t5 + 1)); ) d3.push({ type: 7, index: c4 }), t5 += h2.length - 1;
346
+ }
347
+ c4++;
348
+ }
349
+ }
350
+ static createElement(t4, i5) {
351
+ const s3 = r3.createElement("template");
352
+ return s3.innerHTML = t4, s3;
353
+ }
354
+ };
355
+ function S2(t4, i5, s3 = t4, e5) {
356
+ if (i5 === T) return i5;
357
+ let h3 = void 0 !== e5 ? s3._$Co?.[e5] : s3._$Cl;
358
+ const o5 = c3(i5) ? void 0 : i5._$litDirective$;
359
+ return h3?.constructor !== o5 && (h3?._$AO?.(false), void 0 === o5 ? h3 = void 0 : (h3 = new o5(t4), h3._$AT(t4, s3, e5)), void 0 !== e5 ? (s3._$Co ??= [])[e5] = h3 : s3._$Cl = h3), void 0 !== h3 && (i5 = S2(t4, h3._$AS(t4, i5.values), h3, e5)), i5;
360
+ }
361
+ var M = class {
362
+ constructor(t4, i5) {
363
+ this._$AV = [], this._$AN = void 0, this._$AD = t4, this._$AM = i5;
364
+ }
365
+ get parentNode() {
366
+ return this._$AM.parentNode;
367
+ }
368
+ get _$AU() {
369
+ return this._$AM._$AU;
370
+ }
371
+ u(t4) {
372
+ const { el: { content: i5 }, parts: s3 } = this._$AD, e5 = (t4?.creationScope ?? r3).importNode(i5, true);
373
+ C.currentNode = e5;
374
+ let h3 = C.nextNode(), o5 = 0, n5 = 0, l3 = s3[0];
375
+ for (; void 0 !== l3; ) {
376
+ if (o5 === l3.index) {
377
+ let i6;
378
+ 2 === l3.type ? i6 = new R(h3, h3.nextSibling, this, t4) : 1 === l3.type ? i6 = new l3.ctor(h3, l3.name, l3.strings, this, t4) : 6 === l3.type && (i6 = new z(h3, this, t4)), this._$AV.push(i6), l3 = s3[++n5];
379
+ }
380
+ o5 !== l3?.index && (h3 = C.nextNode(), o5++);
381
+ }
382
+ return C.currentNode = r3, e5;
383
+ }
384
+ p(t4) {
385
+ let i5 = 0;
386
+ for (const s3 of this._$AV) void 0 !== s3 && (void 0 !== s3.strings ? (s3._$AI(t4, s3, i5), i5 += s3.strings.length - 2) : s3._$AI(t4[i5])), i5++;
387
+ }
388
+ };
389
+ var R = class _R {
390
+ get _$AU() {
391
+ return this._$AM?._$AU ?? this._$Cv;
392
+ }
393
+ constructor(t4, i5, s3, e5) {
394
+ this.type = 2, this._$AH = E, this._$AN = void 0, this._$AA = t4, this._$AB = i5, this._$AM = s3, this.options = e5, this._$Cv = e5?.isConnected ?? true;
395
+ }
396
+ get parentNode() {
397
+ let t4 = this._$AA.parentNode;
398
+ const i5 = this._$AM;
399
+ return void 0 !== i5 && 11 === t4?.nodeType && (t4 = i5.parentNode), t4;
400
+ }
401
+ get startNode() {
402
+ return this._$AA;
403
+ }
404
+ get endNode() {
405
+ return this._$AB;
406
+ }
407
+ _$AI(t4, i5 = this) {
408
+ t4 = S2(this, t4, i5), c3(t4) ? t4 === E || null == t4 || "" === t4 ? (this._$AH !== E && this._$AR(), this._$AH = E) : t4 !== this._$AH && t4 !== T && this._(t4) : void 0 !== t4._$litType$ ? this.$(t4) : void 0 !== t4.nodeType ? this.T(t4) : u2(t4) ? this.k(t4) : this._(t4);
409
+ }
410
+ O(t4) {
411
+ return this._$AA.parentNode.insertBefore(t4, this._$AB);
412
+ }
413
+ T(t4) {
414
+ this._$AH !== t4 && (this._$AR(), this._$AH = this.O(t4));
415
+ }
416
+ _(t4) {
417
+ this._$AH !== E && c3(this._$AH) ? this._$AA.nextSibling.data = t4 : this.T(r3.createTextNode(t4)), this._$AH = t4;
418
+ }
419
+ $(t4) {
420
+ const { values: i5, _$litType$: s3 } = t4, e5 = "number" == typeof s3 ? this._$AC(t4) : (void 0 === s3.el && (s3.el = N.createElement(P(s3.h, s3.h[0]), this.options)), s3);
421
+ if (this._$AH?._$AD === e5) this._$AH.p(i5);
422
+ else {
423
+ const t5 = new M(e5, this), s4 = t5.u(this.options);
424
+ t5.p(i5), this.T(s4), this._$AH = t5;
425
+ }
426
+ }
427
+ _$AC(t4) {
428
+ let i5 = A.get(t4.strings);
429
+ return void 0 === i5 && A.set(t4.strings, i5 = new N(t4)), i5;
430
+ }
431
+ k(t4) {
432
+ a2(this._$AH) || (this._$AH = [], this._$AR());
433
+ const i5 = this._$AH;
434
+ let s3, e5 = 0;
435
+ for (const h3 of t4) e5 === i5.length ? i5.push(s3 = new _R(this.O(l2()), this.O(l2()), this, this.options)) : s3 = i5[e5], s3._$AI(h3), e5++;
436
+ e5 < i5.length && (this._$AR(s3 && s3._$AB.nextSibling, e5), i5.length = e5);
437
+ }
438
+ _$AR(t4 = this._$AA.nextSibling, i5) {
439
+ for (this._$AP?.(false, true, i5); t4 && t4 !== this._$AB; ) {
440
+ const i6 = t4.nextSibling;
441
+ t4.remove(), t4 = i6;
442
+ }
443
+ }
444
+ setConnected(t4) {
445
+ void 0 === this._$AM && (this._$Cv = t4, this._$AP?.(t4));
446
+ }
447
+ };
448
+ var k = class {
449
+ get tagName() {
450
+ return this.element.tagName;
451
+ }
452
+ get _$AU() {
453
+ return this._$AM._$AU;
454
+ }
455
+ constructor(t4, i5, s3, e5, h3) {
456
+ this.type = 1, this._$AH = E, this._$AN = void 0, this.element = t4, this.name = i5, this._$AM = e5, this.options = h3, s3.length > 2 || "" !== s3[0] || "" !== s3[1] ? (this._$AH = Array(s3.length - 1).fill(new String()), this.strings = s3) : this._$AH = E;
457
+ }
458
+ _$AI(t4, i5 = this, s3, e5) {
459
+ const h3 = this.strings;
460
+ let o5 = false;
461
+ if (void 0 === h3) t4 = S2(this, t4, i5, 0), o5 = !c3(t4) || t4 !== this._$AH && t4 !== T, o5 && (this._$AH = t4);
462
+ else {
463
+ const e6 = t4;
464
+ let n5, r7;
465
+ for (t4 = h3[0], n5 = 0; n5 < h3.length - 1; n5++) r7 = S2(this, e6[s3 + n5], i5, n5), r7 === T && (r7 = this._$AH[n5]), o5 ||= !c3(r7) || r7 !== this._$AH[n5], r7 === E ? t4 = E : t4 !== E && (t4 += (r7 ?? "") + h3[n5 + 1]), this._$AH[n5] = r7;
466
+ }
467
+ o5 && !e5 && this.j(t4);
468
+ }
469
+ j(t4) {
470
+ t4 === E ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, t4 ?? "");
471
+ }
472
+ };
473
+ var H = class extends k {
474
+ constructor() {
475
+ super(...arguments), this.type = 3;
476
+ }
477
+ j(t4) {
478
+ this.element[this.name] = t4 === E ? void 0 : t4;
479
+ }
480
+ };
481
+ var I = class extends k {
482
+ constructor() {
483
+ super(...arguments), this.type = 4;
484
+ }
485
+ j(t4) {
486
+ this.element.toggleAttribute(this.name, !!t4 && t4 !== E);
487
+ }
488
+ };
489
+ var L = class extends k {
490
+ constructor(t4, i5, s3, e5, h3) {
491
+ super(t4, i5, s3, e5, h3), this.type = 5;
492
+ }
493
+ _$AI(t4, i5 = this) {
494
+ if ((t4 = S2(this, t4, i5, 0) ?? E) === T) return;
495
+ const s3 = this._$AH, e5 = t4 === E && s3 !== E || t4.capture !== s3.capture || t4.once !== s3.once || t4.passive !== s3.passive, h3 = t4 !== E && (s3 === E || e5);
496
+ e5 && this.element.removeEventListener(this.name, this, s3), h3 && this.element.addEventListener(this.name, this, t4), this._$AH = t4;
497
+ }
498
+ handleEvent(t4) {
499
+ "function" == typeof this._$AH ? this._$AH.call(this.options?.host ?? this.element, t4) : this._$AH.handleEvent(t4);
500
+ }
501
+ };
502
+ var z = class {
503
+ constructor(t4, i5, s3) {
504
+ this.element = t4, this.type = 6, this._$AN = void 0, this._$AM = i5, this.options = s3;
505
+ }
506
+ get _$AU() {
507
+ return this._$AM._$AU;
508
+ }
509
+ _$AI(t4) {
510
+ S2(this, t4);
511
+ }
512
+ };
513
+ var j = t2.litHtmlPolyfillSupport;
514
+ j?.(N, R), (t2.litHtmlVersions ??= []).push("3.2.1");
515
+ var B = (t4, i5, s3) => {
516
+ const e5 = s3?.renderBefore ?? i5;
517
+ let h3 = e5._$litPart$;
518
+ if (void 0 === h3) {
519
+ const t5 = s3?.renderBefore ?? null;
520
+ e5._$litPart$ = h3 = new R(i5.insertBefore(l2(), t5), t5, void 0, s3 ?? {});
521
+ }
522
+ return h3._$AI(t4), h3;
523
+ };
524
+
525
+ // node_modules/lit-element/lit-element.js
526
+ var r4 = class extends b {
527
+ constructor() {
528
+ super(...arguments), this.renderOptions = { host: this }, this._$Do = void 0;
529
+ }
530
+ createRenderRoot() {
531
+ const t4 = super.createRenderRoot();
532
+ return this.renderOptions.renderBefore ??= t4.firstChild, t4;
533
+ }
534
+ update(t4) {
535
+ const s3 = this.render();
536
+ this.hasUpdated || (this.renderOptions.isConnected = this.isConnected), super.update(t4), this._$Do = B(s3, this.renderRoot, this.renderOptions);
537
+ }
538
+ connectedCallback() {
539
+ super.connectedCallback(), this._$Do?.setConnected(true);
540
+ }
541
+ disconnectedCallback() {
542
+ super.disconnectedCallback(), this._$Do?.setConnected(false);
543
+ }
544
+ render() {
545
+ return T;
546
+ }
547
+ };
548
+ r4._$litElement$ = true, r4["finalized"] = true, globalThis.litElementHydrateSupport?.({ LitElement: r4 });
549
+ var i4 = globalThis.litElementPolyfillSupport;
550
+ i4?.({ LitElement: r4 });
551
+ (globalThis.litElementVersions ??= []).push("4.1.1");
552
+
553
+ // node_modules/@lit/reactive-element/decorators/custom-element.js
554
+ var t3 = (t4) => (e5, o5) => {
555
+ void 0 !== o5 ? o5.addInitializer(() => {
556
+ customElements.define(t4, e5);
557
+ }) : customElements.define(t4, e5);
558
+ };
559
+
560
+ // node_modules/@lit/reactive-element/decorators/property.js
561
+ var o4 = { attribute: true, type: String, converter: u, reflect: false, hasChanged: f };
562
+ var r5 = (t4 = o4, e5, r7) => {
563
+ const { kind: n5, metadata: i5 } = r7;
564
+ let s3 = globalThis.litPropertyMetadata.get(i5);
565
+ if (void 0 === s3 && globalThis.litPropertyMetadata.set(i5, s3 = /* @__PURE__ */ new Map()), s3.set(r7.name, t4), "accessor" === n5) {
566
+ const { name: o5 } = r7;
567
+ return { set(r8) {
568
+ const n6 = e5.get.call(this);
569
+ e5.set.call(this, r8), this.requestUpdate(o5, n6, t4);
570
+ }, init(e6) {
571
+ return void 0 !== e6 && this.P(o5, void 0, t4), e6;
572
+ } };
573
+ }
574
+ if ("setter" === n5) {
575
+ const { name: o5 } = r7;
576
+ return function(r8) {
577
+ const n6 = this[o5];
578
+ e5.call(this, r8), this.requestUpdate(o5, n6, t4);
579
+ };
580
+ }
581
+ throw Error("Unsupported decorator location: " + n5);
582
+ };
583
+ function n4(t4) {
584
+ return (e5, o5) => "object" == typeof o5 ? r5(t4, e5, o5) : ((t5, e6, o6) => {
585
+ const r7 = e6.hasOwnProperty(o6);
586
+ return e6.constructor.createProperty(o6, r7 ? { ...t5, wrapped: true } : t5), r7 ? Object.getOwnPropertyDescriptor(e6, o6) : void 0;
587
+ })(t4, e5, o5);
588
+ }
589
+
590
+ // node_modules/@lit/reactive-element/decorators/state.js
591
+ function r6(r7) {
592
+ return n4({ ...r7, state: true, attribute: false });
593
+ }
594
+
595
+ // dist/utils.js
596
+ function getLanguageName(languageCode) {
597
+ const userLocale = navigator.language || "en";
598
+ const displayNames = new Intl.DisplayNames([userLocale], {
599
+ type: "language"
600
+ });
601
+ const languageName = displayNames.of(languageCode);
602
+ return languageName || languageCode;
603
+ }
604
+ async function requestMicAccess() {
605
+ try {
606
+ if (!navigator.permissions) {
607
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
608
+ stream.getTracks().forEach((track) => track.stop());
609
+ return;
610
+ }
611
+ const permissionStatus = await navigator.permissions.query({
612
+ // eslint-disable-next-line no-undef
613
+ name: "microphone"
614
+ });
615
+ if (permissionStatus.state === "prompt") {
616
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
617
+ stream.getTracks().forEach((track) => track.stop());
618
+ } else if (permissionStatus.state === "denied") {
619
+ console.warn("Microphone permission is denied.");
620
+ }
621
+ } catch (error) {
622
+ console.error("Error checking/requesting microphone permission:", error);
623
+ }
624
+ }
625
+ async function getAudioDevices() {
626
+ if (!navigator.mediaDevices?.enumerateDevices) {
627
+ console.error("Media devices API not supported.");
628
+ return { devices: [] };
629
+ }
630
+ await requestMicAccess();
631
+ try {
632
+ const devices = await navigator.mediaDevices.enumerateDevices();
633
+ const audioDevices = devices.filter((device) => device.kind === "audioinput");
634
+ const defaultDeviceId = audioDevices.length > 0 ? audioDevices[0].deviceId : void 0;
635
+ return { devices: audioDevices, defaultDeviceId };
636
+ } catch (error) {
637
+ console.error("Error enumerating devices:", error);
638
+ return { devices: [] };
639
+ }
640
+ }
641
+ function decodeToken(token) {
642
+ const parts = token.split(".");
643
+ if (parts.length < 2) {
644
+ throw new Error("Invalid token format: expected header.payload.signature");
645
+ }
646
+ const base64Url = parts[1];
647
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
648
+ console.log("Decoded base64:", base64);
649
+ let jsonPayload;
650
+ try {
651
+ jsonPayload = decodeURIComponent(atob(base64).split("").map((c4) => "%" + ("00" + c4.charCodeAt(0).toString(16)).slice(-2)).join(""));
652
+ } catch (error) {
653
+ throw new Error("Failed to decode token payload");
654
+ }
655
+ console.log("Decoded payload:", jsonPayload);
656
+ let tokenDetails;
657
+ try {
658
+ tokenDetails = JSON.parse(jsonPayload);
659
+ } catch (error) {
660
+ throw new Error("Invalid JSON payload in token");
661
+ }
662
+ const issuerUrl = tokenDetails.iss;
663
+ if (!issuerUrl) {
664
+ throw new Error("Token payload does not contain an issuer (iss) field");
665
+ }
666
+ const regex = /^https:\/\/(keycloak|auth)\.([^.]+)\.corti\.app\/realms\/([^/]+)/;
667
+ const match = issuerUrl.match(regex);
668
+ console.log("Matched URL pattern:", match);
669
+ if (match) {
670
+ console.log("Matched URL pattern:", match);
671
+ return {
672
+ environment: match[2],
673
+ tenant: match[3],
674
+ token
675
+ };
676
+ }
677
+ }
678
+
679
+ // dist/audioService.js
680
+ var AudioService = class {
681
+ constructor(mediaStream) {
682
+ this.audioContext = new AudioContext();
683
+ const source = this.audioContext.createMediaStreamSource(mediaStream);
684
+ this.analyser = this.audioContext.createAnalyser();
685
+ this.analyser.fftSize = 8192;
686
+ source.connect(this.analyser);
687
+ }
688
+ getAudioLevel() {
689
+ const bufferLength = this.analyser.fftSize;
690
+ const dataArray = new Uint8Array(bufferLength);
691
+ this.analyser.getByteTimeDomainData(dataArray);
692
+ let sum = 0;
693
+ for (let i5 = 0; i5 < bufferLength; i5 += 1) {
694
+ const normalized = (dataArray[i5] - 128) / 128;
695
+ sum += normalized * normalized;
696
+ }
697
+ return Math.sqrt(sum / bufferLength);
698
+ }
699
+ };
700
+
701
+ // dist/DictationService.js
702
+ var DictationService = class extends EventTarget {
703
+ constructor(mediaStream, { dictationConfig, authToken }) {
704
+ super();
705
+ this.mediaRecorder = new MediaRecorder(mediaStream);
706
+ this.authToken = authToken;
707
+ this.dictationConfig = dictationConfig;
708
+ this.mediaRecorder.ondataavailable = (event) => {
709
+ if (this.webSocket?.readyState === WebSocket.OPEN) {
710
+ this.webSocket.send(event.data);
711
+ }
712
+ };
713
+ }
714
+ startRecording() {
715
+ const serverConfig = decodeToken(this.authToken);
716
+ if (!serverConfig) {
717
+ this.dispatchEvent(new CustomEvent("error", {
718
+ detail: "Invalid token",
719
+ bubbles: true,
720
+ composed: true
721
+ }));
722
+ return;
723
+ }
724
+ console.log("serverConfig:", serverConfig);
725
+ const url = `wss://api.${serverConfig.environment}.corti.app/audio-bridge/v2/transcribe?tenant-name=${serverConfig.tenant}&token=Bearer%20${this.authToken}`;
726
+ this.webSocket = new WebSocket(url);
727
+ this.webSocket.onopen = () => {
728
+ this.webSocket.send(JSON.stringify({
729
+ type: "config",
730
+ configuration: this.dictationConfig
731
+ }));
732
+ };
733
+ this.webSocket.onmessage = (event) => {
734
+ const message = JSON.parse(event.data);
735
+ if (message.type === "config") {
736
+ this.mediaRecorder.start(250);
737
+ } else if (message.type === "transcript") {
738
+ this.dispatchEvent(new CustomEvent("transcript", {
739
+ detail: message,
740
+ bubbles: true,
741
+ composed: true
742
+ }));
743
+ }
744
+ };
745
+ this.webSocket.onerror = (event) => {
746
+ this.dispatchEvent(new CustomEvent("error", {
747
+ detail: event,
748
+ bubbles: true,
749
+ composed: true
750
+ }));
751
+ };
752
+ this.webSocket.onclose = (event) => {
753
+ this.dispatchEvent(new CustomEvent("stream-closed", {
754
+ detail: event,
755
+ bubbles: true,
756
+ composed: true
757
+ }));
758
+ };
759
+ }
760
+ async stopRecording() {
761
+ this.mediaRecorder.stop();
762
+ if (this.webSocket?.readyState === WebSocket.OPEN) {
763
+ this.webSocket.send(JSON.stringify({
764
+ type: "end"
765
+ }));
766
+ }
767
+ const timeOut = setTimeout(() => {
768
+ if (this.webSocket?.readyState === WebSocket.OPEN) {
769
+ this.webSocket.close();
770
+ }
771
+ }, 1e4);
772
+ this.webSocket.onclose = () => {
773
+ this.webSocket?.close();
774
+ clearTimeout(timeOut);
775
+ };
776
+ }
777
+ };
778
+
779
+ // dist/RecorderManager.js
780
+ var RecorderManager = class extends EventTarget {
781
+ constructor() {
782
+ super(...arguments);
783
+ this.devices = [];
784
+ this.selectedDevice = "";
785
+ this.recordingState = "stopped";
786
+ this._mediaStream = null;
787
+ this._audioService = null;
788
+ this._dictationService = null;
789
+ }
790
+ async initialize() {
791
+ const deviceResponse = await getAudioDevices();
792
+ this.devices = deviceResponse.devices;
793
+ this.selectedDevice = deviceResponse.defaultDeviceId || "";
794
+ return deviceResponse;
795
+ }
796
+ async startRecording(params) {
797
+ this._updateRecordingState("initializing");
798
+ try {
799
+ this._mediaStream = await navigator.mediaDevices.getUserMedia({
800
+ audio: { deviceId: this.selectedDevice }
801
+ });
802
+ this._audioService = new AudioService(this._mediaStream);
803
+ this._dictationService = new DictationService(this._mediaStream, params);
804
+ this._dictationService.addEventListener("error", (e5) => this.dispatchEvent(new CustomEvent("error", {
805
+ detail: e5.detail,
806
+ bubbles: true,
807
+ composed: true
808
+ })));
809
+ this._dictationService.addEventListener("stream-closed", () => this.stopRecording());
810
+ this._dictationService.addEventListener("transcript", (e5) => this.dispatchEvent(new CustomEvent("transcript", {
811
+ detail: e5.detail,
812
+ bubbles: true,
813
+ composed: true
814
+ })));
815
+ } catch (error) {
816
+ this.dispatchEvent(new CustomEvent("error", {
817
+ detail: error,
818
+ bubbles: true,
819
+ composed: true
820
+ }));
821
+ this._updateRecordingState("stopped");
822
+ return;
823
+ }
824
+ this._dictationService?.startRecording();
825
+ this._updateRecordingState("recording");
826
+ this._visualiserInterval = window.setInterval(() => {
827
+ const level = this._audioService ? this._audioService.getAudioLevel() * 3 : 0;
828
+ this.dispatchEvent(new CustomEvent("audio-level-changed", {
829
+ detail: { audioLevel: level },
830
+ bubbles: true,
831
+ composed: true
832
+ }));
833
+ }, 150);
834
+ }
835
+ async stopRecording() {
836
+ this._updateRecordingState("stopping");
837
+ if (this._visualiserInterval) {
838
+ clearInterval(this._visualiserInterval);
839
+ this._visualiserInterval = void 0;
840
+ }
841
+ if (this._mediaStream) {
842
+ this._mediaStream.getTracks().forEach((track) => track.stop());
843
+ this._mediaStream = null;
844
+ }
845
+ await this._dictationService?.stopRecording();
846
+ this._updateRecordingState("stopped");
847
+ }
848
+ _updateRecordingState(state) {
849
+ this.recordingState = state;
850
+ this.dispatchEvent(new CustomEvent("recording-state-changed", {
851
+ detail: { state },
852
+ bubbles: true,
853
+ composed: true
854
+ }));
855
+ }
856
+ };
857
+
858
+ // dist/styles/buttons.js
859
+ var ButtonStyles = i`
860
+ /* Default (plain) button styling */
861
+ button,
862
+ .button {
863
+ background: var(--action-plain-background);
864
+ /* border: 1px solid var(--action-plain-border-color); */
865
+ border: none;
866
+ color: var(--component-text-color);
867
+ cursor: pointer;
868
+ padding: 8px;
869
+ border-radius: var(--card-inner-border-radius);
870
+ display: inline-flex;
871
+ gap: 4px;
872
+ align-items: center;
873
+ justify-content: center;
874
+ transition: background 0.3s ease;
875
+ font-family: var(--component-font-family);
876
+ }
877
+
878
+ button:hover,
879
+ .button:hover {
880
+ background: var(--action-plain-background-hover);
881
+ }
882
+
883
+ button:focus-visible {
884
+ outline: 2px solid var(--action-accent-background);
885
+ outline-offset: 2px;
886
+ }
887
+
888
+ /* Accent variant */
889
+ button.accent,
890
+ .button.accent {
891
+ background: var(--action-accent-background);
892
+ color: var(--action-accent-text-color);
893
+ border: none;
894
+ }
895
+
896
+ button.accent:hover,
897
+ .button.accent:hover {
898
+ background: var(--action-accent-background-hover);
899
+ }
900
+
901
+ /* Accent variant */
902
+ button.red,
903
+ .button.red {
904
+ background: var(--action-red-background);
905
+ color: var(--action-red-text-color);
906
+ border: none;
907
+ }
908
+
909
+ button.red:hover,
910
+ .button.red:hover {
911
+ background: var(--action-red-background-hover);
912
+ }
913
+ `;
914
+ var buttons_default = ButtonStyles;
915
+
916
+ // dist/styles/select.js
917
+ var SelectStyles = i`
918
+ label {
919
+ display: block;
920
+ font-size: 0.8rem;
921
+ padding-bottom: 0.5rem;
922
+ font-weight: 500;
923
+ color: var(--component-text-color);
924
+ pointer-events: none;
925
+ }
926
+ select {
927
+ background: var(--card-background);
928
+ color: var(--component-text-color);
929
+ border: 1px solid var(--card-border-color);
930
+ padding: var(--card-padding);
931
+ border-radius: var(--card-inner-border-radius);
932
+ outline: none;
933
+ width: 100%;
934
+ }
935
+
936
+ select:disabled {
937
+ opacity: 0.5;
938
+ cursor: not-allowed;
939
+ }
940
+
941
+ select:hover {
942
+ background: var(--action-plain-background-hover);
943
+ }
944
+
945
+ select:focus-visible {
946
+ outline: 2px solid var(--action-accent-background);
947
+ /* outline-offset: 2px; */
948
+ }
949
+ `;
950
+ var select_default = SelectStyles;
951
+
952
+ // dist/constants.js
953
+ var LANGUAGES_SUPPORTED = ["en", "da"];
954
+ var DEFAULT_DICTATION_CONFIG = {
955
+ primaryLanguage: "en",
956
+ interimResults: true,
957
+ spokenPunctuation: true,
958
+ automaticPunctuation: true,
959
+ model: "others"
960
+ };
961
+
962
+ // dist/styles/callout.js
963
+ var CalloutStyles = i`
964
+ .callout {
965
+ background: var(--callout-accent-background);
966
+ border: 1px solid var(--callout-accent-border);
967
+ color: var(--callout-accent-text);
968
+ padding: 8px;
969
+ border-radius: var(--card-inner-border-radius);
970
+ display: flex;
971
+ font-size: 0.9rem;
972
+ gap: 8px;
973
+ align-items: flex-start;
974
+ &.red {
975
+ background: var(--callout-red-background);
976
+ border: 1px solid var(--callout-red-border);
977
+ color: var(--callout-red-text);
978
+ }
979
+ &.orange {
980
+ background: var(--callout-orange-background);
981
+ border: 1px solid var(--callout-orange-border);
982
+ color: var(--callout-orange-text);
983
+ }
984
+ }
985
+ `;
986
+ var callout_default = CalloutStyles;
987
+
988
+ // dist/components/settings-menu.js
989
+ var SettingsMenu = class SettingsMenu2 extends r4 {
990
+ constructor() {
991
+ super(...arguments);
992
+ this.devices = [];
993
+ this.selectedDevice = "";
994
+ this.selectedLanguage = "";
995
+ this.settingsDisabled = false;
996
+ }
997
+ _selectDevice(deviceId) {
998
+ this.selectedDevice = deviceId;
999
+ const device = this.devices.find((d3) => d3.deviceId === deviceId);
1000
+ this.dispatchEvent(new CustomEvent("recording-device-changed", {
1001
+ detail: device,
1002
+ bubbles: true,
1003
+ composed: true
1004
+ }));
1005
+ }
1006
+ render() {
1007
+ return x`
1008
+ <div class="mic-selector">
1009
+ <button id="settings-popover-button" popovertarget="settings-popover">
1010
+ <icon-settings></icon-settings>
1011
+ </button>
1012
+ <div id="settings-popover" popover>
1013
+ <div class="settings-wrapper">
1014
+ ${this.settingsDisabled ? x`
1015
+ <div class="callout orange">
1016
+ Recording is in progress. Stop recording to change settings.
1017
+ </div>
1018
+ ` : ""}
1019
+ <div class="form-group">
1020
+ <label id="device-select-label" for="device-select">
1021
+ Recording Device
1022
+ </label>
1023
+ <select
1024
+ id="device-select"
1025
+ aria-labelledby="device-select-label"
1026
+ @change=${(e5) => {
1027
+ this._selectDevice(e5.target.value);
1028
+ }}
1029
+ ?disabled=${this.settingsDisabled}
1030
+ >
1031
+ ${this.devices.map((device) => x`
1032
+ <option
1033
+ value=${device.deviceId}
1034
+ ?selected=${this.selectedDevice === device.deviceId}
1035
+ >
1036
+ ${device.label || "Unknown Device"}
1037
+ </option>
1038
+ `)}
1039
+ </select>
1040
+ </div>
1041
+ <div class="form-group">
1042
+ <label id="language-select-label" for="language-select">
1043
+ Dictation Language
1044
+ </label>
1045
+ <select
1046
+ id="language-select"
1047
+ aria-labelledby="language-select-label"
1048
+ @change=${(e5) => {
1049
+ this._selectDevice(e5.target.value);
1050
+ }}
1051
+ ?disabled=${this.settingsDisabled}
1052
+ >
1053
+ ${LANGUAGES_SUPPORTED.map((language) => x`
1054
+ <option
1055
+ value=${language}
1056
+ ?selected=${this.selectedLanguage === language}
1057
+ >
1058
+ ${getLanguageName(language)}
1059
+ </option>
1060
+ `)}
1061
+ </select>
1062
+ </div>
1063
+ </div>
1064
+ </div>
1065
+ </div>
1066
+ `;
1067
+ }
1068
+ };
1069
+ SettingsMenu.styles = [
1070
+ i`
1071
+ :host {
1072
+ display: block;
1073
+ font-family: var(--component-font-family);
1074
+ }
1075
+ /* Retain the anchor-name styling for this component */
1076
+ #settings-popover-button {
1077
+ anchor-name: --settings_popover_btn;
1078
+ }
1079
+ [popover] {
1080
+ margin: 0;
1081
+ padding: 16px;
1082
+ border: 0;
1083
+ background: var(--card-background);
1084
+ border: 1px solid var(--card-border-color);
1085
+ border-radius: var(--card-border-radius);
1086
+ box-shadow: var(--card-box-shadow);
1087
+ z-index: 1000;
1088
+ max-width: 260px;
1089
+ width: 100%;
1090
+ min-width: 200px;
1091
+ position-anchor: --settings_popover_btn;
1092
+ position-area: bottom;
1093
+ position-visibility: always;
1094
+ /* inset: unset; */
1095
+ transform: translateX(40%);
1096
+ overflow-x: hidden;
1097
+ }
1098
+ .settings-wrapper {
1099
+ display: flex;
1100
+ flex-direction: column;
1101
+ gap: 20px;
1102
+ }
1103
+ `,
1104
+ buttons_default,
1105
+ select_default,
1106
+ callout_default
1107
+ ];
1108
+ __decorate([
1109
+ n4({ type: Array })
1110
+ ], SettingsMenu.prototype, "devices", void 0);
1111
+ __decorate([
1112
+ n4({ type: String })
1113
+ ], SettingsMenu.prototype, "selectedDevice", void 0);
1114
+ __decorate([
1115
+ n4({ type: String })
1116
+ ], SettingsMenu.prototype, "selectedLanguage", void 0);
1117
+ __decorate([
1118
+ n4({ type: Boolean })
1119
+ ], SettingsMenu.prototype, "settingsDisabled", void 0);
1120
+ SettingsMenu = __decorate([
1121
+ t3("settings-menu")
1122
+ ], SettingsMenu);
1123
+
1124
+ // dist/components/audio-visualiser.js
1125
+ var AudioVisualiser = class AudioVisualiser2 extends r4 {
1126
+ constructor() {
1127
+ super(...arguments);
1128
+ this.level = 0;
1129
+ this.active = true;
1130
+ }
1131
+ render() {
1132
+ const activeSegments = Math.round(this.level * 5);
1133
+ const segments = [];
1134
+ for (let i5 = 0; i5 < 5; i5 += 1) {
1135
+ segments.push(x`
1136
+ <div class="segment ${i5 < activeSegments ? "active" : ""}"></div>
1137
+ `);
1138
+ }
1139
+ return x`
1140
+ <div class="container ${this.active ? "active" : ""}">${segments}</div>
1141
+ `;
1142
+ }
1143
+ };
1144
+ AudioVisualiser.styles = i`
1145
+ :host {
1146
+ height: 100%;
1147
+ }
1148
+ .container {
1149
+ display: flex;
1150
+ width: 8px;
1151
+ flex-direction: column-reverse; /* Bottom-up stacking */
1152
+ height: 100%;
1153
+ gap: 1px;
1154
+ opacity: 0.5;
1155
+ &.active {
1156
+ opacity: 1;
1157
+ }
1158
+ }
1159
+ .segment {
1160
+ flex: 1;
1161
+ background-color: var(--action-accent-text-color);
1162
+ transition: background-color 0.25s;
1163
+ border-radius: 1px;
1164
+ opacity: 0.5;
1165
+ }
1166
+ .segment.active {
1167
+ opacity: 1;
1168
+ }
1169
+ `;
1170
+ __decorate([
1171
+ n4({ type: Number })
1172
+ ], AudioVisualiser.prototype, "level", void 0);
1173
+ __decorate([
1174
+ n4({ type: Boolean })
1175
+ ], AudioVisualiser.prototype, "active", void 0);
1176
+ AudioVisualiser = __decorate([
1177
+ t3("audio-visualiser")
1178
+ ], AudioVisualiser);
1179
+
1180
+ // dist/icons/icons.js
1181
+ var IconMicOn = class IconMicOn2 extends r4 {
1182
+ render() {
1183
+ return x`
1184
+ <div style="display: flex">
1185
+ <svg
1186
+ xmlns="http://www.w3.org/2000/svg"
1187
+ width="20"
1188
+ height="20"
1189
+ viewBox="0 0 24 24"
1190
+ fill="none"
1191
+ stroke="currentColor"
1192
+ stroke-width="2"
1193
+ stroke-linecap="round"
1194
+ stroke-linejoin="round"
1195
+ class="lucide lucide-mic"
1196
+ >
1197
+ <path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
1198
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2" />
1199
+ <line x1="12" x2="12" y1="19" y2="22" />
1200
+ </svg>
1201
+ </div>
1202
+ `;
1203
+ }
1204
+ };
1205
+ IconMicOn = __decorate([
1206
+ t3("icon-mic-on")
1207
+ ], IconMicOn);
1208
+ var IconMicOff = class IconMicOff2 extends r4 {
1209
+ render() {
1210
+ return x` <div style="display: flex">
1211
+ <svg
1212
+ xmlns="http://www.w3.org/2000/svg"
1213
+ width="20"
1214
+ height="20"
1215
+ viewBox="0 0 24 24"
1216
+ fill="none"
1217
+ stroke="currentColor"
1218
+ stroke-width="2"
1219
+ stroke-linecap="round"
1220
+ stroke-linejoin="round"
1221
+ class="lucide lucide-mic-off"
1222
+ >
1223
+ <line x1="2" x2="22" y1="2" y2="22" />
1224
+ <path d="M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" />
1225
+ <path d="M5 10v2a7 7 0 0 0 12 5" />
1226
+ <path d="M15 9.34V5a3 3 0 0 0-5.68-1.33" />
1227
+ <path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
1228
+ <line x1="12" x2="12" y1="19" y2="22" />
1229
+ </svg>
1230
+ </div>`;
1231
+ }
1232
+ };
1233
+ IconMicOff = __decorate([
1234
+ t3("icon-mic-off")
1235
+ ], IconMicOff);
1236
+ var IconRecording = class IconRecording2 extends r4 {
1237
+ render() {
1238
+ return x`
1239
+ <div style="display: flex;">
1240
+ <svg
1241
+ xmlns="http://www.w3.org/2000/svg"
1242
+ width="20"
1243
+ height="20"
1244
+ viewBox="0 0 24 24"
1245
+ fill="none"
1246
+ stroke="currentColor"
1247
+ stroke-width="2"
1248
+ stroke-linecap="round"
1249
+ stroke-linejoin="round"
1250
+ class="lucide lucide-circle-stop"
1251
+ >
1252
+ <circle cx="12" cy="12" r="10" />
1253
+ <rect x="9" y="9" width="6" height="6" rx="1" fill="currentColor" />
1254
+ </svg>
1255
+ </div>
1256
+ `;
1257
+ }
1258
+ };
1259
+ IconRecording = __decorate([
1260
+ t3("icon-recording")
1261
+ ], IconRecording);
1262
+ var IconSettings = class IconSettings2 extends r4 {
1263
+ render() {
1264
+ return x`<div style="display: flex">
1265
+ <svg
1266
+ xmlns="http://www.w3.org/2000/svg"
1267
+ width="20"
1268
+ height="20"
1269
+ viewBox="0 0 24 24"
1270
+ fill="none"
1271
+ stroke="currentColor"
1272
+ stroke-width="2"
1273
+ stroke-linecap="round"
1274
+ stroke-linejoin="round"
1275
+ class="lucide lucide-settings-2"
1276
+ >
1277
+ <path d="M20 7h-9" />
1278
+ <path d="M14 17H5" />
1279
+ <circle cx="17" cy="17" r="3" />
1280
+ <circle cx="7" cy="7" r="3" />
1281
+ </svg>
1282
+ </div>`;
1283
+ }
1284
+ };
1285
+ IconSettings = __decorate([
1286
+ t3("icon-settings")
1287
+ ], IconSettings);
1288
+ var IconLoadingSpinner = class IconLoadingSpinner2 extends r4 {
1289
+ render() {
1290
+ return x`<div style="display: flex">
1291
+ <svg
1292
+ xmlns="http://www.w3.org/2000/svg"
1293
+ width="20"
1294
+ height="20"
1295
+ viewBox="0 0 24 24"
1296
+ fill="none"
1297
+ stroke="currentColor"
1298
+ stroke-width="2"
1299
+ stroke-linecap="round"
1300
+ stroke-linejoin="round"
1301
+ class="lucide lucide-loader-circle spin"
1302
+ >
1303
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
1304
+ </svg>
1305
+ </div>`;
1306
+ }
1307
+ };
1308
+ IconLoadingSpinner.styles = i`
1309
+ @keyframes spin {
1310
+ 0% {
1311
+ transform: rotate(0deg);
1312
+ }
1313
+ 100% {
1314
+ transform: rotate(360deg);
1315
+ }
1316
+ }
1317
+ .spin {
1318
+ animation: spin 1s linear infinite;
1319
+ }
1320
+ `;
1321
+ IconLoadingSpinner = __decorate([
1322
+ t3("icon-loading-spinner")
1323
+ ], IconLoadingSpinner);
1324
+
1325
+ // dist/styles/theme.js
1326
+ var ThemeStyles = i`
1327
+ :host {
1328
+ /* Component Defaults */
1329
+ --component-font-family: 'Segoe UI', Roboto, sans-serif;
1330
+ --component-text-color: #333;
1331
+
1332
+ /* Card Defaults */
1333
+ --card-background: #fff;
1334
+ --card-border-color: #ddd;
1335
+ --card-padding: 4px;
1336
+ --card-border-radius: 8px;
1337
+ --card-inner-border-radius: 6px;
1338
+ --card-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
1339
+
1340
+ /* Actions Defaults */
1341
+ --action-plain-border-color: #ccc;
1342
+ --action-plain-background-hover: #ddd;
1343
+
1344
+ --action-accent-background: #007bff;
1345
+ --action-accent-background-hover: #0056b3;
1346
+ --action-accent-text-color: #fff;
1347
+
1348
+ --action-red-background: #dc3545;
1349
+ --action-red-background-hover: #bd2130;
1350
+ --action-red-text-color: #fff;
1351
+
1352
+ /* Callout Defaults */
1353
+ --callout-accent-background: #007bff33;
1354
+ --callout-accent-border: #007bff99;
1355
+ --callout-accent-text: #007bff;
1356
+
1357
+ --callout-red-background: #dc354533;
1358
+ --callout-red-border: #dc354599;
1359
+ --callout-red-text: #dc3545;
1360
+
1361
+ --callout-orange-background: #fd7e1433;
1362
+ --callout-orange-border: #fd7e1499;
1363
+ --callout-orange-text: #fd7e14;
1364
+
1365
+ /* Visualiser Defaults */
1366
+ --visualiser-background: #e0e0e0;
1367
+ --visualiser-level-color: #28a745;
1368
+ }
1369
+
1370
+ @media (prefers-color-scheme: dark) {
1371
+ :host {
1372
+ /* Component Dark */
1373
+ --component-text-color: #eee;
1374
+
1375
+ /* Card Dark */
1376
+ --card-background: #333;
1377
+ --card-border-color: #555;
1378
+
1379
+ /* Actions Dark */
1380
+ --action-plain-border-color: #555;
1381
+ --action-plain-background: #333;
1382
+ --action-plain-background-hover: #444;
1383
+
1384
+ --action-accent-background: #0056b3;
1385
+ --action-accent-background-hover: #003d80;
1386
+
1387
+ /* Visualiser Dark */
1388
+ --visualiser-background: #fff;
1389
+ }
1390
+ }
1391
+ :host {
1392
+ box-sizing: border-box;
1393
+ font-family: var(--component-font-family);
1394
+ color: var(--component-text-color);
1395
+ }
1396
+ `;
1397
+ var theme_default = ThemeStyles;
1398
+
1399
+ // dist/styles/ComponentStyles.js
1400
+ var ComponentStyles = i`
1401
+ .wrapper {
1402
+ background-color: var(--card-background);
1403
+ border: 1px solid var(--card-border-color);
1404
+ border-radius: var(--card-border-radius);
1405
+ box-shadow: var(--card-box-shadow);
1406
+ padding: var(--card-padding);
1407
+ display: flex;
1408
+ width: min-content;
1409
+ gap: 4px;
1410
+ height: 46px;
1411
+ box-sizing: border-box;
1412
+ overflow: hidden;
1413
+ }
1414
+ h2 {
1415
+ margin: 0 0 10px;
1416
+ font-size: 1rem;
1417
+ font-weight: 500;
1418
+ }
1419
+ label {
1420
+ font-size: 0.9rem;
1421
+ margin-right: 8px;
1422
+ }
1423
+ select {
1424
+ padding: 4px 6px;
1425
+ font-size: 0.9rem;
1426
+ border: 1px solid var(--card-border-color);
1427
+ border-radius: 4px;
1428
+ background-color: var(--card-background);
1429
+ color: inherit;
1430
+ }
1431
+
1432
+ .visualiser {
1433
+ width: 16px;
1434
+ height: 100%;
1435
+ background: var(--visualiser-background);
1436
+ margin-top: 8px;
1437
+ border-radius: 5px;
1438
+ overflow: hidden;
1439
+ display: flex;
1440
+ align-items: flex-end;
1441
+ }
1442
+ .level {
1443
+ height: 100%;
1444
+ width: 100%;
1445
+ background: var(--visualiser-level-color);
1446
+ transition: width 0.1s ease-in-out;
1447
+ }
1448
+ `;
1449
+ var ComponentStyles_default = ComponentStyles;
1450
+
1451
+ // dist/CortiDictation.js
1452
+ var CortiDictation = class extends r4 {
1453
+ constructor() {
1454
+ super(...arguments);
1455
+ this.devices = [];
1456
+ this.recordingState = "stopped";
1457
+ this.dictationConfig = DEFAULT_DICTATION_CONFIG;
1458
+ this._audioLevel = 0;
1459
+ this.recorderManager = new RecorderManager();
1460
+ }
1461
+ async connectedCallback() {
1462
+ super.connectedCallback();
1463
+ await this.recorderManager.initialize();
1464
+ this.devices = this.recorderManager.devices;
1465
+ const eventHandlers = {
1466
+ "recording-state-changed": (e5) => {
1467
+ this.recordingState = e5.detail.state;
1468
+ },
1469
+ "audio-level-changed": (e5) => {
1470
+ this._audioLevel = e5.detail.audioLevel;
1471
+ this.requestUpdate();
1472
+ }
1473
+ };
1474
+ const eventsToRelay = [
1475
+ "recording-state-changed",
1476
+ "audio-level-changed",
1477
+ "error",
1478
+ "transcript"
1479
+ ];
1480
+ eventsToRelay.forEach((eventName) => {
1481
+ this.recorderManager.addEventListener(eventName, (e5) => {
1482
+ const customEvent = e5;
1483
+ if (eventHandlers[eventName]) {
1484
+ eventHandlers[eventName](customEvent);
1485
+ }
1486
+ this.dispatchEvent(new CustomEvent(eventName, {
1487
+ detail: customEvent.detail,
1488
+ bubbles: true,
1489
+ composed: true
1490
+ }));
1491
+ });
1492
+ });
1493
+ }
1494
+ toggleRecording() {
1495
+ this._toggleRecording();
1496
+ }
1497
+ _toggleRecording() {
1498
+ if (!this.authToken)
1499
+ return;
1500
+ if (this.recordingState === "recording") {
1501
+ this.recorderManager.stopRecording();
1502
+ } else if (this.recordingState === "stopped") {
1503
+ this.recorderManager.startRecording({
1504
+ dictationConfig: this.dictationConfig,
1505
+ authToken: this.authToken
1506
+ });
1507
+ }
1508
+ }
1509
+ // Handle device change events if needed
1510
+ async _onRecordingDeviceChanged(event) {
1511
+ const customEvent = event;
1512
+ if (!this.authToken)
1513
+ return;
1514
+ this.recorderManager.selectedDevice = customEvent.detail.deviceId;
1515
+ if (this.recordingState === "recording") {
1516
+ await this.recorderManager.stopRecording();
1517
+ await this.recorderManager.startRecording({
1518
+ dictationConfig: this.dictationConfig,
1519
+ authToken: this.authToken
1520
+ });
1521
+ }
1522
+ }
1523
+ render() {
1524
+ const isConfigured = this.authToken;
1525
+ if (!isConfigured) {
1526
+ return x`
1527
+ <div class="wrapper">
1528
+ <div class="callout red tiny">
1529
+ Please configure the server settings in the parent component.
1530
+ </div>
1531
+ </div>
1532
+ `;
1533
+ }
1534
+ const isLoading = this.recordingState === "initializing" || this.recordingState === "stopping";
1535
+ const isRecording = this.recordingState === "recording";
1536
+ return x`
1537
+ <div class="wrapper">
1538
+ <button
1539
+ @click=${this._toggleRecording}
1540
+ class=${isRecording ? "red" : "accent"}
1541
+ >
1542
+ ${isLoading ? x`<icon-loading-spinner></icon-loading-spinner>` : isRecording ? x`<icon-recording></icon-recording>` : x`<icon-mic-on></icon-mic-on>`}
1543
+ <audio-visualiser
1544
+ .level=${this._audioLevel}
1545
+ .active=${isRecording}
1546
+ ></audio-visualiser>
1547
+ </button>
1548
+
1549
+ <settings-menu
1550
+ .devices=${this.devices}
1551
+ .selectedDevice=${this.recorderManager.selectedDevice}
1552
+ ?settingsDisabled=${this.recordingState !== "stopped"}
1553
+ @recording-device-changed=${this._onRecordingDeviceChanged}
1554
+ ></settings-menu>
1555
+ </div>
1556
+ `;
1557
+ }
1558
+ };
1559
+ CortiDictation.styles = [buttons_default, theme_default, ComponentStyles_default, callout_default];
1560
+ __decorate([
1561
+ n4({ type: Array })
1562
+ ], CortiDictation.prototype, "devices", void 0);
1563
+ __decorate([
1564
+ n4({ type: String, reflect: true })
1565
+ ], CortiDictation.prototype, "recordingState", void 0);
1566
+ __decorate([
1567
+ n4({ type: Object })
1568
+ ], CortiDictation.prototype, "dictationConfig", void 0);
1569
+ __decorate([
1570
+ n4({ type: String })
1571
+ ], CortiDictation.prototype, "authToken", void 0);
1572
+ __decorate([
1573
+ r6()
1574
+ ], CortiDictation.prototype, "_audioLevel", void 0);
1575
+ var CortiDictation_default = CortiDictation;
1576
+
1577
+ // dist/index.js
1578
+ if (!customElements.get("corti-dictation")) {
1579
+ customElements.define("corti-dictation", CortiDictation_default);
1580
+ }
1581
+ var index_default = CortiDictation_default;
1582
+ export {
1583
+ index_default as default
1584
+ };
1585
+ /*! Bundled license information:
1586
+
1587
+ @lit/reactive-element/css-tag.js:
1588
+ (**
1589
+ * @license
1590
+ * Copyright 2019 Google LLC
1591
+ * SPDX-License-Identifier: BSD-3-Clause
1592
+ *)
1593
+
1594
+ @lit/reactive-element/reactive-element.js:
1595
+ (**
1596
+ * @license
1597
+ * Copyright 2017 Google LLC
1598
+ * SPDX-License-Identifier: BSD-3-Clause
1599
+ *)
1600
+
1601
+ lit-html/lit-html.js:
1602
+ (**
1603
+ * @license
1604
+ * Copyright 2017 Google LLC
1605
+ * SPDX-License-Identifier: BSD-3-Clause
1606
+ *)
1607
+
1608
+ lit-element/lit-element.js:
1609
+ (**
1610
+ * @license
1611
+ * Copyright 2017 Google LLC
1612
+ * SPDX-License-Identifier: BSD-3-Clause
1613
+ *)
1614
+
1615
+ lit-html/is-server.js:
1616
+ (**
1617
+ * @license
1618
+ * Copyright 2022 Google LLC
1619
+ * SPDX-License-Identifier: BSD-3-Clause
1620
+ *)
1621
+
1622
+ @lit/reactive-element/decorators/custom-element.js:
1623
+ (**
1624
+ * @license
1625
+ * Copyright 2017 Google LLC
1626
+ * SPDX-License-Identifier: BSD-3-Clause
1627
+ *)
1628
+
1629
+ @lit/reactive-element/decorators/property.js:
1630
+ (**
1631
+ * @license
1632
+ * Copyright 2017 Google LLC
1633
+ * SPDX-License-Identifier: BSD-3-Clause
1634
+ *)
1635
+
1636
+ @lit/reactive-element/decorators/state.js:
1637
+ (**
1638
+ * @license
1639
+ * Copyright 2017 Google LLC
1640
+ * SPDX-License-Identifier: BSD-3-Clause
1641
+ *)
1642
+
1643
+ @lit/reactive-element/decorators/event-options.js:
1644
+ (**
1645
+ * @license
1646
+ * Copyright 2017 Google LLC
1647
+ * SPDX-License-Identifier: BSD-3-Clause
1648
+ *)
1649
+
1650
+ @lit/reactive-element/decorators/base.js:
1651
+ (**
1652
+ * @license
1653
+ * Copyright 2017 Google LLC
1654
+ * SPDX-License-Identifier: BSD-3-Clause
1655
+ *)
1656
+
1657
+ @lit/reactive-element/decorators/query.js:
1658
+ (**
1659
+ * @license
1660
+ * Copyright 2017 Google LLC
1661
+ * SPDX-License-Identifier: BSD-3-Clause
1662
+ *)
1663
+
1664
+ @lit/reactive-element/decorators/query-all.js:
1665
+ (**
1666
+ * @license
1667
+ * Copyright 2017 Google LLC
1668
+ * SPDX-License-Identifier: BSD-3-Clause
1669
+ *)
1670
+
1671
+ @lit/reactive-element/decorators/query-async.js:
1672
+ (**
1673
+ * @license
1674
+ * Copyright 2017 Google LLC
1675
+ * SPDX-License-Identifier: BSD-3-Clause
1676
+ *)
1677
+
1678
+ @lit/reactive-element/decorators/query-assigned-elements.js:
1679
+ (**
1680
+ * @license
1681
+ * Copyright 2021 Google LLC
1682
+ * SPDX-License-Identifier: BSD-3-Clause
1683
+ *)
1684
+
1685
+ @lit/reactive-element/decorators/query-assigned-nodes.js:
1686
+ (**
1687
+ * @license
1688
+ * Copyright 2017 Google LLC
1689
+ * SPDX-License-Identifier: BSD-3-Clause
1690
+ *)
1691
+ */