@corti/dictation-web 0.0.0-rc.359 → 0.0.0-test.562

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 (189) hide show
  1. package/README.md +14 -5
  2. package/dist/CortiDictation.d.ts +6 -2
  3. package/dist/CortiDictation.js +36 -14
  4. package/dist/CortiDictation.js.map +1 -1
  5. package/dist/bundle.js +2802 -1571
  6. package/dist/components/audio-visualiser.d.ts +3 -2
  7. package/dist/components/audio-visualiser.js +29 -40
  8. package/dist/components/audio-visualiser.js.map +1 -1
  9. package/dist/components/corti-dictation.d.ts +123 -0
  10. package/dist/components/corti-dictation.js +224 -0
  11. package/dist/components/corti-dictation.js.map +1 -0
  12. package/dist/components/device-selector.d.ts +24 -0
  13. package/dist/components/device-selector.js +106 -0
  14. package/dist/components/device-selector.js.map +1 -0
  15. package/dist/components/language-selector.d.ts +24 -0
  16. package/dist/components/language-selector.js +100 -0
  17. package/dist/components/language-selector.js.map +1 -0
  18. package/dist/components/recording-button.d.ts +37 -0
  19. package/dist/components/recording-button.js +203 -0
  20. package/dist/components/recording-button.js.map +1 -0
  21. package/dist/components/settings-menu.d.ts +9 -13
  22. package/dist/components/settings-menu.js +42 -147
  23. package/dist/components/settings-menu.js.map +1 -1
  24. package/dist/constants.d.ts +3 -2
  25. package/dist/constants.js +33 -12
  26. package/dist/constants.js.map +1 -1
  27. package/dist/contexts/dictation-context.d.ts +97 -0
  28. package/dist/contexts/dictation-context.js +208 -0
  29. package/dist/contexts/dictation-context.js.map +1 -0
  30. package/dist/controllers/DictationController.d.ts +35 -0
  31. package/dist/controllers/DictationController.js +130 -0
  32. package/dist/controllers/DictationController.js.map +1 -0
  33. package/dist/controllers/MediaController.d.ts +31 -0
  34. package/dist/controllers/MediaController.js +99 -0
  35. package/dist/controllers/MediaController.js.map +1 -0
  36. package/dist/index.d.ts +9 -1
  37. package/dist/index.js +29 -3
  38. package/dist/index.js.map +1 -1
  39. package/dist/package.json +14 -0
  40. package/dist/src/components/audio-visualiser.d.ts +13 -0
  41. package/dist/src/components/audio-visualiser.js +54 -0
  42. package/dist/src/components/audio-visualiser.js.map +1 -0
  43. package/dist/src/components/corti-dictation.d.ts +108 -0
  44. package/dist/src/components/corti-dictation.js +201 -0
  45. package/dist/src/components/corti-dictation.js.map +1 -0
  46. package/dist/src/components/device-selector.d.ts +24 -0
  47. package/dist/src/components/device-selector.js +106 -0
  48. package/dist/src/components/device-selector.js.map +1 -0
  49. package/dist/src/components/language-selector.d.ts +24 -0
  50. package/dist/src/components/language-selector.js +100 -0
  51. package/dist/src/components/language-selector.js.map +1 -0
  52. package/dist/src/components/recording-button.d.ts +33 -0
  53. package/dist/src/components/recording-button.js +179 -0
  54. package/dist/src/components/recording-button.js.map +1 -0
  55. package/dist/src/components/settings-menu.d.ts +16 -0
  56. package/dist/src/components/settings-menu.js +80 -0
  57. package/dist/src/components/settings-menu.js.map +1 -0
  58. package/dist/src/constants.d.ts +4 -0
  59. package/dist/src/constants.js +19 -0
  60. package/dist/src/constants.js.map +1 -0
  61. package/dist/src/contexts/dictation-context.d.ts +83 -0
  62. package/dist/src/contexts/dictation-context.js +188 -0
  63. package/dist/src/contexts/dictation-context.js.map +1 -0
  64. package/dist/src/controllers/DictationController.d.ts +30 -0
  65. package/dist/src/controllers/DictationController.js +111 -0
  66. package/dist/src/controllers/DictationController.js.map +1 -0
  67. package/dist/src/controllers/MediaController.d.ts +25 -0
  68. package/dist/src/controllers/MediaController.js +83 -0
  69. package/dist/src/controllers/MediaController.js.map +1 -0
  70. package/dist/src/icons/icons.d.ts +17 -0
  71. package/dist/src/icons/icons.js +158 -0
  72. package/dist/src/icons/icons.js.map +1 -0
  73. package/dist/src/styles/ComponentStyles.d.ts +2 -0
  74. package/dist/src/styles/ComponentStyles.js +18 -0
  75. package/dist/src/styles/ComponentStyles.js.map +1 -0
  76. package/dist/src/styles/audio-visualiser.d.ts +2 -0
  77. package/dist/src/styles/audio-visualiser.js +33 -0
  78. package/dist/src/styles/audio-visualiser.js.map +1 -0
  79. package/dist/src/styles/buttons.d.ts +2 -0
  80. package/dist/src/styles/buttons.js +52 -0
  81. package/dist/src/styles/buttons.js.map +1 -0
  82. package/dist/src/styles/callout.d.ts +2 -0
  83. package/dist/src/styles/callout.js +23 -0
  84. package/dist/src/styles/callout.js.map +1 -0
  85. package/dist/src/styles/default-theme.d.ts +2 -0
  86. package/dist/src/styles/default-theme.js +50 -0
  87. package/dist/src/styles/default-theme.js.map +1 -0
  88. package/dist/src/styles/recording-button.d.ts +2 -0
  89. package/dist/src/styles/recording-button.js +8 -0
  90. package/dist/src/styles/recording-button.js.map +1 -0
  91. package/dist/src/styles/select.d.ts +2 -0
  92. package/dist/src/styles/select.js +36 -0
  93. package/dist/src/styles/select.js.map +1 -0
  94. package/dist/src/styles/settings-menu.d.ts +2 -0
  95. package/dist/src/styles/settings-menu.js +34 -0
  96. package/dist/src/styles/settings-menu.js.map +1 -0
  97. package/dist/src/types.d.ts +2 -0
  98. package/dist/src/types.js +2 -0
  99. package/dist/src/types.js.map +1 -0
  100. package/dist/src/utils/auth.d.ts +9 -0
  101. package/dist/src/utils/auth.js +21 -0
  102. package/dist/src/utils/auth.js.map +1 -0
  103. package/dist/src/utils/converters.d.ts +4 -0
  104. package/dist/src/utils/converters.js +5 -0
  105. package/dist/src/utils/converters.js.map +1 -0
  106. package/dist/src/utils/devices.d.ts +26 -0
  107. package/dist/src/utils/devices.js +53 -0
  108. package/dist/src/utils/devices.js.map +1 -0
  109. package/dist/src/utils/events.d.ts +37 -0
  110. package/dist/src/utils/events.js +88 -0
  111. package/dist/src/utils/events.js.map +1 -0
  112. package/dist/src/utils/languages.d.ts +7 -0
  113. package/dist/src/utils/languages.js +28 -0
  114. package/dist/src/utils/languages.js.map +1 -0
  115. package/dist/src/utils/media.d.ts +6 -0
  116. package/dist/src/utils/media.js +27 -0
  117. package/dist/src/utils/media.js.map +1 -0
  118. package/dist/src/utils/token.d.ts +13 -0
  119. package/dist/src/utils/token.js +59 -0
  120. package/dist/src/utils/token.js.map +1 -0
  121. package/dist/src/utils/validation.d.ts +1 -0
  122. package/dist/src/utils/validation.js +7 -0
  123. package/dist/src/utils/validation.js.map +1 -0
  124. package/dist/stories/audio-visualiser.stories.d.ts +39 -0
  125. package/dist/stories/audio-visualiser.stories.js +71 -0
  126. package/dist/stories/audio-visualiser.stories.js.map +1 -0
  127. package/dist/stories/corti-dictation.stories.d.ts +27 -0
  128. package/dist/stories/corti-dictation.stories.js +129 -0
  129. package/dist/stories/corti-dictation.stories.js.map +1 -0
  130. package/dist/stories/device-selector.stories.d.ts +18 -0
  131. package/dist/stories/device-selector.stories.js +84 -0
  132. package/dist/stories/device-selector.stories.js.map +1 -0
  133. package/dist/stories/language-selector.stories.d.ts +18 -0
  134. package/dist/stories/language-selector.stories.js +53 -0
  135. package/dist/stories/language-selector.stories.js.map +1 -0
  136. package/dist/stories/recording-button.stories.d.ts +27 -0
  137. package/dist/stories/recording-button.stories.js +90 -0
  138. package/dist/stories/recording-button.stories.js.map +1 -0
  139. package/dist/stories/settings-menu.stories.d.ts +23 -0
  140. package/dist/stories/settings-menu.stories.js +156 -0
  141. package/dist/stories/settings-menu.stories.js.map +1 -0
  142. package/dist/styles/ComponentStyles.js +6 -41
  143. package/dist/styles/ComponentStyles.js.map +1 -1
  144. package/dist/styles/audio-visualiser.d.ts +2 -0
  145. package/dist/styles/audio-visualiser.js +33 -0
  146. package/dist/styles/audio-visualiser.js.map +1 -0
  147. package/dist/styles/buttons.js +19 -25
  148. package/dist/styles/buttons.js.map +1 -1
  149. package/dist/styles/callout.js +7 -17
  150. package/dist/styles/callout.js.map +1 -1
  151. package/dist/styles/default-theme.d.ts +2 -0
  152. package/dist/styles/default-theme.js +14 -0
  153. package/dist/styles/default-theme.js.map +1 -0
  154. package/dist/styles/recording-button.d.ts +2 -0
  155. package/dist/styles/recording-button.js +8 -0
  156. package/dist/styles/recording-button.js.map +1 -0
  157. package/dist/styles/select.js +9 -9
  158. package/dist/styles/select.js.map +1 -1
  159. package/dist/styles/settings-menu.d.ts +2 -0
  160. package/dist/styles/settings-menu.js +34 -0
  161. package/dist/styles/settings-menu.js.map +1 -0
  162. package/dist/tsconfig.stories.tsbuildinfo +1 -0
  163. package/dist/types.d.ts +7 -8
  164. package/dist/types.js.map +1 -1
  165. package/dist/utils/auth.d.ts +9 -0
  166. package/dist/utils/auth.js +21 -0
  167. package/dist/utils/auth.js.map +1 -0
  168. package/dist/utils/converters.d.ts +4 -0
  169. package/dist/utils/converters.js +8 -0
  170. package/dist/utils/converters.js.map +1 -0
  171. package/dist/utils/devices.d.ts +26 -0
  172. package/dist/utils/devices.js +53 -0
  173. package/dist/utils/devices.js.map +1 -0
  174. package/dist/utils/events.d.ts +44 -0
  175. package/dist/utils/events.js +88 -0
  176. package/dist/utils/events.js.map +1 -0
  177. package/dist/utils/languages.d.ts +7 -0
  178. package/dist/utils/languages.js +29 -0
  179. package/dist/utils/languages.js.map +1 -0
  180. package/dist/utils/media.d.ts +6 -0
  181. package/dist/utils/media.js +39 -0
  182. package/dist/utils/media.js.map +1 -0
  183. package/dist/utils/token.d.ts +13 -0
  184. package/dist/utils/token.js +59 -0
  185. package/dist/utils/token.js.map +1 -0
  186. package/dist/utils/validation.d.ts +1 -0
  187. package/dist/utils/validation.js +7 -0
  188. package/dist/utils/validation.js.map +1 -0
  189. package/package.json +23 -50
