@arcgis/ai-components 5.1.0-next.61 → 5.1.0-next.63

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.
Files changed (41) hide show
  1. package/dist/cdn/5RA2JKQ5.js +3 -0
  2. package/dist/cdn/6IDESYBP.js +2 -0
  3. package/dist/cdn/E4J4SWHB.js +2 -0
  4. package/dist/cdn/MP7AEALE.js +2 -0
  5. package/dist/cdn/SOPNKXO5.js +2 -0
  6. package/dist/cdn/VJGA26MX.js +2 -0
  7. package/dist/cdn/assets/assistant-chat-card/t9n/messages.en.json +1 -1
  8. package/dist/cdn/index.js +1 -1
  9. package/dist/cdn/main.css +1 -1
  10. package/dist/components/arcgis-assistant/customElement.d.ts +4 -0
  11. package/dist/components/arcgis-assistant/customElement.js +30 -30
  12. package/dist/components/arcgis-assistant-chat/customElement.d.ts +2 -0
  13. package/dist/components/arcgis-assistant-chat/customElement.js +7 -7
  14. package/dist/components/arcgis-assistant-chat-card/customElement.d.ts +6 -0
  15. package/dist/components/arcgis-assistant-chat-card/customElement.js +101 -25
  16. package/dist/components/arcgis-assistant-chat-entry/customElement.d.ts +2 -0
  17. package/dist/components/arcgis-assistant-chat-entry/customElement.js +129 -33
  18. package/dist/components/arcgis-assistant-chat-entry/index.js +1 -0
  19. package/dist/components/arcgis-assistant-chat-entry-speech-input/customElement.d.ts +26 -0
  20. package/dist/components/arcgis-assistant-chat-entry-speech-input/customElement.js +437 -0
  21. package/dist/components/arcgis-assistant-chat-entry-speech-input/index.d.ts +1 -0
  22. package/dist/components/arcgis-assistant-chat-entry-speech-input/index.js +2 -0
  23. package/dist/components/arcgis-assistant-chat-entry-speech-input/support/types.d.ts +15 -0
  24. package/dist/components/arcgis-assistant-shell/customElement.d.ts +2 -0
  25. package/dist/components/arcgis-assistant-shell/customElement.js +6 -6
  26. package/dist/docs/api.json +1 -1
  27. package/dist/docs/docs.json +1 -1
  28. package/dist/docs/vscode.html-custom-data.json +1 -1
  29. package/dist/docs/web-types.json +1 -1
  30. package/dist/index.d.ts +10 -0
  31. package/dist/loader.js +6 -5
  32. package/dist/types/lumina.d.ts +16 -5
  33. package/dist/types/preact.d.ts +17 -5
  34. package/dist/types/react.d.ts +18 -5
  35. package/dist/types/stencil.d.ts +16 -5
  36. package/package.json +6 -6
  37. package/dist/cdn/ETKNVWKV.js +0 -2
  38. package/dist/cdn/JPYSTYTV.js +0 -2
  39. package/dist/cdn/NN7QKIMP.js +0 -2
  40. package/dist/cdn/WO6WO3SH.js +0 -3
  41. package/dist/cdn/ZLYDPB4L.js +0 -2
