@corti/dictation-web 0.0.1 → 0.0.2

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 (139) hide show
  1. package/dist/{src/index.js → CortiDictation.js} +1 -1
  2. package/dist/CortiDictation.js.map +1 -0
  3. package/dist/{src/DictationService.js → DictationService.js} +1 -1
  4. package/dist/DictationService.js.map +1 -0
  5. package/dist/RecorderManager.js.map +1 -0
  6. package/dist/audioService.js.map +1 -0
  7. package/dist/components/audio-visualiser.js.map +1 -0
  8. package/dist/components/settings-menu.js.map +1 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/icons/icons.js.map +1 -0
  11. package/dist/icons/index.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +6 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/styles/ComponentStyles.js.map +1 -0
  16. package/dist/styles/buttons.js.map +1 -0
  17. package/dist/styles/callout.js.map +1 -0
  18. package/dist/styles/select.js.map +1 -0
  19. package/dist/styles/theme.js.map +1 -0
  20. package/dist/types.js.map +1 -0
  21. package/dist/utils.js.map +1 -0
  22. package/package.json +6 -6
  23. package/.editorconfig +0 -29
  24. package/.eslintrc.json +0 -16
  25. package/.husky/pre-commit +0 -1
  26. package/.storybook/main.js +0 -8
  27. package/demo/index.html +0 -98
  28. package/dist/src/CortiDictation.d.ts +0 -19
  29. package/dist/src/CortiDictation.js +0 -137
  30. package/dist/src/CortiDictation.js.map +0 -1
  31. package/dist/src/DictationService.js.map +0 -1
  32. package/dist/src/RecorderManager.js.map +0 -1
  33. package/dist/src/audioRecorderManager.d.ts +0 -17
  34. package/dist/src/audioRecorderManager.js +0 -78
  35. package/dist/src/audioRecorderManager.js.map +0 -1
  36. package/dist/src/audioService.js.map +0 -1
  37. package/dist/src/componentStyles.d.ts +0 -1
  38. package/dist/src/componentStyles.js +0 -51
  39. package/dist/src/componentStyles.js.map +0 -1
  40. package/dist/src/components/audio-visualiser.js.map +0 -1
  41. package/dist/src/components/settings-menu.js.map +0 -1
  42. package/dist/src/components/visualiser.d.ts +0 -7
  43. package/dist/src/components/visualiser.js +0 -62
  44. package/dist/src/components/visualiser.js.map +0 -1
  45. package/dist/src/constants.js.map +0 -1
  46. package/dist/src/corti-dictation.d.ts +0 -1
  47. package/dist/src/corti-dictation.js +0 -3
  48. package/dist/src/corti-dictation.js.map +0 -1
  49. package/dist/src/dictationService.d.ts +0 -13
  50. package/dist/src/dictationService.js +0 -70
  51. package/dist/src/dictationService.js.map +0 -1
  52. package/dist/src/icons/icons.js.map +0 -1
  53. package/dist/src/icons/index.js.map +0 -1
  54. package/dist/src/icons/micOn.d.ts +0 -7
  55. package/dist/src/icons/micOn.js +0 -25
  56. package/dist/src/icons/micOn.js.map +0 -1
  57. package/dist/src/index.js.map +0 -1
  58. package/dist/src/mediaRecorderService.d.ts +0 -6
  59. package/dist/src/mediaRecorderService.js +0 -31
  60. package/dist/src/mediaRecorderService.js.map +0 -1
  61. package/dist/src/mic-selector.d.ts +0 -18
  62. package/dist/src/mic-selector.js +0 -131
  63. package/dist/src/mic-selector.js.map +0 -1
  64. package/dist/src/settings-menu.d.ts +0 -18
  65. package/dist/src/settings-menu.js +0 -131
  66. package/dist/src/settings-menu.js.map +0 -1
  67. package/dist/src/settings-popover.d.ts +0 -18
  68. package/dist/src/settings-popover.js +0 -131
  69. package/dist/src/settings-popover.js.map +0 -1
  70. package/dist/src/settings.d.ts +0 -18
  71. package/dist/src/settings.js +0 -131
  72. package/dist/src/settings.js.map +0 -1
  73. package/dist/src/styles/ComponentStyles.js.map +0 -1
  74. package/dist/src/styles/buttons.js.map +0 -1
  75. package/dist/src/styles/callout.js.map +0 -1
  76. package/dist/src/styles/select.js.map +0 -1
  77. package/dist/src/styles/theme.js.map +0 -1
  78. package/dist/src/types.js.map +0 -1
  79. package/dist/src/utils.js.map +0 -1
  80. package/dist/stories/index.stories.d.ts +0 -33
  81. package/dist/stories/index.stories.js +0 -37
  82. package/dist/stories/index.stories.js.map +0 -1
  83. package/dist/test/corti-dictation.test.d.ts +0 -1
  84. package/dist/test/corti-dictation.test.js +0 -100
  85. package/dist/test/corti-dictation.test.js.map +0 -1
  86. package/dist/tsconfig.tsbuildinfo +0 -1
  87. package/docs/DEV_README.md +0 -80
  88. package/src/DictationService.ts +0 -99
  89. package/src/RecorderManager.ts +0 -114
  90. package/src/audioService.ts +0 -25
  91. package/src/components/audio-visualiser.ts +0 -56
  92. package/src/components/settings-menu.ts +0 -152
  93. package/src/constants.ts +0 -10
  94. package/src/corti-dictation.ts +0 -3
  95. package/src/icons/icons.ts +0 -141
  96. package/src/icons/index.ts +0 -0
  97. package/src/index.ts +0 -154
  98. package/src/styles/ComponentStyles.ts +0 -53
  99. package/src/styles/buttons.ts +0 -59
  100. package/src/styles/callout.ts +0 -27
  101. package/src/styles/select.ts +0 -37
  102. package/src/styles/theme.ts +0 -75
  103. package/src/types.ts +0 -28
  104. package/src/utils.ts +0 -83
  105. package/stories/index.stories.ts +0 -60
  106. package/test/corti-dictation.test.ts +0 -124
  107. package/tsconfig.json +0 -22
  108. package/web-dev-server.config.js +0 -27
  109. package/web-test-runner.config.js +0 -41
  110. /package/dist/{src/index.d.ts → CortiDictation.d.ts} +0 -0
  111. /package/dist/{src/DictationService.d.ts → DictationService.d.ts} +0 -0
  112. /package/dist/{src/RecorderManager.d.ts → RecorderManager.d.ts} +0 -0
  113. /package/dist/{src/RecorderManager.js → RecorderManager.js} +0 -0
  114. /package/dist/{src/audioService.d.ts → audioService.d.ts} +0 -0
  115. /package/dist/{src/audioService.js → audioService.js} +0 -0
  116. /package/dist/{src/components → components}/audio-visualiser.d.ts +0 -0
  117. /package/dist/{src/components → components}/audio-visualiser.js +0 -0
  118. /package/dist/{src/components → components}/settings-menu.d.ts +0 -0
  119. /package/dist/{src/components → components}/settings-menu.js +0 -0
  120. /package/dist/{src/constants.d.ts → constants.d.ts} +0 -0
  121. /package/dist/{src/constants.js → constants.js} +0 -0
  122. /package/dist/{src/icons → icons}/icons.d.ts +0 -0
  123. /package/dist/{src/icons → icons}/icons.js +0 -0
  124. /package/dist/{src/icons → icons}/index.d.ts +0 -0
  125. /package/dist/{src/icons → icons}/index.js +0 -0
  126. /package/dist/{src/styles → styles}/ComponentStyles.d.ts +0 -0
  127. /package/dist/{src/styles → styles}/ComponentStyles.js +0 -0
  128. /package/dist/{src/styles → styles}/buttons.d.ts +0 -0
  129. /package/dist/{src/styles → styles}/buttons.js +0 -0
  130. /package/dist/{src/styles → styles}/callout.d.ts +0 -0
  131. /package/dist/{src/styles → styles}/callout.js +0 -0
  132. /package/dist/{src/styles → styles}/select.d.ts +0 -0
  133. /package/dist/{src/styles → styles}/select.js +0 -0
  134. /package/dist/{src/styles → styles}/theme.d.ts +0 -0
  135. /package/dist/{src/styles → styles}/theme.js +0 -0
  136. /package/dist/{src/types.d.ts → types.d.ts} +0 -0
  137. /package/dist/{src/types.js → types.js} +0 -0
  138. /package/dist/{src/utils.d.ts → utils.d.ts} +0 -0
  139. /package/dist/{src/utils.js → utils.js} +0 -0