@@ -0,0 +1,31 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from "lit";
2
+ interface MediaControllerHost extends ReactiveControllerHost {
3
+ _selectedDevice?: MediaDeviceInfo;
4
+ _debug_displayAudio?: boolean;
5
+ }
6
+ export declare class MediaController implements ReactiveController {
7
+ host: MediaControllerHost;
8
+ private _mediaStream;
9
+ private _audioContext;
10
+ private _analyser;
11
+ private _mediaRecorder;
12
+ private _visualiserInterval?;
13
+ private _audioLevel;
14
+ private _onTrackEnded?;
15
+ private _onAudioLevelChange?;
16
+ constructor(host: MediaControllerHost);
17
+ hostDisconnected(): void;
18
+ initialize(onTrackEnded?: () => void): Promise<void>;
19
+ getAudioLevel(): number;
20
+ startAudioLevelMonitoring(onAudioLevelChange?: (level: number) => void): void;
21
+ stopAudioLevelMonitoring(): void;
22
+ cleanup(): Promise<void>;
23
+ /**
24
+ * Stops the media recorder and waits for all buffered data to be flushed.
25
+ * This ensures the final ondataavailable event fires before resolving.
26
+ */
27
+ stopRecording(): Promise<void>;
28
+ get mediaRecorder(): MediaRecorder | null;
29
+ get audioLevel(): number;
30
+ }
31
+ export {};
@@ -0,0 +1,99 @@
1
+ import { calculateAudioLevel, createAudioAnalyzer, getMediaStream, } from "../utils/media.js";
2
+ export class MediaController {
3
+ constructor(host) {
4
+ this._mediaStream = null;
5
+ this._audioContext = null;
6
+ this._analyser = null;
7
+ this._mediaRecorder = null;
8
+ this._audioLevel = 0;
9
+ this.host = host;
10
+ host.addController(this);
11
+ }
12
+ hostDisconnected() {
13
+ this.cleanup();
14
+ }
15
+ async initialize(onTrackEnded) {
16
+ await this.cleanup();
17
+ this._onTrackEnded = onTrackEnded;
18
+ this._mediaStream = await getMediaStream(this.host._selectedDevice?.deviceId, this.host._debug_displayAudio);
19
+ this._mediaStream.getTracks().forEach((track) => {
20
+ track.addEventListener("ended", () => {
21
+ if (this._onTrackEnded) {
22
+ this._onTrackEnded();
23
+ }
24
+ });
25
+ });
26
+ const { audioContext, analyser } = createAudioAnalyzer(this._mediaStream);
27
+ this._audioContext = audioContext;
28
+ this._analyser = analyser;
29
+ this._mediaRecorder = new MediaRecorder(this._mediaStream);
30
+ }
31
+ getAudioLevel() {
32
+ return this._analyser ? calculateAudioLevel(this._analyser) : 0;
33
+ }
34
+ startAudioLevelMonitoring(onAudioLevelChange) {
35
+ this.stopAudioLevelMonitoring();
36
+ this._onAudioLevelChange = onAudioLevelChange;
37
+ this._visualiserInterval = window.setInterval(() => {
38
+ this._audioLevel = this.getAudioLevel() * 3;
39
+ this.host.requestUpdate();
40
+ if (this._onAudioLevelChange) {
41
+ this._onAudioLevelChange(this._audioLevel);
42
+ }
43
+ }, 150);
44
+ }
45
+ stopAudioLevelMonitoring() {
46
+ if (this._visualiserInterval) {
47
+ clearInterval(this._visualiserInterval);
48
+ this._visualiserInterval = undefined;
49
+ }
50
+ this._audioLevel = 0;
51
+ this.host.requestUpdate();
52
+ if (this._onAudioLevelChange) {
53
+ this._onAudioLevelChange(this._audioLevel);
54
+ }
55
+ }
56
+ async cleanup() {
57
+ this.stopAudioLevelMonitoring();
58
+ if (this._mediaRecorder?.state === "recording") {
59
+ this._mediaRecorder.stop();
60
+ }
61
+ if (this._mediaStream) {
62
+ this._mediaStream.getTracks().forEach((track) => {
63
+ track.stop();
64
+ });
65
+ this._mediaStream = null;
66
+ }
67
+ if (this._audioContext && this._audioContext.state !== "closed") {
68
+ await this._audioContext.close();
69
+ }
70
+ this._audioContext = null;
71
+ this._analyser = null;
72
+ this._mediaRecorder = null;
73
+ this._onTrackEnded = undefined;
74
+ this._onAudioLevelChange = undefined;
75
+ }
76
+ /**
77
+ * Stops the media recorder and waits for all buffered data to be flushed.
78
+ * This ensures the final ondataavailable event fires before resolving.
79
+ */
80
+ async stopRecording() {
81
+ return new Promise((resolve) => {
82
+ if (!this._mediaRecorder || this._mediaRecorder.state !== "recording") {
83
+ resolve();
84
+ return;
85
+ }
86
+ this._mediaRecorder.onstop = () => {
87
+ resolve();
88
+ };
89
+ this._mediaRecorder.stop();
90
+ });
91
+ }
92
+ get mediaRecorder() {
93
+ return this._mediaRecorder;
94
+ }
95
+ get audioLevel() {
96
+ return this._audioLevel;
97
+ }
98
+ }
99
+ //# sourceMappingURL=MediaController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediaController.js","sourceRoot":"","sources":["../../src/controllers/MediaController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from \"lit\";\nimport {\n calculateAudioLevel,\n createAudioAnalyzer,\n getMediaStream,\n} from \"../utils/media.js\";\n\ninterface MediaControllerHost extends ReactiveControllerHost {\n _selectedDevice?: MediaDeviceInfo;\n _debug_displayAudio?: boolean;\n}\n\nexport class MediaController implements ReactiveController {\n host: MediaControllerHost;\n\n private _mediaStream: MediaStream | null = null;\n private _audioContext: AudioContext | null = null;\n private _analyser: AnalyserNode | null = null;\n private _mediaRecorder: MediaRecorder | null = null;\n private _visualiserInterval?: number;\n private _audioLevel: number = 0;\n private _onTrackEnded?: () => void;\n private _onAudioLevelChange?: (level: number) => void;\n\n constructor(host: MediaControllerHost) {\n this.host = host;\n host.addController(this);\n }\n\n hostDisconnected(): void {\n this.cleanup();\n }\n\n async initialize(onTrackEnded?: () => void): Promise<void> {\n await this.cleanup();\n\n this._onTrackEnded = onTrackEnded;\n this._mediaStream = await getMediaStream(\n this.host._selectedDevice?.deviceId,\n this.host._debug_displayAudio,\n );\n\n this._mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.addEventListener(\"ended\", () => {\n if (this._onTrackEnded) {\n this._onTrackEnded();\n }\n });\n });\n\n const { audioContext, analyser } = createAudioAnalyzer(this._mediaStream);\n\n this._audioContext = audioContext;\n this._analyser = analyser;\n\n this._mediaRecorder = new MediaRecorder(this._mediaStream);\n }\n\n getAudioLevel(): number {\n return this._analyser ? calculateAudioLevel(this._analyser) : 0;\n }\n\n startAudioLevelMonitoring(\n onAudioLevelChange?: (level: number) => void,\n ): void {\n this.stopAudioLevelMonitoring();\n\n this._onAudioLevelChange = onAudioLevelChange;\n\n this._visualiserInterval = window.setInterval(() => {\n this._audioLevel = this.getAudioLevel() * 3;\n this.host.requestUpdate();\n\n if (this._onAudioLevelChange) {\n this._onAudioLevelChange(this._audioLevel);\n }\n }, 150);\n }\n\n stopAudioLevelMonitoring(): void {\n if (this._visualiserInterval) {\n clearInterval(this._visualiserInterval);\n this._visualiserInterval = undefined;\n }\n\n this._audioLevel = 0;\n this.host.requestUpdate();\n\n if (this._onAudioLevelChange) {\n this._onAudioLevelChange(this._audioLevel);\n }\n }\n\n async cleanup(): Promise<void> {\n this.stopAudioLevelMonitoring();\n\n if (this._mediaRecorder?.state === \"recording\") {\n this._mediaRecorder.stop();\n }\n\n if (this._mediaStream) {\n this._mediaStream.getTracks().forEach((track) => {\n track.stop();\n });\n this._mediaStream = null;\n }\n\n if (this._audioContext && this._audioContext.state !== \"closed\") {\n await this._audioContext.close();\n }\n\n this._audioContext = null;\n\n this._analyser = null;\n this._mediaRecorder = null;\n this._onTrackEnded = undefined;\n this._onAudioLevelChange = undefined;\n }\n\n /**\n * Stops the media recorder and waits for all buffered data to be flushed.\n * This ensures the final ondataavailable event fires before resolving.\n */\n async stopRecording(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this._mediaRecorder || this._mediaRecorder.state !== \"recording\") {\n resolve();\n return;\n }\n\n this._mediaRecorder.onstop = () => {\n resolve();\n };\n\n this._mediaRecorder.stop();\n });\n }\n\n get mediaRecorder(): MediaRecorder | null {\n return this._mediaRecorder;\n }\n\n get audioLevel(): number {\n return this._audioLevel;\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,10 @@
1
- import CortiDictation from './CortiDictation.js';
1
+ import { CortiDictation } from "./components/corti-dictation.js";
2
+ export { CortiDictation } from "./components/corti-dictation.js";
3
+ export { DeviceSelector } from "./components/device-selector.js";
4
+ export { LanguageSelector } from "./components/language-selector.js";
5
+ export { RecordingButton } from "./components/recording-button.js";
6
+ export { SettingsMenu } from "./components/settings-menu.js";
7
+ export { DictationContext } from "./contexts/dictation-context.js";
8
+ export type { ConfigurableSettings, RecordingState } from "./types.js";
9
+ export type { AudioLevelChangedEventDetail, CommandEventDetail, ErrorEventDetail, LanguageChangedEventDetail, LanguagesChangedEventDetail, NetworkActivityEventDetail, RecordingDevicesChangedEventDetail, RecordingStateChangedEventDetail, TranscriptEventDetail, UsageEventDetail, } from "./utils/events.js";
2
10
  export default CortiDictation;