@@ -1,66 +1,162 @@
1
1
  /* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
2
- import { c as u } from "../../chunks/runtime.js";
3
- import { css as h, html as l } from "lit";
4
- import { LitElement as d, createEvent as c, nothing as p } from "@arcgis/lumina";
5
- import { createRef as f, ref as g } from "lit/directives/ref.js";
6
- import { watch as m } from "@arcgis/core/core/reactiveUtils.js";
7
- import { u as y } from "../../chunks/useT9n.js";
8
- import _ from "@arcgis/core/core/Collection.js";
9
- const v = h`.assistant-chat-entry__input-container{display:flex;flex-direction:column}.assistant-chat-entry__footer-start{display:flex;gap:var(--calcite-spacing-md);flex-wrap:wrap;align-items:center}.assistant-chat-entry__footer-end{display:flex;gap:var(--calcite-spacing-md);align-items:center}.assistant-chat-entry__status-indicator{width:9px;height:9px;border-radius:100%;background-color:var(--calcite-color-status-success)}.assistant-chat-entry__status-indicator[data-status=working]{background-color:var(--calcite-color-status-warning)}.assistant-chat-entry__status-indicator[data-status=error]{background-color:var(--calcite-color-status-danger)}.assistant-chat-entry__status-text{text-transform:capitalize}`;
10
- class w extends d {
2
+ import { c as p } from "../../chunks/runtime.js";
3
+ import { css as d, html as c } from "lit";
4
+ import { LitElement as f, createEvent as h, nothing as g } from "@arcgis/lumina";
5
+ import { createRef as v, ref as m } from "lit/directives/ref.js";
6
+ import { watch as y } from "@arcgis/core/core/reactiveUtils.js";
7
+ import { u as _ } from "../../chunks/useT9n.js";
8
+ import V from "@arcgis/core/core/Collection.js";
9
+ const I = d`.assistant-chat-entry__input-container{display:flex;flex-direction:column}.assistant-chat-entry__footer-start{display:flex;gap:var(--calcite-spacing-md);flex-wrap:wrap;align-items:center}.assistant-chat-entry__footer-end{display:flex;gap:var(--calcite-spacing-md);align-items:center}.assistant-chat-entry__status-indicator{width:9px;height:9px;border-radius:100%;background-color:var(--calcite-color-status-success)}.assistant-chat-entry__status-indicator[data-status=working]{background-color:var(--calcite-color-status-warning)}.assistant-chat-entry__status-indicator[data-status=error]{background-color:var(--calcite-color-status-danger)}.assistant-chat-entry__status-text{text-transform:capitalize}`;
10
+ function l(u) {
11
+ const { baseValue: t, transcript: s } = u;
12
+ if (!s)
13
+ return t;
14
+ const e = t.trim();
15
+ return e ? `${e} ${s}` : s;
16
+ }
17
+ class b extends f {
11
18
  constructor() {
12
- super(...arguments), this.#s = f(), this.#t = -1, this.#e = "", this._messages = y({ blocking: !0 }), this.keyboardShortcutsDisabled = !1, this.awaitingResponse = !1, this.inputValue = "", this.messages = new _([]), this.arcgisCancel = c(), this.arcgisSubmit = c();
19
+ super(...arguments), this.#t = v(), this.#s = -1, this.#i = "", this.#e = null, this.#a = (t) => {
20
+ const s = t.detail;
21
+ this._applyVoiceInputTranscript(s?.transcript);
22
+ }, this.#n = () => {
23
+ this._startVoiceInputSession();
24
+ }, this.#r = () => {
25
+ this._finishVoiceInputSession();
26
+ }, this.#o = (t) => {
27
+ const s = t.detail;
28
+ this._applyVoiceInputTranscript(s?.transcript, { final: !0 });
29
+ }, this.#c = (t) => {
30
+ }, this._messages = _({ blocking: !0 }), this.keyboardShortcutsDisabled = !1, this.awaitingResponse = !1, this.inputValue = "", this.voiceInputEnabled = !1, this.messages = new V([]), this.arcgisCancel = h(), this.arcgisSubmit = h();
13
31
  }
14
32
  static {
15
- this.properties = { _userMessages: 16, keyboardShortcutsDisabled: 5, entryPlaceholder: 1, awaitingResponse: 5, inputValue: 1, status: 1, messages: 0 };
33
+ this.properties = { _userMessages: 16, keyboardShortcutsDisabled: 5, entryPlaceholder: 1, awaitingResponse: 5, inputValue: 1, status: 1, voiceInputEnabled: 5, messages: 0 };
16
34
  }
17
35
  static {
18
- this.styles = v;
36
+ this.styles = I;
19
37
  }
20
- #s;
21
38
  #t;
39
+ #s;
40
+ #i;
22
41
  #e;
42
+ #a;
43
+ #n;
44
+ #r;
45
+ #o;
46
+ #c;
23
47
  get _userMessages() {
24
48
  return this.messages.toArray().filter((t) => t.role === "user").map(({ content: t }) => t);
25
49
  }
26
50
  loaded() {
27
- this.manager.onLifecycle(() => [
28
- m(() => this.inputValue, (t) => {
29
- this.#s.value && (this.#s.value.value = t);
30
- }, { initial: !0 })
31
- ]);
51
+ this.manager.onLifecycle(() => {
52
+ const t = [
53
+ {
54
+ eventType: "arcgisVoiceInputInterimTranscription",
55
+ callback: this.#a
56
+ },
57
+ {
58
+ eventType: "arcgisVoiceInputStart",
59
+ callback: this.#n
60
+ },
61
+ {
62
+ eventType: "arcgisVoiceInputStop",
63
+ callback: this.#r
64
+ },
65
+ {
66
+ eventType: "arcgisVoiceInputTranscription",
67
+ callback: this.#o
68
+ },
69
+ {
70
+ eventType: "arcgisVoiceInputTranscriptionStreamChunk",
71
+ callback: this.#c
72
+ }
73
+ ];
74
+ for (const { eventType: s, callback: e } of t)
75
+ this.el.addEventListener(s, e);
76
+ return [
77
+ y(() => this.inputValue, (s) => {
78
+ this.#t.value && (this.#t.value.value = s);
79
+ }, { initial: !0 }),
80
+ {
81
+ remove: () => {
82
+ for (const { eventType: s, callback: e } of t)
83
+ this.el.removeEventListener(s, e);
84
+ }
85
+ }
86
+ ];
87
+ });
32
88
  }
33
89
  async _submitMessage() {
34
90
  if (this.awaitingResponse) {
35
91
  this.arcgisCancel.emit();
36
92
  return;
37
93
  }
38
- const t = this.#s.value?.value.trim();
39
- t && (this.arcgisSubmit.emit(t), this.#t = -1, this.#e = "", this.#s.value && (this.#s.value.value = "", await this.#s.value.setFocus()));
94
+ const t = this.#t.value?.value.trim();
95
+ t && (this.arcgisSubmit.emit(t), this.#s = -1, this.#i = "", this._clearVoiceInputSession(), this.#t.value && (this.#t.value.value = "", await this.#t.value.setFocus()));
40
96
  }
41
- async _navigateHistory(t, i) {
42
- const s = this.#s.value;
43
- if (!s)
97
+ async _navigateHistory(t, s) {
98
+ const e = this.#t.value;
99
+ if (!e)
44
100
  return;
45
- const e = this._userMessages;
46
- if (e.length === 0)
101
+ const i = this._userMessages;
102
+ if (i.length === 0)
47
103
  return;
48
- const r = s.value ?? "", n = s.shadowRoot?.querySelector("textarea"), a = n?.selectionStart, o = n?.selectionEnd;
49
- if (!(a == null || o == null) && !(a !== o || t === "up" && a !== 0 || t === "down" && a !== r.length)) {
104
+ const a = e.value ?? "", r = e.shadowRoot?.querySelector("textarea"), n = r?.selectionStart, o = r?.selectionEnd;
105
+ if (!(n == null || o == null) && !(n !== o || t === "up" && n !== 0 || t === "down" && n !== a.length)) {
50
106
  if (t === "up") {
51
- this.#t === -1 ? (this.#e = r, this.#t = e.length - 1) : this.#t = Math.max(0, this.#t - 1), s.value = e[this.#t] ?? "", i.preventDefault();
107
+ this.#s === -1 ? (this.#i = a, this.#s = i.length - 1) : this.#s = Math.max(0, this.#s - 1), e.value = i[this.#s] ?? "", s.preventDefault();
108
+ return;
109
+ }
110
+ this.#s !== -1 && (this.#s < i.length - 1 ? (this.#s += 1, e.value = i[this.#s] ?? "") : (this.#s = -1, e.value = this.#i), s.preventDefault());
111
+ }
112
+ }
113
+ _startVoiceInputSession() {
114
+ this.#e = {
115
+ baseValue: this.#t.value?.value?.trim() ?? "",
116
+ phase: "listening",
117
+ transcript: ""
118
+ };
119
+ }
120
+ _finishVoiceInputSession() {
121
+ const t = this.#t.value, s = this.#e;
122
+ if (!t) {
123
+ this._clearVoiceInputSession();
124
+ return;
125
+ }
126
+ if (!s) {
127
+ this._setDraftValue(t.value?.trim() ?? "");
128
+ return;
129
+ }
130
+ const e = { ...s, phase: "stopped" }, i = l(e);
131
+ this.#e = e, this._setDraftValue(i);
132
+ }
133
+ async _applyVoiceInputTranscript(t, s) {
134
+ const e = this.#t.value, i = this.#e;
135
+ if (!e || !t || !i)
136
+ return;
137
+ if (i.phase === "stopped") {
138
+ const n = l(i);
139
+ if ((e.value?.trim() ?? "") !== n) {
140
+ this._clearVoiceInputSession();
52
141
  return;
53
142
  }
54
- this.#t !== -1 && (this.#t < e.length - 1 ? (this.#t += 1, s.value = e[this.#t] ?? "") : (this.#t = -1, s.value = this.#e), i.preventDefault());
55
143
  }
144
+ const a = { ...i, transcript: t }, r = l(a);
145
+ this.#e = a, this._setDraftValue(r), s?.final && a.phase === "stopped" && await e.setFocus();
146
+ }
147
+ _setDraftValue(t) {
148
+ this.#t.value && (this.#t.value.value = t), this.#s = -1, this.#i = t;
149
+ }
150
+ _clearVoiceInputSession() {
151
+ this.#e = null;
56
152
  }
57
153
  render() {
58
- return l`<div class="assistant-chat-entry__input-container"><calcite-text-area .value=${this.#s.value?.value} .placeholder=${this.entryPlaceholder ?? this._messages.entryPlaceholder} resize=vertical @keydown=${async (t) => {
154
+ return c`<div class="assistant-chat-entry__input-container"><calcite-text-area .value=${this.#t.value?.value} .placeholder=${this.entryPlaceholder ?? this._messages.entryPlaceholder} resize=vertical @keydown=${async (t) => {
59
155
  t.altKey || t.ctrlKey || t.metaKey || t.shiftKey || this.keyboardShortcutsDisabled || (t.key === "Enter" ? (t.preventDefault(), await this._submitMessage()) : t.key === "ArrowUp" ? await this._navigateHistory("up", t) : t.key === "ArrowDown" && await this._navigateHistory("down", t));
60
- }} ${g(this.#s)}><div slot=footer-start class="assistant-chat-entry__footer-start"><slot name=entry-actions-start></slot></div><div slot=footer-end class="assistant-chat-entry__footer-end">${this.status ? l`<div id=tooltip-status class="assistant-chat-entry__status-indicator" data-status=${this.status ?? p}></div><calcite-tooltip reference-element=tooltip-status offset-distance=12><span class="assistant-chat-entry__status-text">${this.status}</span></calcite-tooltip>` : null}<calcite-button .iconStart=${this.awaitingResponse ? "circle-stop" : "send"} slot=footer-end round @click=${() => void this._submitMessage()}>${this.awaitingResponse ? this._messages.stopButtonLabel : this._messages.askButtonLabel}</calcite-button></div></calcite-text-area></div>`;
156
+ }} ${m(this.#t)}><div slot=footer-start class="assistant-chat-entry__footer-start"><slot name=entry-actions-start></slot></div><div slot=footer-end class="assistant-chat-entry__footer-end">${this.status ? c`<div id=tooltip-status class="assistant-chat-entry__status-indicator" data-status=${this.status ?? g}></div><calcite-tooltip reference-element=tooltip-status offset-distance=12><span class="assistant-chat-entry__status-text">${this.status}</span></calcite-tooltip>` : null}${this.voiceInputEnabled ? c`<arcgis-assistant-chat-entry-speech-input .awaitingResponse=${this.awaitingResponse}></arcgis-assistant-chat-entry-speech-input>` : null}<calcite-button .iconStart=${this.awaitingResponse ? "circle-stop" : "send"} slot=footer-end round @click=${() => void this._submitMessage()}>${this.awaitingResponse ? this._messages.stopButtonLabel : this._messages.askButtonLabel}</calcite-button></div></calcite-text-area></div>`;
61
157
  }
62
158
  }
63
- u("arcgis-assistant-chat-entry", w);
159
+ p("arcgis-assistant-chat-entry", b);
64
160
  export {
65
- w as ArcgisAssistantChatEntry
161
+ b as ArcgisAssistantChatEntry
66
162
  };
@@ -1,4 +1,5 @@
1
1
  import "@esri/calcite-components/components/calcite-text-area";
2
2
  import "@esri/calcite-components/components/calcite-tooltip";
3
+ import "../arcgis-assistant-chat-entry-speech-input/index.js";
3
4
  import "@esri/calcite-components/components/calcite-button";
4
5
  export * from "./customElement.js";
@@ -0,0 +1,26 @@
1
+ /// <reference path="../../index.d.ts" />
2
+ import type { PublicLitElement as LitElement } from "@arcgis/lumina";
3
+ import type { VoiceInputErrorCode, VoiceInputMode, VoiceInputTranscriptDetail, VoiceInputTranscriptionStreamChunkDetail } from "./support/types.js";
4
+
5
+ /** @internal */
6
+ export abstract class ArcgisAssistantChatEntrySpeechInput extends LitElement {
7
+ /** @default false */
8
+ accessor awaitingResponse: boolean;
9
+ accessor language: string | undefined;
10
+ /** @default "web-speech" */
11
+ accessor mode: VoiceInputMode;
12
+ readonly arcgisVoiceInputError: import("@arcgis/lumina").TargetedEvent<this, { errorCode: VoiceInputErrorCode; }>;
13
+ readonly arcgisVoiceInputInterimTranscription: import("@arcgis/lumina").TargetedEvent<this, VoiceInputTranscriptDetail>;
14
+ readonly arcgisVoiceInputStart: import("@arcgis/lumina").TargetedEvent<this, void>;
15
+ readonly arcgisVoiceInputStop: import("@arcgis/lumina").TargetedEvent<this, void>;
16
+ readonly arcgisVoiceInputTranscription: import("@arcgis/lumina").TargetedEvent<this, VoiceInputTranscriptDetail>;
17
+ readonly arcgisVoiceInputTranscriptionStreamChunk: import("@arcgis/lumina").TargetedEvent<this, VoiceInputTranscriptionStreamChunkDetail>;
18
+ readonly "@eventTypes": {
19
+ arcgisVoiceInputError: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputError"]["detail"];
20
+ arcgisVoiceInputInterimTranscription: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputInterimTranscription"]["detail"];
21
+ arcgisVoiceInputStart: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputStart"]["detail"];
22
+ arcgisVoiceInputStop: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputStop"]["detail"];
23
+ arcgisVoiceInputTranscription: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputTranscription"]["detail"];
24
+ arcgisVoiceInputTranscriptionStreamChunk: ArcgisAssistantChatEntrySpeechInput["arcgisVoiceInputTranscriptionStreamChunk"]["detail"];
25
+ };
26
+ }
@@ -0,0 +1,437 @@
1
+ /* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
2
+ import { c as C } from "../../chunks/runtime.js";
3
+ import { css as S, html as R } from "lit";
4
+ import { when as f, watch as u } from "@arcgis/core/core/reactiveUtils.js";
5
+ import { LitElement as y, createEvent as h, nothing as v } from "@arcgis/lumina";
6
+ import w from "@arcgis/core/core/Accessor.js";
7
+ import { property as l, subclass as m } from "@arcgis/core/core/accessorSupport/decorators.js";
8
+ const T = S`.assistant-chat-entry-speech-input__button{--calcite-button-background-color: var(--calcite-color-transparent);--calcite-button-border-color: transparent;--calcite-button-icon-color: var(--calcite-color-text-3);--calcite-button-text-color: var(--calcite-color-text-3);flex:0 0 auto;position:relative}.assistant-chat-entry-speech-input__button[data-state=disabled]{--calcite-button-icon-color: var(--calcite-color-text-3);opacity:var(--calcite-opacity-disabled)}.assistant-chat-entry-speech-input__button[data-state=listening]{--calcite-button-background-color: color-mix( in srgb, var(--calcite-color-brand) 14%, var(--calcite-color-foreground-1) );--calcite-button-border-color: color-mix(in srgb, var(--calcite-color-brand) 24%, transparent);--calcite-button-icon-color: var(--calcite-color-brand);--calcite-button-text-color: var(--calcite-color-brand);box-shadow:var(--calcite-shadow-sm)}.assistant-chat-entry-speech-input__button[data-state=listening]:hover{--calcite-button-background-color: color-mix( in srgb, var(--calcite-color-brand-hover, var(--calcite-color-brand)) 18%, var(--calcite-color-foreground-1) )}.assistant-chat-entry-speech-input__button[data-state=listening]:active{--calcite-button-background-color: color-mix( in srgb, var(--calcite-color-brand) 24%, var(--calcite-color-foreground-1) )}.assistant-chat-entry-speech-input__button[data-state=processing]{--calcite-button-background-color: color-mix( in srgb, var(--calcite-color-brand) 10%, var(--calcite-color-foreground-1) );--calcite-button-border-color: color-mix(in srgb, var(--calcite-color-brand) 20%, transparent);--calcite-button-icon-color: var(--calcite-color-brand);--calcite-button-text-color: var(--calcite-color-brand)}.assistant-chat-entry-speech-input__button[data-state=error]{--calcite-button-background-color: color-mix( in srgb, var(--calcite-color-status-danger) 12%, var(--calcite-color-foreground-1) );--calcite-button-border-color: color-mix(in srgb, var(--calcite-color-status-danger) 24%, transparent);--calcite-button-icon-color: var(--calcite-color-status-danger);--calcite-button-text-color: var(--calcite-color-status-danger)}.assistant-chat-entry-speech-input__button[data-state=listening]:after{content:"";position:absolute;inset:-4px;border:1px solid color-mix(in srgb,var(--calcite-color-brand) 40%,transparent);border-radius:inherit;opacity:0;pointer-events:none;transform:scale(.92);animation:assistant-chat-entry-speech-input-recording-pulse 1.8s ease-out infinite}@keyframes assistant-chat-entry-speech-input-recording-pulse{0%{opacity:.65;transform:scale(.92)}70%{opacity:0;transform:scale(1.16)}to{opacity:0;transform:scale(1.16)}}@media(prefers-reduced-motion){.assistant-chat-entry-speech-input__button[data-state=listening]:after{animation:none;opacity:1;transform:none}}`;
9
+ var k = Object.defineProperty, I = Object.getOwnPropertyDescriptor, p = (t, e, s, r) => {
10
+ for (var i = r > 1 ? void 0 : r ? I(e, s) : e, n = t.length - 1, o; n >= 0; n--)
11
+ (o = t[n]) && (i = (r ? o(e, s, i) : o(i)) || i);
12
+ return r && i && k(e, s, i), i;
13
+ };
14
+ let a = class extends w {
15
+ constructor(t) {
16
+ super(t), this.state = "idle", this.liveTranscript = "", this.transcript = "", this.errorCode = void 0;
17
+ }
18
+ static isSupported() {
19
+ return !1;
20
+ }
21
+ };
22
+ p([
23
+ l()
24
+ ], a.prototype, "language", 2);
25
+ p([
26
+ l({ readOnly: !0 })
27
+ ], a.prototype, "state", 2);
28
+ p([
29
+ l({ readOnly: !0 })
30
+ ], a.prototype, "liveTranscript", 2);
31
+ p([
32
+ l({ readOnly: !0 })
33
+ ], a.prototype, "transcript", 2);
34
+ p([
35
+ l({ readOnly: !0 })
36
+ ], a.prototype, "errorCode", 2);
37
+ a = p([
38
+ m("SpeechController")
39
+ ], a);
40
+ const x = [
41
+ "audio/webm;codecs=opus",
42
+ "audio/webm",
43
+ "audio/mp4",
44
+ "audio/ogg;codecs=opus",
45
+ "audio/ogg"
46
+ ];
47
+ function d(t) {
48
+ return t.replace(/\s+/gu, " ").trim();
49
+ }
50
+ var O = Object.defineProperty, M = Object.getOwnPropertyDescriptor, g = (t, e, s, r) => {
51
+ for (var i = r > 1 ? void 0 : r ? M(e, s) : e, n = t.length - 1, o; n >= 0; n--)
52
+ (o = t[n]) && (i = (r ? o(e, s, i) : o(i)) || i);
53
+ return r && i && O(e, s, i), i;
54
+ };
55
+ let c = class extends a {
56
+ constructor(t) {
57
+ super(t), this._activeSessionId = null, this._mediaRecorder = null, this._mediaRecorderChunkIndex = 0, this._mediaRecorderStopReason = null, this._mediaStream = null, this._pendingChunkOperations = /* @__PURE__ */ new Set(), this._recordedChunks = [], this.handleRecording = null, this.chunkTimeSlice = 3e3;
58
+ }
59
+ get _mimeType() {
60
+ return typeof window > "u" || typeof window.MediaRecorder?.isTypeSupported != "function" ? "" : x.find((t) => window.MediaRecorder.isTypeSupported(t)) ?? "";
61
+ }
62
+ initialize() {
63
+ c.isSupported() && this.addHandles(
64
+ f(
65
+ () => !!this.errorCode,
66
+ () => {
67
+ this._set("state", "error");
68
+ }
69
+ )
70
+ );
71
+ }
72
+ destroy() {
73
+ this._mediaRecorder && (this._mediaRecorder.onstart = null, this._mediaRecorder.ondataavailable = null, this._mediaRecorder.onerror = null, this._mediaRecorder.onstop = null), this.cancel(), this._mediaRecorder = null;
74
+ }
75
+ // Stop waits for any in-flight chunk transcription before finalizing the session transcript.
76
+ _queuePendingChunkOperation(t) {
77
+ this._pendingChunkOperations.add(t), t.finally(() => {
78
+ this._pendingChunkOperations.delete(t);
79
+ });
80
+ }
81
+ async _awaitPendingChunkOperations() {
82
+ this._pendingChunkOperations.size && await Promise.allSettled(Array.from(this._pendingChunkOperations));
83
+ }
84
+ _onDataAvailable(t) {
85
+ const e = this._activeSessionId;
86
+ e != null && this._queuePendingChunkOperation(this._processDataAvailable(t, e));
87
+ }
88
+ async _processDataAvailable(t, e) {
89
+ const s = t.data;
90
+ if (!s.size || e !== this._activeSessionId)
91
+ return;
92
+ this._recordedChunks.push(s);
93
+ const r = s.type || this._mediaRecorder?.mimeType || this._mimeType, i = this._mediaRecorderStopReason === "toggle" && this._mediaRecorder?.state === "inactive";
94
+ try {
95
+ if (!this.handleRecording)
96
+ return;
97
+ const n = d(
98
+ await this.handleRecording(s, r, this._mediaRecorderChunkIndex, i) ?? ""
99
+ );
100
+ if (e !== this._activeSessionId)
101
+ return;
102
+ n && this._set("liveTranscript", d(`${this.liveTranscript} ${n}`));
103
+ } catch (n) {
104
+ if (e !== this._activeSessionId)
105
+ return;
106
+ this._failSession(
107
+ n instanceof Error && n.message === "transcription-unavailable" ? "transcription-unavailable" : "transcription-failed"
108
+ );
109
+ return;
110
+ }
111
+ !i && e === this._activeSessionId && (this._mediaRecorderChunkIndex += 1);
112
+ }
113
+ _failSession(t) {
114
+ const e = this._mediaRecorder;
115
+ if (e) {
116
+ e.onstart = null, e.ondataavailable = null, e.onerror = null, e.onstop = null;
117
+ try {
118
+ e.state !== "inactive" && e.stop();
119
+ } catch {
120
+ }
121
+ }
122
+ this._activeSessionId = null, this._mediaRecorder = null, this._mediaRecorderChunkIndex = 0, this._mediaRecorderStopReason = null, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._releaseMediaStream(), this._set("liveTranscript", ""), this._set("transcript", ""), this._set("errorCode", t);
123
+ }
124
+ _onError() {
125
+ this._failSession("recording-failed");
126
+ }
127
+ _onStart() {
128
+ this._set("state", "listening");
129
+ }
130
+ _onStop() {
131
+ this._handleStop();
132
+ }
133
+ _releaseMediaStream() {
134
+ this._mediaStream?.getTracks().forEach((t) => t.stop()), this._mediaStream = null;
135
+ }
136
+ async _handleStop() {
137
+ const t = this._mediaRecorder, e = this._activeSessionId, s = this._mediaRecorderStopReason, r = t?.mimeType || this._recordedChunks.find((o) => !!o.type)?.type || "", i = [...this._recordedChunks];
138
+ if (this._mediaRecorder = null, this._mediaRecorderChunkIndex = 0, this._releaseMediaStream(), s === "cancel") {
139
+ this._activeSessionId === e && (this._activeSessionId = null), this._mediaRecorderStopReason = null, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._set("liveTranscript", ""), this._set("transcript", ""), this._set("state", "idle"), this._set("errorCode", void 0);
140
+ return;
141
+ }
142
+ if (e == null) {
143
+ this._mediaRecorderStopReason = null, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._set("state", "idle"), this._set("errorCode", void 0);
144
+ return;
145
+ }
146
+ if (await this._awaitPendingChunkOperations(), e !== this._activeSessionId)
147
+ return;
148
+ if (!(r ? new Blob(i, { type: r }) : new Blob(i)).size) {
149
+ this._activeSessionId === e && (this._activeSessionId = null), this._mediaRecorderStopReason = null, this._recordedChunks = [], this._set("errorCode", "recording-failed");
150
+ return;
151
+ }
152
+ this._set("state", "processing"), this._set("transcript", d(`${this.transcript} ${this.liveTranscript}`)), this._set("liveTranscript", ""), this._activeSessionId === e && (this._activeSessionId = null), this._set("state", "idle"), this._set("errorCode", void 0), this._mediaRecorderStopReason = null, this._recordedChunks = [];
153
+ }
154
+ start() {
155
+ if (!c.isSupported()) {
156
+ this._set("errorCode", "not-supported");
157
+ return;
158
+ }
159
+ const t = Date.now();
160
+ this._activeSessionId = t, this._mediaRecorderChunkIndex = 0, this._mediaRecorderStopReason = null, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._set("liveTranscript", ""), this._set("transcript", ""), this._set("errorCode", void 0), navigator.mediaDevices.getUserMedia({ audio: !0 }).then((e) => {
161
+ if (t !== this._activeSessionId) {
162
+ e.getTracks().forEach((i) => i.stop());
163
+ return;
164
+ }
165
+ const s = this._mimeType, r = s ? new window.MediaRecorder(e, { mimeType: s }) : new window.MediaRecorder(e);
166
+ this._mediaStream = e, this._mediaRecorder = r, this._mediaRecorderChunkIndex = 0, this._mediaRecorderStopReason = null, this._recordedChunks = [], r.ondataavailable = this._onDataAvailable.bind(this), r.onerror = this._onError.bind(this), r.onstart = this._onStart.bind(this), r.onstop = this._onStop.bind(this), this._mediaRecorder.start(this.chunkTimeSlice);
167
+ }).catch((e) => {
168
+ t === this._activeSessionId && (this._activeSessionId = null, this._mediaRecorder = null, this._mediaRecorderChunkIndex = 0, this._mediaRecorderStopReason = null, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._releaseMediaStream(), e instanceof DOMException && e.name === "NotAllowedError" ? this._set("errorCode", "not-allowed") : this._set("errorCode", "recording-failed"));
169
+ });
170
+ }
171
+ stop() {
172
+ if (this._mediaRecorder) {
173
+ this._mediaRecorderStopReason = "toggle";
174
+ try {
175
+ this._mediaRecorder.state !== "inactive" ? this._mediaRecorder.stop() : this._handleStop();
176
+ } catch {
177
+ }
178
+ }
179
+ }
180
+ cancel() {
181
+ const t = this._mediaRecorder;
182
+ if (this._activeSessionId = null, this._mediaRecorderStopReason = "cancel", this._mediaRecorderChunkIndex = 0, this._pendingChunkOperations.clear(), this._recordedChunks = [], this._set("liveTranscript", ""), this._set("transcript", ""), this._set("state", "idle"), this._set("errorCode", void 0), !t) {
183
+ this._releaseMediaStream();
184
+ return;
185
+ }
186
+ try {
187
+ if (t.state !== "inactive") {
188
+ t.stop();
189
+ return;
190
+ }
191
+ } catch {
192
+ }
193
+ this._mediaRecorder = null, this._releaseMediaStream();
194
+ }
195
+ static isSupported() {
196
+ return typeof window < "u" && !!(window.MediaRecorder && navigator.mediaDevices?.getUserMedia);
197
+ }
198
+ };
199
+ g([
200
+ l()
201
+ ], c.prototype, "_mimeType", 1);
202
+ g([
203
+ l()
204
+ ], c.prototype, "handleRecording", 2);
205
+ g([
206
+ l()
207
+ ], c.prototype, "chunkTimeSlice", 2);
208
+ c = g([
209
+ m("MediaRecorderController")
210
+ ], c);
211
+ var E = Object.getOwnPropertyDescriptor, $ = (t, e, s, r) => {
212
+ for (var i = r > 1 ? void 0 : r ? E(e, s) : e, n = t.length - 1, o; n >= 0; n--)
213
+ (o = t[n]) && (i = o(i) || i);
214
+ return i;
215
+ };
216
+ function b() {
217
+ if (typeof window > "u")
218
+ return null;
219
+ const t = window;
220
+ return t.SpeechRecognition ?? t.webkitSpeechRecognition ?? null;
221
+ }
222
+ let _ = class extends a {
223
+ constructor(t) {
224
+ super(t), this._isCancelled = !1, this._recognition = null;
225
+ }
226
+ initialize() {
227
+ const t = b();
228
+ if (!t)
229
+ return;
230
+ const e = new t();
231
+ e.continuous = !0, e.interimResults = !0, this.language && (e.lang = this.language), e.onstart = this._onStart.bind(this), e.onresult = this._onResult.bind(this), e.onerror = this._onError.bind(this), e.onend = this._onEnd.bind(this), e.onspeechend = this._onSpeechEnd.bind(this), this._recognition = e, this.addHandles(
232
+ f(
233
+ () => !!this.errorCode,
234
+ () => {
235
+ this._set("state", "error");
236
+ }
237
+ )
238
+ );
239
+ }
240
+ destroy() {
241
+ this._recognition && (this._recognition.onstart = null, this._recognition.onresult = null, this._recognition.onerror = null, this._recognition.onend = null, this._recognition.onspeechend = null, this.cancel(), this._recognition = null);
242
+ }
243
+ _onStart() {
244
+ this._isCancelled = !1, this._set("state", "listening");
245
+ }
246
+ // SpeechRecognition result lists are cumulative, so rebuild finalized and live text from the full list.
247
+ _onResult(t) {
248
+ const { finalTranscript: e, liveTranscript: s } = Array.from(t.results).reduce(
249
+ (r, i) => (i.isFinal ? r.finalTranscript += i[0].transcript : r.liveTranscript += i[0].transcript, r),
250
+ { finalTranscript: "", liveTranscript: "" }
251
+ );
252
+ this._set("transcript", d(e)), this._set("liveTranscript", d(s));
253
+ }
254
+ _onError(t) {
255
+ if (t.error === "aborted" && this._isCancelled) {
256
+ this._set("state", "idle");
257
+ return;
258
+ }
259
+ let e = "unhandled";
260
+ switch (t.error) {
261
+ case "no-speech":
262
+ e = "no-speech";
263
+ break;
264
+ case "service-not-allowed":
265
+ case "not-allowed":
266
+ e = "not-allowed";
267
+ break;
268
+ default:
269
+ e = "unhandled";
270
+ }
271
+ this._set("errorCode", e);
272
+ }
273
+ // Natural end can arrive before the last interim segment becomes final, so preserve that trailing text.
274
+ _onEnd() {
275
+ const t = d(`${this.transcript} ${this.liveTranscript}`);
276
+ if (this._set("liveTranscript", ""), this._isCancelled) {
277
+ this._set("transcript", ""), this._set("state", "idle"), this._set("errorCode", void 0);
278
+ return;
279
+ }
280
+ this.errorCode ? this._set("transcript", "") : (this._set("transcript", t), this._set("state", "idle")), this._set("errorCode", void 0);
281
+ }
282
+ _onSpeechEnd() {
283
+ this._set("state", "processing");
284
+ }
285
+ _reset(t = !1) {
286
+ this._isCancelled = t, this._set("liveTranscript", ""), this._set("transcript", ""), this._set("errorCode", void 0), this._set("state", "idle");
287
+ }
288
+ start() {
289
+ if (!this._recognition) {
290
+ this._set("errorCode", "not-supported");
291
+ return;
292
+ }
293
+ this._reset(!1);
294
+ try {
295
+ this._recognition.start();
296
+ } catch {
297
+ this._set("errorCode", "unhandled");
298
+ }
299
+ }
300
+ stop() {
301
+ if (this._recognition) {
302
+ this._set("state", "processing");
303
+ try {
304
+ this._recognition.stop();
305
+ } catch {
306
+ }
307
+ }
308
+ }
309
+ cancel() {
310
+ if (this._recognition) {
311
+ this._reset(!0);
312
+ try {
313
+ this._recognition.abort();
314
+ } catch {
315
+ }
316
+ }
317
+ }
318
+ static isSupported() {
319
+ return !!b();
320
+ }
321
+ };
322
+ _ = $([
323
+ m("WebSpeechController")
324
+ ], _);
325
+ class D extends y {
326
+ constructor() {
327
+ super(...arguments), this._resolvedMode = "disabled", this.awaitingResponse = !1, this.mode = "web-speech", this.arcgisVoiceInputError = h(), this.arcgisVoiceInputStart = h(), this.arcgisVoiceInputStop = h(), this.arcgisVoiceInputInterimTranscription = h(), this.arcgisVoiceInputTranscription = h(), this.arcgisVoiceInputTranscriptionStreamChunk = h();
328
+ }
329
+ static {
330
+ this.properties = { _resolvedMode: 16, _state: 16, _errorCode: 16, _liveTranscript: 16, _transcript: 16, _isButtonDisabled: 16, _buttonLabel: 16, awaitingResponse: 5, language: 1, mode: 1 };
331
+ }
332
+ static {
333
+ this.styles = T;
334
+ }
335
+ get _state() {
336
+ return this._speechController?.state ?? "idle";
337
+ }
338
+ get _errorCode() {
339
+ return this._speechController?.errorCode ?? null;
340
+ }
341
+ get _liveTranscript() {
342
+ return this._speechController?.liveTranscript ?? "";
343
+ }
344
+ get _transcript() {
345
+ return this._speechController?.transcript ?? "";
346
+ }
347
+ get _isButtonDisabled() {
348
+ return this._resolvedMode === "disabled" || this.awaitingResponse || this._state === "processing";
349
+ }
350
+ get _buttonLabel() {
351
+ if (this.awaitingResponse)
352
+ return "Voice input unavailable while assistant is responding";
353
+ if (this._resolvedMode === "disabled")
354
+ return "Voice input unavailable";
355
+ switch (this._state) {
356
+ case "error":
357
+ return this._errorCode === "not-allowed" ? "Microphone permission denied. Retry voice input" : "Retry voice input";
358
+ case "listening":
359
+ return "Stop voice input";
360
+ case "processing":
361
+ return "Processing voice input";
362
+ default:
363
+ return "Start voice input";
364
+ }
365
+ }
366
+ loaded() {
367
+ this.manager.onLifecycle(() => [
368
+ u(() => [this.mode, this.language], () => {
369
+ this._configureController();
370
+ }, { initial: !0 }),
371
+ u(() => this.awaitingResponse, (e) => {
372
+ e && this._cancelActiveSession();
373
+ }, { initial: !0 }),
374
+ u(() => this._liveTranscript, (e) => {
375
+ if (e) {
376
+ const s = d(`${this._transcript} ${e}`);
377
+ this.arcgisVoiceInputInterimTranscription.emit({ transcript: s });
378
+ }
379
+ }),
380
+ u(() => this._transcript, (e) => {
381
+ e && this.arcgisVoiceInputTranscription.emit({ transcript: e });
382
+ }),
383
+ u(() => this._state, (e) => {
384
+ e === "error" && this._errorCode && this.arcgisVoiceInputError.emit({ errorCode: this._errorCode });
385
+ })
386
+ ]);
387
+ }
388
+ disconnectedCallback() {
389
+ super.disconnectedCallback(), this._destroySpeechController();
390
+ }
391
+ _configureController() {
392
+ const e = this._resolveMode();
393
+ this._destroySpeechController(), this._resolvedMode = e, e !== "disabled" && (this._speechController = e === "web-speech" ? new _({
394
+ language: this.language
395
+ }) : new c({
396
+ language: this.language,
397
+ handleRecording: this._handleRecording.bind(this)
398
+ }));
399
+ }
400
+ _destroySpeechController() {
401
+ this._speechController?.cancel(), this._speechController?.destroy(), this._speechController = void 0;
402
+ }
403
+ async _handleToggle() {
404
+ if (!(this._isButtonDisabled || !this._speechController)) {
405
+ if (this._state === "listening") {
406
+ this._speechController.stop(), this.arcgisVoiceInputStop.emit();
407
+ return;
408
+ }
409
+ this._speechController.start(), this.arcgisVoiceInputStart.emit();
410
+ }
411
+ }
412
+ async _handleRecording(e, s, r, i) {
413
+ let n;
414
+ return this.arcgisVoiceInputTranscriptionStreamChunk.emit({
415
+ blob: e,
416
+ chunkIndex: r,
417
+ isFinal: i,
418
+ mimeType: s,
419
+ respondWithTranscript: (o) => {
420
+ n = o;
421
+ }
422
+ }), n;
423
+ }
424
+ _resolveMode() {
425
+ return this.mode === "disabled" ? "disabled" : this.mode === "web-speech" && _.isSupported() ? "web-speech" : c.isSupported() ? "media-recorder" : "disabled";
426
+ }
427
+ async _cancelActiveSession() {
428
+ this._speechController && this._resolvedMode !== "disabled" && this._speechController.cancel();
429
+ }
430
+ render() {
431
+ return R`<calcite-button appearance=transparent class="assistant-chat-entry-speech-input__button" data-mode=${this._resolvedMode ?? v} data-state=${(this._resolvedMode === "disabled" ? "disabled" : this._state) ?? v} .disabled=${this._isButtonDisabled} icon-start=microphone kind=neutral .label=${this._buttonLabel} .loading=${this._state === "processing"} round scale=m @click=${() => void this._handleToggle()}></calcite-button>`;
432
+ }
433
+ }
434
+ C("arcgis-assistant-chat-entry-speech-input", D);
435
+ export {
436
+ D as ArcgisAssistantChatEntrySpeechInput
437
+ };