@@ -1,114 +0,0 @@
1
- import { getAudioDevices } from './utils';
2
- import { AudioService } from './audioService';
3
- import { DictationService } from './DictationService';
4
- import type { DictationConfig, RecordingState, ServerConfig } from './types';
5
-
6
- export class RecorderManager extends EventTarget {
7
- public devices: MediaDeviceInfo[] = [];
8
-
9
- public selectedDevice: string = '';
10
-
11
- public recordingState: RecordingState = 'stopped';
12
-
13
- private _mediaStream: MediaStream | null = null;
14
-
15
- private _audioService: AudioService | null = null;
16
-
17
- private _dictationService: DictationService | null = null;
18
-
19
- private _visualiserInterval?: number;
20
-
21
- async initialize() {
22
- const deviceResponse = await getAudioDevices();
23
- this.devices = deviceResponse.devices;
24
- this.selectedDevice = deviceResponse.defaultDeviceId || '';
25
- return deviceResponse;
26
- }
27
-
28
- async startRecording(params: {
29
- dictationConfig: DictationConfig;
30
- serverConfig: ServerConfig;
31
- }) {
32
- this._updateRecordingState('initializing');
33
- try {
34
- this._mediaStream = await navigator.mediaDevices.getUserMedia({
35
- audio: { deviceId: this.selectedDevice },
36
- });
37
- this._audioService = new AudioService(this._mediaStream);
38
- this._dictationService = new DictationService(this._mediaStream, params);
39
-
40
- // Forward custom events from dictation service
41
- this._dictationService.addEventListener('error', e =>
42
- this.dispatchEvent(
43
- new CustomEvent('error', {
44
- detail: (e as CustomEvent).detail,
45
- bubbles: true,
46
- composed: true,
47
- }),
48
- ),
49
- );
50
- this._dictationService.addEventListener('stream-closed', () =>
51
- this.stopRecording(),
52
- );
53
- this._dictationService.addEventListener('transcript', e =>
54
- this.dispatchEvent(
55
- new CustomEvent('transcript', {
56
- detail: (e as CustomEvent).detail,
57
- bubbles: true,
58
- composed: true,
59
- }),
60
- ),
61
- );
62
- } catch (error) {
63
- this.dispatchEvent(
64
- new CustomEvent('error', {
65
- detail: error,
66
- bubbles: true,
67
- composed: true,
68
- }),
69
- );
70
- this._updateRecordingState('stopped');
71
- return;
72
- }
73
-
74
- this._dictationService?.startRecording();
75
- this._updateRecordingState('recording');
76
- this._visualiserInterval = window.setInterval(() => {
77
- const level = this._audioService
78
- ? this._audioService.getAudioLevel() * 3
79
- : 0;
80
- this.dispatchEvent(
81
- new CustomEvent('audio-level-changed', {
82
- detail: { audioLevel: level },
83
- bubbles: true,
84
- composed: true,
85
- }),
86
- );
87
- }, 150);
88
- }
89
-
90
- async stopRecording() {
91
- this._updateRecordingState('stopping');
92
- if (this._visualiserInterval) {
93
- clearInterval(this._visualiserInterval);
94
- this._visualiserInterval = undefined;
95
- }
96
- if (this._mediaStream) {
97
- this._mediaStream.getTracks().forEach(track => track.stop());
98
- this._mediaStream = null;
99
- }
100
- await this._dictationService?.stopRecording();
101
- this._updateRecordingState('stopped');
102
- }
103
-
104
- private _updateRecordingState(state: RecordingState) {
105
- this.recordingState = state;
106
- this.dispatchEvent(
107
- new CustomEvent('recording-state-changed', {
108
- detail: { state },
109
- bubbles: true,
110
- composed: true,
111
- }),
112
- );
113
- }
114
- }
@@ -1,25 +0,0 @@
1
- export class AudioService {
2
- private audioContext: AudioContext;
3
-
4
- private analyser: AnalyserNode;
5
-
6
- constructor(mediaStream: MediaStream) {
7
- this.audioContext = new AudioContext();
8
- const source = this.audioContext.createMediaStreamSource(mediaStream);
9
- this.analyser = this.audioContext.createAnalyser();
10
- this.analyser.fftSize = 8192;
11
- source.connect(this.analyser);
12
- }
13
-
14
- public getAudioLevel(): number {
15
- const bufferLength = this.analyser.fftSize;
16
- const dataArray = new Uint8Array(bufferLength);
17
- this.analyser.getByteTimeDomainData(dataArray);
18
- let sum = 0;
19
- for (let i = 0; i < bufferLength; i += 1) {
20
- const normalized = (dataArray[i] - 128) / 128;
21
- sum += normalized * normalized;
22
- }
23
- return Math.sqrt(sum / bufferLength);
24
- }
25
- }
@@ -1,56 +0,0 @@
1
- import { LitElement, html, css } from 'lit';
2
- import { property, customElement } from 'lit/decorators.js';
3
-
4
- @customElement('audio-visualiser')
5
- export class AudioVisualiser extends LitElement {
6
- @property({ type: Number }) level = 0; // expects a value from 0 to 100
7
-
8
- @property({ type: Boolean }) active = true;
9
-
10
- static styles = css`
11
- :host {
12
- height: 100%;
13
- }
14
- .container {
15
- display: flex;
16
- width: 8px;
17
- flex-direction: column-reverse; /* Bottom-up stacking */
18
- height: 100%;
19
- gap: 1px;
20
- opacity: 0.5;
21
- &.active {
22
- opacity: 1;
23
- }
24
- }
25
- .segment {
26
- flex: 1;
27
- background-color: var(--action-accent-text-color);
28
- transition: background-color 0.25s;
29
- border-radius: 1px;
30
- opacity: 0.5;
31
- }
32
- .segment.active {
33
- opacity: 1;
34
- }
35
- `;
36
-
37
- render() {
38
- // Each segment represents 20%. Using Math.ceil to fill segments optimistically.
39
- const activeSegments = Math.round(this.level * 5);
40
- const segments = [];
41
- for (let i = 0; i < 5; i += 1) {
42
- segments.push(html`
43
- <div class="segment ${i < activeSegments ? 'active' : ''}"></div>
44
- `);
45
- }
46
- return html`
47
- <div class="container ${this.active ? 'active' : ''}">${segments}</div>
48
- `;
49
- }
50
- }
51
-
52
- declare global {
53
- interface HTMLElementTagNameMap {
54
- 'audio-visualiser': AudioVisualiser;
55
- }
56
- }
@@ -1,152 +0,0 @@
1
- // mic-selector.ts
2
- import { LitElement, html, css, TemplateResult, CSSResultGroup } from 'lit';
3
- import { customElement, property } from 'lit/decorators.js';
4
-
5
- import ButtonStyles from '../styles/buttons';
6
- import SelectStyles from '../styles/select';
7
- import { LANGUAGES_SUPPORTED } from '../constants';
8
- import { getLanguageName } from '../utils';
9
- import CalloutStyles from '../styles/callout';
10
-
11
- @customElement('settings-menu')
12
- export class SettingsMenu extends LitElement {
13
- @property({ type: Array })
14
- devices: MediaDeviceInfo[] = [];
15
-
16
- @property({ type: String })
17
- selectedDevice: string = '';
18
-
19
- @property({ type: String })
20
- selectedLanguage: string = '';
21
-
22
- @property({ type: Boolean })
23
- settingsDisabled: boolean = false;
24
-
25
- static styles: CSSResultGroup = [
26
- css`
27
- :host {
28
- display: block;
29
- font-family: var(--component-font-family);
30
- }
31
- /* Retain the anchor-name styling for this component */
32
- #settings-popover-button {
33
- anchor-name: --settings_popover_btn;
34
- }
35
- [popover] {
36
- margin: 0;
37
- padding: 16px;
38
- border: 0;
39
- background: var(--card-background);
40
- border: 1px solid var(--card-border-color);
41
- border-radius: var(--card-border-radius);
42
- box-shadow: var(--card-box-shadow);
43
- z-index: 1000;
44
- max-width: 260px;
45
- width: 100%;
46
- min-width: 200px;
47
- position-anchor: --settings_popover_btn;
48
- position-area: bottom;
49
- position-visibility: always;
50
- /* inset: unset; */
51
- transform: translateX(40%);
52
- overflow-x: hidden;
53
- }
54
- .settings-wrapper {
55
- display: flex;
56
- flex-direction: column;
57
- gap: 20px;
58
- }
59
- `,
60
- ButtonStyles,
61
- SelectStyles,
62
- CalloutStyles,
63
- ];
64
-
65
- private _selectDevice(deviceId: string): void {
66
- this.selectedDevice = deviceId;
67
- // Find the device object
68
- const device = this.devices.find(d => d.deviceId === deviceId);
69
- this.dispatchEvent(
70
- new CustomEvent('recording-device-changed', {
71
- detail: device,
72
- bubbles: true,
73
- composed: true,
74
- }),
75
- );
76
- }
77
-
78
- render(): TemplateResult {
79
- return html`
80
- <div class="mic-selector">
81
- <button id="settings-popover-button" popovertarget="settings-popover">
82
- <icon-settings></icon-settings>
83
- </button>
84
- <div id="settings-popover" popover>
85
- <div class="settings-wrapper">
86
- ${this.settingsDisabled
87
- ? html`
88
- <div class="callout orange">
89
- Recording is in progress. Stop recording to change settings.
90
- </div>
91
- `
92
- : ''}
93
- <div class="form-group">
94
- <label id="device-select-label" for="device-select">
95
- Recording Device
96
- </label>
97
- <select
98
- id="device-select"
99
- aria-labelledby="device-select-label"
100
- @change=${(e: Event) => {
101
- this._selectDevice((e.target as HTMLSelectElement).value);
102
- }}
103
- ?disabled=${this.settingsDisabled}
104
- >
105
- ${this.devices.map(
106
- device => html`
107
- <option
108
- value=${device.deviceId}
109
- ?selected=${this.selectedDevice === device.deviceId}
110
- >
111
- ${device.label || 'Unknown Device'}
112
- </option>
113
- `,
114
- )}
115
- </select>
116
- </div>
117
- <div class="form-group">
118
- <label id="language-select-label" for="language-select">
119
- Dictation Language
120
- </label>
121
- <select
122
- id="language-select"
123
- aria-labelledby="language-select-label"
124
- @change=${(e: Event) => {
125
- this._selectDevice((e.target as HTMLSelectElement).value);
126
- }}
127
- ?disabled=${this.settingsDisabled}
128
- >
129
- ${LANGUAGES_SUPPORTED.map(
130
- language => html`
131
- <option
132
- value=${language}
133
- ?selected=${this.selectedLanguage === language}
134
- >
135
- ${getLanguageName(language)}
136
- </option>
137
- `,
138
- )}
139
- </select>
140
- </div>
141
- </div>
142
- </div>
143
- </div>
144
- `;
145
- }
146
- }
147
-
148
- declare global {
149
- interface HTMLElementTagNameMap {
150
- 'settings-menu': SettingsMenu;
151
- }
152
- }
package/src/constants.ts DELETED
@@ -1,10 +0,0 @@
1
- import { DictationConfig } from './types';
2
-
3
- export const LANGUAGES_SUPPORTED = ['en', 'da'];
4
- export const DEFAULT_DICTATION_CONFIG: DictationConfig = {
5
- primaryLanguage: 'en',
6
- interimResults: true,
7
- spokenPunctuation: true,
8
- automaticPunctuation: true,
9
- model: 'others',
10
- };
@@ -1,3 +0,0 @@
1
- import CortiDictation from './index.js';
2
-
3
- window.customElements.define('corti-dictation', CortiDictation);
@@ -1,141 +0,0 @@
1
- /* eslint-disable max-classes-per-file */
2
- import { LitElement, css, html } from 'lit';
3
- import { customElement } from 'lit/decorators.js';
4
-
5
- @customElement('icon-mic-on')
6
- export class IconMicOn extends LitElement {
7
- render() {
8
- return html`
9
- <div style="display: flex">
10
- <svg
11
- xmlns="http://www.w3.org/2000/svg"
12
- width="20"
13
- height="20"
14
- viewBox="0 0 24 24"
15
- fill="none"
16
- stroke="currentColor"
17
- stroke-width="2"
18
- stroke-linecap="round"
19
- stroke-linejoin="round"
20
- class="lucide lucide-mic"
21
- >
22
- <path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
23
- <path d="M19 10v2a7 7 0 0 1-14 0v-2" />
24
- <line x1="12" x2="12" y1="19" y2="22" />
25
- </svg>
26
- </div>
27
- `;
28
- }
29
- }
30
-
31
- @customElement('icon-mic-off')
32
- export class IconMicOff extends LitElement {
33
- render() {
34
- return html` <div style="display: flex">
35
- <svg
36
- xmlns="http://www.w3.org/2000/svg"
37
- width="20"
38
- height="20"
39
- viewBox="0 0 24 24"
40
- fill="none"
41
- stroke="currentColor"
42
- stroke-width="2"
43
- stroke-linecap="round"
44
- stroke-linejoin="round"
45
- class="lucide lucide-mic-off"
46
- >
47
- <line x1="2" x2="22" y1="2" y2="22" />
48
- <path d="M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" />
49
- <path d="M5 10v2a7 7 0 0 0 12 5" />
50
- <path d="M15 9.34V5a3 3 0 0 0-5.68-1.33" />
51
- <path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
52
- <line x1="12" x2="12" y1="19" y2="22" />
53
- </svg>
54
- </div>`;
55
- }
56
- }
57
-
58
- @customElement('icon-recording')
59
- export class IconRecording extends LitElement {
60
- render() {
61
- return html`
62
- <div style="display: flex;">
63
- <svg
64
- xmlns="http://www.w3.org/2000/svg"
65
- width="20"
66
- height="20"
67
- viewBox="0 0 24 24"
68
- fill="none"
69
- stroke="currentColor"
70
- stroke-width="2"
71
- stroke-linecap="round"
72
- stroke-linejoin="round"
73
- class="lucide lucide-circle-stop"
74
- >
75
- <circle cx="12" cy="12" r="10" />
76
- <rect x="9" y="9" width="6" height="6" rx="1" fill="currentColor" />
77
- </svg>
78
- </div>
79
- `;
80
- }
81
- }
82
- @customElement('icon-settings')
83
- export class IconSettings extends LitElement {
84
- render() {
85
- return html`<div style="display: flex">
86
- <svg
87
- xmlns="http://www.w3.org/2000/svg"
88
- width="20"
89
- height="20"
90
- viewBox="0 0 24 24"
91
- fill="none"
92
- stroke="currentColor"
93
- stroke-width="2"
94
- stroke-linecap="round"
95
- stroke-linejoin="round"
96
- class="lucide lucide-settings-2"
97
- >
98
- <path d="M20 7h-9" />
99
- <path d="M14 17H5" />
100
- <circle cx="17" cy="17" r="3" />
101
- <circle cx="7" cy="7" r="3" />
102
- </svg>
103
- </div>`;
104
- }
105
- }
106
-
107
- @customElement('icon-loading-spinner')
108
- export class IconLoadingSpinner extends LitElement {
109
- static styles = css`
110
- @keyframes spin {
111
- 0% {
112
- transform: rotate(0deg);
113
- }
114
- 100% {
115
- transform: rotate(360deg);
116
- }
117
- }
118
- .spin {
119
- animation: spin 1s linear infinite;
120
- }
121
- `;
122
-
123
- render() {
124
- return html`<div style="display: flex">
125
- <svg
126
- xmlns="http://www.w3.org/2000/svg"
127
- width="20"
128
- height="20"
129
- viewBox="0 0 24 24"
130
- fill="none"
131
- stroke="currentColor"
132
- stroke-width="2"
133
- stroke-linecap="round"
134
- stroke-linejoin="round"
135
- class="lucide lucide-loader-circle spin"
136
- >
137
- <path d="M21 12a9 9 0 1 1-6.219-8.56" />
138
- </svg>
139
- </div>`;
140
- }
141
- }
File without changes
package/src/index.ts DELETED
@@ -1,154 +0,0 @@
1
- // corti-dictation.ts
2
- import { html, LitElement } from 'lit';
3
- import { property, state } from 'lit/decorators.js';
4
- import { RecorderManager } from './RecorderManager';
5
- import './components/settings-menu';
6
- import './components/audio-visualiser';
7
- import './icons/icons';
8
- import ThemeStyles from './styles/theme';
9
- import ButtonStyles from './styles/buttons';
10
- import ComponentStyles from './styles/ComponentStyles';
11
-
12
- import { DictationConfig, ServerConfig } from './types';
13
- import { DEFAULT_DICTATION_CONFIG } from './constants';
14
- import CalloutStyles from './styles/callout';
15
-
16
- export class CortiDictation extends LitElement {
17
- static styles = [ButtonStyles, ThemeStyles, ComponentStyles, CalloutStyles];
18
-
19
- @property({ type: Array })
20
- devices: MediaDeviceInfo[] = [];
21
-
22
- @property({ type: String, reflect: true })
23
- recordingState = 'stopped';
24
-
25
- @property({ type: Object })
26
- dictationConfig: DictationConfig = DEFAULT_DICTATION_CONFIG;
27
-
28
- @property({ type: Object })
29
- serverConfig: ServerConfig = {};
30
-
31
- @state()
32
- private _audioLevel = 0;
33
-
34
- private recorderManager = new RecorderManager();
35
-
36
- async connectedCallback() {
37
- super.connectedCallback();
38
- await this.recorderManager.initialize();
39
- this.devices = this.recorderManager.devices;
40
-
41
- // Map event names to any extra handling logic
42
- const eventHandlers: Record<string, (e: CustomEvent) => void> = {
43
- 'recording-state-changed': e => {
44
- this.recordingState = e.detail.state;
45
- },
46
- 'audio-level-changed': e => {
47
- this._audioLevel = e.detail.audioLevel;
48
- this.requestUpdate();
49
- },
50
- };
51
-
52
- const eventsToRelay = [
53
- 'recording-state-changed',
54
- 'audio-level-changed',
55
- 'error',
56
- 'transcript',
57
- ];
58
-
59
- eventsToRelay.forEach(eventName => {
60
- this.recorderManager.addEventListener(eventName, (e: Event) => {
61
- const customEvent = e as CustomEvent;
62
- // Perform any additional handling if defined
63
- if (eventHandlers[eventName]) {
64
- eventHandlers[eventName](customEvent);
65
- }
66
- // Re-dispatch the event from the component
67
- this.dispatchEvent(
68
- new CustomEvent(eventName, {
69
- detail: customEvent.detail,
70
- bubbles: true,
71
- composed: true,
72
- }),
73
- );
74
- });
75
- });
76
- }
77
-
78
- public toggleRecording() {
79
- this._toggleRecording();
80
- }
81
-
82
- _toggleRecording() {
83
- if (this.recordingState === 'recording') {
84
- this.recorderManager.stopRecording();
85
- } else if (this.recordingState === 'stopped') {
86
- this.recorderManager.startRecording({
87
- dictationConfig: this.dictationConfig,
88
- serverConfig: this.serverConfig,
89
- });
90
- }
91
- }
92
-
93
- // Handle device change events if needed
94
- async _onRecordingDeviceChanged(event: Event) {
95
- const customEvent = event as CustomEvent;
96
- this.recorderManager.selectedDevice = customEvent.detail.deviceId;
97
- if (this.recordingState === 'recording') {
98
- await this.recorderManager.stopRecording();
99
- await this.recorderManager.startRecording({
100
- dictationConfig: this.dictationConfig,
101
- serverConfig: this.serverConfig,
102
- });
103
- }
104
- }
105
-
106
- render() {
107
- const isConfigured =
108
- this.serverConfig &&
109
- this.serverConfig.token &&
110
- this.serverConfig.environment &&
111
- this.serverConfig.tenant;
112
- if (!isConfigured) {
113
- return html`
114
- <div class="wrapper">
115
- <div class="callout red tiny">
116
- Please configure the server settings in the parent component.
117
- </div>
118
- </div>
119
- `;
120
- }
121
-
122
- const isLoading =
123
- this.recordingState === 'initializing' ||
124
- this.recordingState === 'stopping';
125
- const isRecording = this.recordingState === 'recording';
126
- return html`
127
- <div class="wrapper">
128
- <button
129
- @click=${this._toggleRecording}
130
- class=${isRecording ? 'red' : 'accent'}
131
- >
132
- ${isLoading
133
- ? html`<icon-loading-spinner></icon-loading-spinner>`
134
- : isRecording
135
- ? html`<icon-recording></icon-recording>`
136
- : html`<icon-mic-on></icon-mic-on>`}
137
- <audio-visualiser
138
- .level=${this._audioLevel}
139
- .active=${isRecording}
140
- ></audio-visualiser>
141
- </button>
142
-
143
- <settings-menu
144
- .devices=${this.devices}
145
- .selectedDevice=${this.recorderManager.selectedDevice}
146
- ?settingsDisabled=${this.recordingState !== 'stopped'}
147
- @recording-device-changed=${this._onRecordingDeviceChanged}
148
- ></settings-menu>
149
- </div>
150
- `;
151
- }
152
- }
153
-
154
- export default CortiDictation;