package/dist/index.js CHANGED
@@ -1,6 +1,32 @@
1
- import CortiDictation from './CortiDictation.js';
2
- if (!customElements.get('corti-dictation')) {
3
- customElements.define('corti-dictation', CortiDictation);
1
+ import { CortiDictation } from "./components/corti-dictation.js";
2
+ import { DeviceSelector } from "./components/device-selector.js";
3
+ import { LanguageSelector } from "./components/language-selector.js";
4
+ import { RecordingButton } from "./components/recording-button.js";
5
+ import { SettingsMenu } from "./components/settings-menu.js";
6
+ import { DictationContext } from "./contexts/dictation-context.js";
7
+ if (!customElements.get("corti-dictation")) {
8
+ customElements.define("corti-dictation", CortiDictation);
4
9
  }
10
+ if (!customElements.get("recording-button")) {
11
+ customElements.define("recording-button", RecordingButton);
12
+ }
13
+ if (!customElements.get("device-selector")) {
14
+ customElements.define("device-selector", DeviceSelector);
15
+ }
16
+ if (!customElements.get("language-selector")) {
17
+ customElements.define("language-selector", LanguageSelector);
18
+ }
19
+ if (!customElements.get("settings-menu")) {
20
+ customElements.define("settings-menu", SettingsMenu);
21
+ }
22
+ if (!customElements.get("dictation-context-provider")) {
23
+ customElements.define("dictation-context-provider", DictationContext);
24
+ }
25
+ export { CortiDictation } from "./components/corti-dictation.js";
26
+ export { DeviceSelector } from "./components/device-selector.js";
27
+ export { LanguageSelector } from "./components/language-selector.js";
28
+ export { RecordingButton } from "./components/recording-button.js";
29
+ export { SettingsMenu } from "./components/settings-menu.js";
30
+ export { DictationContext } from "./contexts/dictation-context.js";
5
31
  export default CortiDictation;
6
32
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAC3C,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,eAAe,cAAc,CAAC","sourcesContent":["import CortiDictation from './CortiDictation.js';\n\nif (!customElements.get('corti-dictation')) {\n customElements.define('corti-dictation', CortiDictation);\n}\n\nexport default CortiDictation;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAC3C,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;IAC5C,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAC7D,CAAC;AAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAC3C,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;IAC7C,cAAc,CAAC,MAAM,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;IACzC,cAAc,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,4BAA4B,CAAC,EAAE,CAAC;IACtD,cAAc,CAAC,MAAM,CAAC,4BAA4B,EAAE,gBAAgB,CAAC,CAAC;AACxE,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAgBnE,eAAe,cAAc,CAAC","sourcesContent":["import { CortiDictation } from \"./components/corti-dictation.js\";\nimport { DeviceSelector } from \"./components/device-selector.js\";\nimport { LanguageSelector } from \"./components/language-selector.js\";\nimport { RecordingButton } from \"./components/recording-button.js\";\nimport { SettingsMenu } from \"./components/settings-menu.js\";\nimport { DictationContext } from \"./contexts/dictation-context.js\";\n\nif (!customElements.get(\"corti-dictation\")) {\n customElements.define(\"corti-dictation\", CortiDictation);\n}\n\nif (!customElements.get(\"recording-button\")) {\n customElements.define(\"recording-button\", RecordingButton);\n}\n\nif (!customElements.get(\"device-selector\")) {\n customElements.define(\"device-selector\", DeviceSelector);\n}\n\nif (!customElements.get(\"language-selector\")) {\n customElements.define(\"language-selector\", LanguageSelector);\n}\n\nif (!customElements.get(\"settings-menu\")) {\n customElements.define(\"settings-menu\", SettingsMenu);\n}\n\nif (!customElements.get(\"dictation-context-provider\")) {\n customElements.define(\"dictation-context-provider\", DictationContext);\n}\n\nexport { CortiDictation } from \"./components/corti-dictation.js\";\nexport { DeviceSelector } from \"./components/device-selector.js\";\nexport { LanguageSelector } from \"./components/language-selector.js\";\nexport { RecordingButton } from \"./components/recording-button.js\";\nexport { SettingsMenu } from \"./components/settings-menu.js\";\nexport { DictationContext } from \"./contexts/dictation-context.js\";\n\nexport type { ConfigurableSettings, RecordingState } from \"./types.js\";\nexport type {\n AudioLevelChangedEventDetail,\n CommandEventDetail,\n ErrorEventDetail,\n LanguageChangedEventDetail,\n LanguagesChangedEventDetail,\n NetworkActivityEventDetail,\n RecordingDevicesChangedEventDetail,\n RecordingStateChangedEventDetail,\n TranscriptEventDetail,\n UsageEventDetail,\n} from \"./utils/events.js\";\n\nexport default CortiDictation;\n"]}
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@corti/dictation-web",
3
+ "version": "0.0.0-local",
4
+ "type": "module",
5
+ "main": "./index.js",
6
+ "module": "./index.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./index.js",
10
+ "types": "./index.d.ts"
11
+ },
12
+ "./*": "./*"
13
+ }
14
+ }
@@ -0,0 +1,13 @@
1
+ import { LitElement, type PropertyValues } from "lit";
2
+ export declare class AudioVisualiser extends LitElement {
3
+ level: number;
4
+ active: boolean;
5
+ static styles: import("lit").CSSResult;
6
+ willUpdate(changedProperties: PropertyValues<this>): void;
7
+ render(): import("lit-html").TemplateResult<1>;
8
+ }
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ "audio-visualiser": AudioVisualiser;
12
+ }
13
+ }
@@ -0,0 +1,54 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, LitElement } from "lit";
8
+ import { customElement, property } from "lit/decorators.js";
9
+ import { classMap } from "lit/directives/class-map.js";
10
+ import { map } from "lit/directives/map.js";
11
+ import { range } from "lit/directives/range.js";
12
+ import AudioVisualiserStyles from "../styles/audio-visualiser.js";
13
+ import { normalizeToRange } from "../utils/validation.js";
14
+ const SEGMENT_COUNT = 5;
15
+ let AudioVisualiser = class AudioVisualiser extends LitElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.level = 0;
19
+ this.active = false;
20
+ }
21
+ willUpdate(changedProperties) {
22
+ if (changedProperties.has("level")) {
23
+ this.level = normalizeToRange(this.level);
24
+ }
25
+ }
26
+ render() {
27
+ // Each segment represents 20%. Using Math.round to fill segments.
28
+ const activeSegments = Math.round(this.level * SEGMENT_COUNT);
29
+ const segments = map(range(SEGMENT_COUNT), (i) => html `<div class=${classMap({
30
+ active: i < activeSegments,
31
+ segment: true,
32
+ })}></div>`);
33
+ return html `
34
+ <div class=${classMap({
35
+ active: this.active,
36
+ container: true,
37
+ })}>
38
+ ${segments}
39
+ </div>
40
+ `;
41
+ }
42
+ };
43
+ AudioVisualiser.styles = AudioVisualiserStyles;
44
+ __decorate([
45
+ property({ type: Number })
46
+ ], AudioVisualiser.prototype, "level", void 0);
47
+ __decorate([
48
+ property({ type: Boolean })
49
+ ], AudioVisualiser.prototype, "active", void 0);
50
+ AudioVisualiser = __decorate([
51
+ customElement("audio-visualiser")
52
+ ], AudioVisualiser);
53
+ export { AudioVisualiser };
54
+ //# sourceMappingURL=audio-visualiser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-visualiser.js","sourceRoot":"","sources":["../../../src/components/audio-visualiser.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAuB,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,qBAAqB,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,aAAa,GAAG,CAAC,CAAC;AAGjB,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,UAAU;IAAxC;;QAEL,UAAK,GAAW,CAAC,CAAC;QAGlB,WAAM,GAAY,KAAK,CAAC;IA+B1B,CAAC;IA3BC,UAAU,CAAC,iBAAuC;QAChD,IAAI,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM;QACJ,kEAAkE;QAClE,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,GAAG,CAClB,KAAK,CAAC,aAAa,CAAC,EACpB,CAAC,CAAC,EAAE,EAAE,CACJ,IAAI,CAAA,cAAc,QAAQ,CAAC;YACzB,MAAM,EAAE,CAAC,GAAG,cAAc;YAC1B,OAAO,EAAE,IAAI;SACd,CAAC,SAAS,CACd,CAAC;QAEF,OAAO,IAAI,CAAA;mBACI,QAAQ,CAAC;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI;SAChB,CAAC;UACE,QAAQ;;KAEb,CAAC;IACJ,CAAC;;AA5BM,sBAAM,GAAG,qBAAqB,AAAxB,CAAyB;AALtC;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CACT;AAGlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;+CACJ;AALb,eAAe;IAD3B,aAAa,CAAC,kBAAkB,CAAC;GACrB,eAAe,CAoC3B","sourcesContent":["import { html, LitElement, type PropertyValues } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { map } from \"lit/directives/map.js\";\nimport { range } from \"lit/directives/range.js\";\nimport AudioVisualiserStyles from \"../styles/audio-visualiser.js\";\nimport { normalizeToRange } from \"../utils/validation.js\";\n\nconst SEGMENT_COUNT = 5;\n\n@customElement(\"audio-visualiser\")\nexport class AudioVisualiser extends LitElement {\n @property({ type: Number })\n level: number = 0;\n\n @property({ type: Boolean })\n active: boolean = false;\n\n static styles = AudioVisualiserStyles;\n\n willUpdate(changedProperties: PropertyValues<this>): void {\n if (changedProperties.has(\"level\")) {\n this.level = normalizeToRange(this.level);\n }\n }\n\n render() {\n // Each segment represents 20%. Using Math.round to fill segments.\n const activeSegments = Math.round(this.level * SEGMENT_COUNT);\n const segments = map(\n range(SEGMENT_COUNT),\n (i) =>\n html`<div class=${classMap({\n active: i < activeSegments,\n segment: true,\n })}></div>`,\n );\n\n return html`\n <div class=${classMap({\n active: this.active,\n container: true,\n })}>\n ${segments}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"audio-visualiser\": AudioVisualiser;\n }\n}\n"]}
@@ -0,0 +1,108 @@
1
+ import type { Corti } from "@corti/sdk";
2
+ import { LitElement } from "lit";
3
+ import type { ConfigurableSettings, RecordingState } from "../types.js";
4
+ import "../contexts/dictation-context.js";
5
+ import "./recording-button.js";
6
+ import "./settings-menu.js";
7
+ export declare class CortiDictation extends LitElement {
8
+ static styles: import("lit").CSSResult;
9
+ private recordingButtonRef;
10
+ private contextProviderRef;
11
+ /**
12
+ * Latest access token
13
+ */
14
+ accessToken?: string;
15
+ /**
16
+ * Authentication configuration with optional refresh mechanism.
17
+ */
18
+ authConfig?: Corti.BearerOptions;
19
+ /**
20
+ * List of all language codes available for use with the Web Component.
21
+ * Default list depends on the accessToken
22
+ */
23
+ set languagesSupported(value: string[] | undefined);
24
+ get languagesSupported(): string[] | undefined;
25
+ private _languagesSupported?;
26
+ /**
27
+ * Which settings should be available in the UI.
28
+ * If an empty array is passed, the settings will be disabled entirely.
29
+ * Options are language and devices
30
+ */
31
+ settingsEnabled: ConfigurableSettings[];
32
+ /**
33
+ * When false (default), allows the start/stop button from taking focus when clicked,
34
+ * disabling textareas or other input elements to maintain focus.
35
+ * Set to "true" to allow the button to receive focus on click.
36
+ */
37
+ allowButtonFocus: boolean;
38
+ /**
39
+ * Configuration settings for dictation
40
+ */
41
+ set dictationConfig(value: Corti.TranscribeConfig);
42
+ get dictationConfig(): Corti.TranscribeConfig;
43
+ private _dictationConfig;
44
+ /**
45
+ * List of available recording devices
46
+ */
47
+ set devices(value: MediaDeviceInfo[] | undefined);
48
+ get devices(): MediaDeviceInfo[];
49
+ private _devices?;
50
+ /**
51
+ * The selected device used for recording (MediaDeviceInfo).
52
+ */
53
+ set selectedDevice(value: MediaDeviceInfo | undefined);
54
+ get selectedDevice(): MediaDeviceInfo | undefined;
55
+ private _selectedDevice?;
56
+ /**
57
+ * Current state of recording (stopped, recording, initializing and stopping, ).
58
+ */
59
+ get recordingState(): RecordingState;
60
+ /**
61
+ * Set the latest access token.
62
+ * @returns ServerConfig with environment, tenant, and accessToken
63
+ */
64
+ setAccessToken(token: string): {
65
+ accessToken: string | undefined;
66
+ environment: undefined;
67
+ tenant: undefined;
68
+ } | {
69
+ accessToken: string;
70
+ environment: string | undefined;
71
+ tenant: string | undefined;
72
+ };
73
+ /**
74
+ * Set the auth configuration for OAuth flows.
75
+ * @returns Promise with ServerConfig containing environment, tenant, and accessToken
76
+ */
77
+ setAuthConfig(config: Corti.BearerOptions): Promise<{
78
+ accessToken: string | undefined;
79
+ environment: undefined;
80
+ tenant: undefined;
81
+ } | {
82
+ accessToken: string;
83
+ environment: string | undefined;
84
+ tenant: string | undefined;
85
+ } | {
86
+ accessToken: undefined;
87
+ environment: undefined;
88
+ tenant: undefined;
89
+ }>;
90
+ /**
91
+ * Starts a recording.
92
+ */
93
+ startRecording(): void;
94
+ /**
95
+ * Stops a recording.
96
+ */
97
+ stopRecording(): void;
98
+ /**
99
+ * Starts or stops recording. Convenience layer on top of the start/stop methods.
100
+ */
101
+ toggleRecording(): void;
102
+ render(): import("lit-html").TemplateResult<1>;
103
+ }
104
+ declare global {
105
+ interface HTMLElementTagNameMap {
106
+ "corti-dictation": CortiDictation;
107
+ }
108
+ }
@@ -0,0 +1,201 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { css, html, LitElement } from "lit";
8
+ import { customElement, property, state } from "lit/decorators.js";
9
+ import { classMap } from "lit/directives/class-map.js";
10
+ import { createRef, ref } from "lit/directives/ref.js";
11
+ import { DEFAULT_DICTATION_CONFIG } from "../constants.js";
12
+ import { commaSeparatedConverter } from "../utils/converters.js";
13
+ import "../contexts/dictation-context.js";
14
+ import "./recording-button.js";
15
+ import "./settings-menu.js";
16
+ let CortiDictation = class CortiDictation extends LitElement {
17
+ constructor() {
18
+ super(...arguments);
19
+ // ─────────────────────────────────────────────────────────────────────────────
20
+ // Private refs
21
+ // ─────────────────────────────────────────────────────────────────────────────
22
+ this.recordingButtonRef = createRef();
23
+ this.contextProviderRef = createRef();
24
+ /**
25
+ * Which settings should be available in the UI.
26
+ * If an empty array is passed, the settings will be disabled entirely.
27
+ * Options are language and devices
28
+ */
29
+ this.settingsEnabled = ["device", "language"];
30
+ /**
31
+ * When false (default), allows the start/stop button from taking focus when clicked,
32
+ * disabling textareas or other input elements to maintain focus.
33
+ * Set to "true" to allow the button to receive focus on click.
34
+ */
35
+ this.allowButtonFocus = false;
36
+ this._dictationConfig = DEFAULT_DICTATION_CONFIG;
37
+ }
38
+ /**
39
+ * List of all language codes available for use with the Web Component.
40
+ * Default list depends on the accessToken
41
+ */
42
+ set languagesSupported(value) {
43
+ this._languagesSupported = value;
44
+ }
45
+ get languagesSupported() {
46
+ return this.contextProviderRef.value?.languages || this._languagesSupported;
47
+ }
48
+ /**
49
+ * Configuration settings for dictation
50
+ */
51
+ set dictationConfig(value) {
52
+ this._dictationConfig = value;
53
+ }
54
+ get dictationConfig() {
55
+ return (this.contextProviderRef.value?.dictationConfig || this._dictationConfig);
56
+ }
57
+ /**
58
+ * List of available recording devices
59
+ */
60
+ set devices(value) {
61
+ this._devices = value;
62
+ }
63
+ get devices() {
64
+ return this.contextProviderRef.value?.devices || this._devices || [];
65
+ }
66
+ /**
67
+ * The selected device used for recording (MediaDeviceInfo).
68
+ */
69
+ set selectedDevice(value) {
70
+ this._selectedDevice = value;
71
+ }
72
+ get selectedDevice() {
73
+ return (this.contextProviderRef.value?.selectedDevice || this._selectedDevice);
74
+ }
75
+ /**
76
+ * Current state of recording (stopped, recording, initializing and stopping, ).
77
+ */
78
+ get recordingState() {
79
+ return this.contextProviderRef.value?.recordingState || "stopped";
80
+ }
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+ // Public methods
83
+ // ─────────────────────────────────────────────────────────────────────────────
84
+ /**
85
+ * Set the latest access token.
86
+ * @returns ServerConfig with environment, tenant, and accessToken
87
+ */
88
+ setAccessToken(token) {
89
+ this.accessToken = token;
90
+ return (this.contextProviderRef.value?.setAccessToken(token) ?? {
91
+ accessToken: token,
92
+ environment: undefined,
93
+ tenant: undefined,
94
+ });
95
+ }
96
+ /**
97
+ * Set the auth configuration for OAuth flows.
98
+ * @returns Promise with ServerConfig containing environment, tenant, and accessToken
99
+ */
100
+ async setAuthConfig(config) {
101
+ this.authConfig = config;
102
+ return (this.contextProviderRef.value?.setAuthConfig(config) ?? {
103
+ accessToken: undefined,
104
+ environment: undefined,
105
+ tenant: undefined,
106
+ });
107
+ }
108
+ /**
109
+ * Starts a recording.
110
+ */
111
+ startRecording() {
112
+ this.recordingButtonRef.value?.startRecording();
113
+ }
114
+ /**
115
+ * Stops a recording.
116
+ */
117
+ stopRecording() {
118
+ this.recordingButtonRef.value?.stopRecording();
119
+ }
120
+ /**
121
+ * Starts or stops recording. Convenience layer on top of the start/stop methods.
122
+ */
123
+ toggleRecording() {
124
+ this.recordingButtonRef.value?.toggleRecording();
125
+ }
126
+ // ─────────────────────────────────────────────────────────────────────────────
127
+ // Render
128
+ // ─────────────────────────────────────────────────────────────────────────────
129
+ render() {
130
+ return html `
131
+ <dictation-context-provider
132
+ ${ref(this.contextProviderRef)}
133
+ class=${classMap({ hidden: !this.accessToken && !this.authConfig })}
134
+ .accessToken=${this.accessToken}
135
+ .authConfig=${this.authConfig}
136
+ .dictationConfig=${this._dictationConfig}
137
+ .languages=${this._languagesSupported}
138
+ .devices=${this._devices}
139
+ .selectedDevice=${this._selectedDevice}
140
+ >
141
+ <recording-button
142
+ ${ref(this.recordingButtonRef)}
143
+ .preventFocus=${!this.allowButtonFocus}
144
+ ></recording-button>
145
+ <settings-menu .settingsEnabled=${this.settingsEnabled}></settings-menu>
146
+ </dictation-context-provider>
147
+ `;
148
+ }
149
+ };
150
+ CortiDictation.styles = css `
151
+ .hidden {
152
+ display: none;
153
+ }
154
+ `;
155
+ __decorate([
156
+ property({ type: String })
157
+ ], CortiDictation.prototype, "accessToken", void 0);
158
+ __decorate([
159
+ property({ attribute: false, type: Object })
160
+ ], CortiDictation.prototype, "authConfig", void 0);
161
+ __decorate([
162
+ property({
163
+ converter: commaSeparatedConverter,
164
+ type: Array,
165
+ })
166
+ ], CortiDictation.prototype, "languagesSupported", null);
167
+ __decorate([
168
+ state()
169
+ ], CortiDictation.prototype, "_languagesSupported", void 0);
170
+ __decorate([
171
+ property({
172
+ converter: commaSeparatedConverter,
173
+ type: Array,
174
+ })
175
+ ], CortiDictation.prototype, "settingsEnabled", void 0);
176
+ __decorate([
177
+ property({ type: Boolean })
178
+ ], CortiDictation.prototype, "allowButtonFocus", void 0);
179
+ __decorate([
180
+ property({ attribute: false, type: Object })
181
+ ], CortiDictation.prototype, "dictationConfig", null);
182
+ __decorate([
183
+ state()
184
+ ], CortiDictation.prototype, "_dictationConfig", void 0);
185
+ __decorate([
186
+ property({ attribute: false, type: Array })
187
+ ], CortiDictation.prototype, "devices", null);
188
+ __decorate([
189
+ state()
190
+ ], CortiDictation.prototype, "_devices", void 0);
191
+ __decorate([
192
+ property({ attribute: false, type: Object })
193
+ ], CortiDictation.prototype, "selectedDevice", null);
194
+ __decorate([
195
+ state()
196
+ ], CortiDictation.prototype, "_selectedDevice", void 0);
197
+ CortiDictation = __decorate([
198
+ customElement("corti-dictation")
199
+ ], CortiDictation);
200
+ export { CortiDictation };
201
+ //# sourceMappingURL=corti-dictation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"corti-dictation.js","sourceRoot":"","sources":["../../../src/components/corti-dictation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Corti } from \"@corti/sdk\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { classMap } from \"lit/directives/class-map.js\";\nimport { createRef, type Ref, ref } from \"lit/directives/ref.js\";\nimport { DEFAULT_DICTATION_CONFIG } from \"../constants.js\";\nimport type { DictationContext } from \"../contexts/dictation-context.js\";\nimport type { ConfigurableSettings, RecordingState } from \"../types.js\";\nimport { commaSeparatedConverter } from \"../utils/converters.js\";\nimport type { RecordingButton } from \"./recording-button.js\";\n\nimport \"../contexts/dictation-context.js\";\nimport \"./recording-button.js\";\nimport \"./settings-menu.js\";\n\n@customElement(\"corti-dictation\")\nexport class CortiDictation extends LitElement {\n static styles = css`\n .hidden {\n display: none;\n }\n `;\n // ─────────────────────────────────────────────────────────────────────────────\n // Private refs\n // ─────────────────────────────────────────────────────────────────────────────\n\n private recordingButtonRef: Ref<RecordingButton> = createRef();\n private contextProviderRef: Ref<DictationContext> = createRef();\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Properties\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Latest access token\n */\n @property({ type: String })\n accessToken?: string;\n\n /**\n * Authentication configuration with optional refresh mechanism.\n */\n @property({ attribute: false, type: Object })\n authConfig?: Corti.BearerOptions;\n\n /**\n * List of all language codes available for use with the Web Component.\n * Default list depends on the accessToken\n */\n @property({\n converter: commaSeparatedConverter,\n type: Array,\n })\n set languagesSupported(value: string[] | undefined) {\n this._languagesSupported = value;\n }\n\n get languagesSupported(): string[] | undefined {\n return this.contextProviderRef.value?.languages || this._languagesSupported;\n }\n\n @state()\n private _languagesSupported?: string[];\n\n /**\n * Which settings should be available in the UI.\n * If an empty array is passed, the settings will be disabled entirely.\n * Options are language and devices\n */\n @property({\n converter: commaSeparatedConverter,\n type: Array,\n })\n settingsEnabled: ConfigurableSettings[] = [\"device\", \"language\"];\n\n /**\n * When false (default), allows the start/stop button from taking focus when clicked,\n * disabling textareas or other input elements to maintain focus.\n * Set to \"true\" to allow the button to receive focus on click.\n */\n @property({ type: Boolean })\n allowButtonFocus: boolean = false;\n\n /**\n * Configuration settings for dictation\n */\n @property({ attribute: false, type: Object })\n set dictationConfig(value: Corti.TranscribeConfig) {\n this._dictationConfig = value;\n }\n\n get dictationConfig(): Corti.TranscribeConfig {\n return (\n this.contextProviderRef.value?.dictationConfig || this._dictationConfig\n );\n }\n\n @state()\n private _dictationConfig: Corti.TranscribeConfig = DEFAULT_DICTATION_CONFIG;\n\n /**\n * List of available recording devices\n */\n @property({ attribute: false, type: Array })\n set devices(value: MediaDeviceInfo[] | undefined) {\n this._devices = value;\n }\n\n get devices(): MediaDeviceInfo[] {\n return this.contextProviderRef.value?.devices || this._devices || [];\n }\n\n @state()\n private _devices?: MediaDeviceInfo[];\n\n /**\n * The selected device used for recording (MediaDeviceInfo).\n */\n @property({ attribute: false, type: Object })\n set selectedDevice(value: MediaDeviceInfo | undefined) {\n this._selectedDevice = value;\n }\n\n get selectedDevice(): MediaDeviceInfo | undefined {\n return (\n this.contextProviderRef.value?.selectedDevice || this._selectedDevice\n );\n }\n\n @state()\n private _selectedDevice?: MediaDeviceInfo;\n\n /**\n * Current state of recording (stopped, recording, initializing and stopping, ).\n */\n get recordingState(): RecordingState {\n return this.contextProviderRef.value?.recordingState || \"stopped\";\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Public methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Set the latest access token.\n * @returns ServerConfig with environment, tenant, and accessToken\n */\n public setAccessToken(token: string) {\n this.accessToken = token;\n\n return (\n this.contextProviderRef.value?.setAccessToken(token) ?? {\n accessToken: token,\n environment: undefined,\n tenant: undefined,\n }\n );\n }\n\n /**\n * Set the auth configuration for OAuth flows.\n * @returns Promise with ServerConfig containing environment, tenant, and accessToken\n */\n public async setAuthConfig(config: Corti.BearerOptions) {\n this.authConfig = config;\n\n return (\n this.contextProviderRef.value?.setAuthConfig(config) ?? {\n accessToken: undefined,\n environment: undefined,\n tenant: undefined,\n }\n );\n }\n\n /**\n * Starts a recording.\n */\n public startRecording(): void {\n this.recordingButtonRef.value?.startRecording();\n }\n\n /**\n * Stops a recording.\n */\n public stopRecording(): void {\n this.recordingButtonRef.value?.stopRecording();\n }\n\n /**\n * Starts or stops recording. Convenience layer on top of the start/stop methods.\n */\n public toggleRecording(): void {\n this.recordingButtonRef.value?.toggleRecording();\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Render\n // ─────────────────────────────────────────────────────────────────────────────\n\n render() {\n return html`\n <dictation-context-provider\n ${ref(this.contextProviderRef)}\n class=${classMap({ hidden: !this.accessToken && !this.authConfig })}\n .accessToken=${this.accessToken}\n .authConfig=${this.authConfig}\n .dictationConfig=${this._dictationConfig}\n .languages=${this._languagesSupported}\n .devices=${this._devices}\n .selectedDevice=${this._selectedDevice}\n >\n <recording-button\n ${ref(this.recordingButtonRef)}\n .preventFocus=${!this.allowButtonFocus}\n ></recording-button>\n <settings-menu .settingsEnabled=${this.settingsEnabled}></settings-menu>\n </dictation-context-provider>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"corti-dictation\": CortiDictation;\n }\n}\n"]}