kempo-ui 0.4.3 → 0.4.5

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 (108) hide show
  1. package/.claude/skills/get-icon/SKILL.md +144 -0
  2. package/.claude/skills/highlight-code/SKILL.md +62 -0
  3. package/.claude/skills/new-component/SKILL.md +362 -0
  4. package/.github/skills/get-icon/SKILL.md +4 -4
  5. package/.github/skills/highlight-code/SKILL.md +51 -20
  6. package/.github/skills/new-component/SKILL.md +183 -152
  7. package/AGENTS.md +2 -2
  8. package/dist/components/SpeechToText.js +60 -0
  9. package/dist/components/TextToSpeech.js +56 -0
  10. package/dist/components/VoiceSelector.js +49 -0
  11. package/dist/utils/voice.js +1 -0
  12. package/docs/components/accordion.html +15 -0
  13. package/docs/components/aside.html +15 -0
  14. package/docs/components/calendar.html +15 -0
  15. package/docs/components/card.html +15 -0
  16. package/docs/components/code-editor.html +15 -0
  17. package/docs/components/color-picker.html +15 -0
  18. package/docs/components/combobox.html +15 -0
  19. package/docs/components/content-slider.html +15 -0
  20. package/docs/components/context.html +15 -0
  21. package/docs/components/dialog.html +15 -0
  22. package/docs/components/dropdown.html +15 -0
  23. package/docs/components/filter-list.html +15 -0
  24. package/docs/components/focus-capture.html +15 -0
  25. package/docs/components/html-editor.html +15 -0
  26. package/docs/components/hybrid-component.html +15 -0
  27. package/docs/components/icon.html +15 -0
  28. package/docs/components/import.html +15 -0
  29. package/docs/components/light-component.html +15 -0
  30. package/docs/components/nav-spacer.html +15 -0
  31. package/docs/components/nav.html +15 -0
  32. package/docs/components/photo-viewer.html +15 -0
  33. package/docs/components/progress.html +15 -0
  34. package/docs/components/resize.html +15 -0
  35. package/docs/components/shadow-component.html +15 -0
  36. package/docs/components/show-more.html +15 -0
  37. package/docs/components/slider.html +15 -0
  38. package/docs/components/sortable.html +15 -0
  39. package/docs/components/speech-to-text.html +724 -0
  40. package/docs/components/spinner.html +15 -0
  41. package/docs/components/split.html +15 -0
  42. package/docs/components/table.html +15 -0
  43. package/docs/components/tableControls.html +15 -0
  44. package/docs/components/tableCustomFields.html +15 -0
  45. package/docs/components/tableFetchRecords.html +15 -0
  46. package/docs/components/tableFieldSortHide.html +15 -0
  47. package/docs/components/tablePagination.html +15 -0
  48. package/docs/components/tablePlaceholder.html +15 -0
  49. package/docs/components/tableRecordEditing.html +15 -0
  50. package/docs/components/tableRecordFiltering.html +15 -0
  51. package/docs/components/tableRecordHiding.html +15 -0
  52. package/docs/components/tableRecordSearching.html +15 -0
  53. package/docs/components/tableRecordSelection.html +15 -0
  54. package/docs/components/tableRowControls.html +15 -0
  55. package/docs/components/tableServerSync.html +15 -0
  56. package/docs/components/tableSorting.html +15 -0
  57. package/docs/components/tabs.html +15 -0
  58. package/docs/components/tags.html +15 -0
  59. package/docs/components/text-to-speech.html +718 -0
  60. package/docs/components/theme-select.html +15 -0
  61. package/docs/components/theme-switcher.html +15 -0
  62. package/docs/components/time.html +15 -0
  63. package/docs/components/timestamp.html +15 -0
  64. package/docs/components/toast.html +15 -0
  65. package/docs/components/toggle.html +15 -0
  66. package/docs/components/tree.html +15 -0
  67. package/docs/components/voice-selector.html +598 -0
  68. package/docs/icons/mic.svg +1 -0
  69. package/docs/icons/record_voice_over.svg +1 -0
  70. package/docs/icons/stop.svg +1 -0
  71. package/docs/index.html +39 -0
  72. package/docs/src/components/SpeechToText.js +60 -0
  73. package/docs/src/components/TextToSpeech.js +56 -0
  74. package/docs/src/components/VoiceSelector.js +49 -0
  75. package/docs/src/utils/voice.js +1 -0
  76. package/docs/utils/context.html +15 -0
  77. package/docs/utils/cookie.html +15 -0
  78. package/docs/utils/debounce.html +15 -0
  79. package/docs/utils/drag.html +15 -0
  80. package/docs/utils/elevation.html +15 -0
  81. package/docs/utils/formatTimestamp.html +15 -0
  82. package/docs/utils/object.html +15 -0
  83. package/docs/utils/propConverters.html +15 -0
  84. package/docs/utils/string.html +15 -0
  85. package/docs/utils/theme.html +15 -0
  86. package/docs/utils/toTitleCase.html +15 -0
  87. package/docs/utils/type.html +15 -0
  88. package/docs/utils/voice.html +536 -0
  89. package/docs/utils/wait.html +15 -0
  90. package/docs-src/components/speech-to-text.page.html +251 -0
  91. package/docs-src/components/text-to-speech.page.html +245 -0
  92. package/docs-src/components/voice-selector.page.html +125 -0
  93. package/docs-src/index.page.html +24 -0
  94. package/docs-src/nav.fragment.html +15 -0
  95. package/docs-src/utils/voice.page.html +66 -0
  96. package/icons/mic.svg +1 -0
  97. package/icons/record_voice_over.svg +1 -0
  98. package/icons/stop.svg +1 -0
  99. package/llms.txt +4 -0
  100. package/package.json +1 -1
  101. package/src/components/SpeechToText.js +252 -0
  102. package/src/components/TextToSpeech.js +205 -0
  103. package/src/components/VoiceSelector.js +271 -0
  104. package/src/utils/voice.js +103 -0
  105. package/tests/components/SpeechToText.browser-test.js +530 -0
  106. package/tests/components/TextToSpeech.browser-test.js +581 -0
  107. package/tests/components/VoiceSelector.browser-test.js +374 -0
  108. package/tests/utils/voice.browser-test.js +128 -0
@@ -0,0 +1,724 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Speech To Text - Components - Kempo Docs - A Web Components Solution</title>
7
+ <link rel="icon" type="image/png" sizes="48x48" href="../media/icon48.png">
8
+ <link rel="manifest" href="../manifest.json" />
9
+ <link rel="stylesheet" href="../kempo-vars.css" />
10
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/kempo-css@2/dist/kempo.min.css" />
11
+ <link rel="stylesheet" href="../kempo-hljs.css" />
12
+ <link rel="stylesheet" href="../styles.css" />
13
+ <script>window.litDisableBundleWarning = true;</script>
14
+
15
+ </head>
16
+ <body>
17
+
18
+ <k-nav
19
+ fixed
20
+ class="bg-primary"
21
+ >
22
+ <button
23
+ id="toggleNavSideMenu"
24
+ class="link"
25
+ >
26
+ <k-icon name="menu"></k-icon>
27
+ </button>
28
+ <a
29
+ href="../"
30
+ class="d-if ph"
31
+ style="align-items: center"
32
+ >
33
+ <img
34
+ src="../media/icon32.png"
35
+ alt="Kempo UI Icon"
36
+ class="pr"
37
+ />
38
+ Kempo UI
39
+ </a>
40
+ <div
41
+ style="position:relative;margin:0 .25rem;align-self:center;"
42
+ theme="light"
43
+ >
44
+ <input
45
+ id="navSearchInput"
46
+ type="search"
47
+ placeholder="Search docs..."
48
+ autocomplete="off"
49
+ style="width:11rem;"
50
+ />
51
+ <div
52
+ id="navSearchDropdown"
53
+ hidden
54
+ theme="light"
55
+ style="position:absolute;top:calc(100% + 4px);left:0;width:min(480px,90vw);max-height:70vh;background:var(--c_bg);border:1px solid var(--c_border);border-radius:var(--radius);overflow:auto;z-index:9999;box-shadow:0 4px 12px rgba(0,0,0,.3);"
56
+ >
57
+ <k-filter-list
58
+ id="navSearchList"
59
+ style="display:block;padding:.25rem 0;"
60
+ >
61
+ <k-filter-item filter-keywords="accordion components"><a
62
+ href="../components/accordion.html">Accordion<br><small>Component</small></a></k-filter-item>
63
+ <k-filter-item filter-keywords="aside sidebar components"><a
64
+ href="../components/aside.html">Aside<br><small>Component</small></a></k-filter-item>
65
+ <k-filter-item filter-keywords="calendar date picker range month day components"><a
66
+ href="../components/calendar.html"
67
+ >Calendar<br><small>Component</small></a></k-filter-item>
68
+ <k-filter-item filter-keywords="card components"><a
69
+ href="../components/card.html">Card<br><small>Component</small></a></k-filter-item>
70
+ <k-filter-item filter-keywords="code editor codeeditor monaco components"><a
71
+ href="../components/code-editor.html"
72
+ >Code Editor<br><small>Component</small></a></k-filter-item>
73
+ <k-filter-item filter-keywords="combobox combo box search autocomplete components"><a
74
+ href="../components/combobox.html"
75
+ >Combobox<br><small>Component</small></a></k-filter-item>
76
+ <k-filter-item filter-keywords="color picker colorpicker components"><a
77
+ href="../components/color-picker.html"
78
+ >Color Picker<br><small>Component</small></a></k-filter-item>
79
+ <k-filter-item filter-keywords="content slider components"><a
80
+ href="../components/content-slider.html"
81
+ >Content Slider<br><small>Component</small></a></k-filter-item>
82
+ <k-filter-item filter-keywords="context state global components"><a
83
+ href="../components/context.html"
84
+ >Context<br><small>Component</small></a></k-filter-item>
85
+ <k-filter-item filter-keywords="dialog modal popup components"><a
86
+ href="../components/dialog.html">Dialog<br><small>Component</small></a></k-filter-item>
87
+ <k-filter-item filter-keywords="dropdown select components"><a
88
+ href="../components/dropdown.html">Dropdown<br><small>Component</small></a></k-filter-item>
89
+ <k-filter-item filter-keywords="filter list filterlist components"><a
90
+ href="../components/filter-list.html"
91
+ >Filter List<br><small>Component</small></a></k-filter-item>
92
+ <k-filter-item filter-keywords="focus capture focuscapture components"><a
93
+ href="../components/focus-capture.html"
94
+ >Focus Capture<br><small>Component</small></a></k-filter-item>
95
+ <k-filter-item filter-keywords="html editor components"><a
96
+ href="../components/html-editor.html">HTML
97
+ Editor<br><small>Component</small></a></k-filter-item>
98
+ <k-filter-item filter-keywords="icon components"><a
99
+ href="../components/icon.html">Icon<br><small>Component</small></a></k-filter-item>
100
+ <k-filter-item filter-keywords="import components"><a
101
+ href="../components/import.html">Import<br><small>Component</small></a></k-filter-item>
102
+ <k-filter-item filter-keywords="nav navbar navigation components"><a
103
+ href="../components/nav.html">Nav<br><small>Component</small></a></k-filter-item>
104
+ <k-filter-item filter-keywords="nav spacer navbar spacer navspacer components"><a
105
+ href="../components/nav-spacer.html"
106
+ >Nav Spacer<br><small>Component</small></a></k-filter-item>
107
+ <k-filter-item filter-keywords="photo viewer photoviewer components"><a
108
+ href="../components/photo-viewer.html"
109
+ >Photo Viewer<br><small>Component</small></a></k-filter-item>
110
+ <k-filter-item filter-keywords="progress loading components"><a
111
+ href="../components/progress.html">Progress<br><small>Component</small></a></k-filter-item>
112
+ <k-filter-item filter-keywords="resize components"><a
113
+ href="../components/resize.html">Resize<br><small>Component</small></a></k-filter-item>
114
+ <k-filter-item filter-keywords="show more showmore components"><a
115
+ href="../components/show-more.html"
116
+ >Show More<br><small>Component</small></a></k-filter-item>
117
+ <k-filter-item filter-keywords="slider range input step components"><a
118
+ href="../components/slider.html"
119
+ >Slider<br><small>Component</small></a></k-filter-item>
120
+ <k-filter-item filter-keywords="sortable drag drop sort components"><a
121
+ href="../components/sortable.html"
122
+ >Sortable<br><small>Component</small></a></k-filter-item>
123
+ <k-filter-item filter-keywords="speech to text speechtotext microphone voice recognition transcription components"><a
124
+ href="../components/speech-to-text.html"
125
+ >Speech To Text<br><small>Component</small></a></k-filter-item>
126
+ <k-filter-item filter-keywords="spinner loading components"><a
127
+ href="../components/spinner.html">Spinner<br><small>Component</small></a></k-filter-item>
128
+ <k-filter-item filter-keywords="split pane components"><a
129
+ href="../components/split.html">Split<br><small>Component</small></a></k-filter-item>
130
+ <k-filter-item filter-keywords="table data grid components"><a
131
+ href="../components/table.html">Table<br><small>Component</small></a></k-filter-item>
132
+ <k-filter-item filter-keywords="table controls advanced example"><a
133
+ href="../components/tableControls.html"
134
+ >Table &mdash; Controls<br><small>Advanced Example</small></a></k-filter-item>
135
+ <k-filter-item filter-keywords="table custom fields advanced example"><a
136
+ href="../components/tableCustomFields.html"
137
+ >Table &mdash; Custom Fields<br><small>Advanced Example</small></a></k-filter-item>
138
+ <k-filter-item filter-keywords="table fetch records advanced example"><a
139
+ href="../components/tableFetchRecords.html"
140
+ >Table &mdash; Fetch Records<br><small>Advanced Example</small></a></k-filter-item>
141
+ <k-filter-item filter-keywords="table field sort hide advanced example"><a
142
+ href="../components/tableFieldSortHide.html"
143
+ >Table &mdash; Field Sort &amp; Hide<br><small>Advanced Example</small></a></k-filter-item>
144
+ <k-filter-item filter-keywords="table pagination advanced example"><a
145
+ href="../components/tablePagination.html"
146
+ >Table &mdash; Pagination<br><small>Advanced Example</small></a></k-filter-item>
147
+ <k-filter-item filter-keywords="table record editing advanced example"><a
148
+ href="../components/tableRecordEditing.html"
149
+ >Table &mdash; Record Editing<br><small>Advanced Example</small></a></k-filter-item>
150
+ <k-filter-item filter-keywords="table record filtering advanced example"><a
151
+ href="../components/tableRecordFiltering.html"
152
+ >Table &mdash; Record Filtering<br><small>Advanced Example</small></a></k-filter-item>
153
+ <k-filter-item filter-keywords="table record hiding advanced example"><a
154
+ href="../components/tableRecordHiding.html"
155
+ >Table &mdash; Record Hiding<br><small>Advanced Example</small></a></k-filter-item>
156
+ <k-filter-item filter-keywords="table record searching advanced example"><a
157
+ href="../components/tableRecordSearching.html"
158
+ >Table &mdash; Record Searching<br><small>Advanced Example</small></a></k-filter-item>
159
+ <k-filter-item filter-keywords="table record selection advanced example"><a
160
+ href="../components/tableRecordSelection.html"
161
+ >Table &mdash; Record Selection<br><small>Advanced Example</small></a></k-filter-item>
162
+ <k-filter-item filter-keywords="table row controls advanced example"><a
163
+ href="../components/tableRowControls.html"
164
+ >Table &mdash; Row Controls<br><small>Advanced Example</small></a></k-filter-item>
165
+ <k-filter-item filter-keywords="table server sync advanced example"><a
166
+ href="../components/tableServerSync.html"
167
+ >Table &mdash; Server Sync<br><small>Advanced Example</small></a></k-filter-item>
168
+ <k-filter-item filter-keywords="table sorting advanced example"><a
169
+ href="../components/tableSorting.html"
170
+ >Table &mdash; Sorting<br><small>Advanced Example</small></a></k-filter-item>
171
+ <k-filter-item filter-keywords="table placeholder advanced example"><a
172
+ href="../components/tablePlaceholder.html"
173
+ >Table &mdash; Placeholder<br><small>Advanced Example</small></a></k-filter-item>
174
+ <k-filter-item filter-keywords="tabs tab panel components"><a
175
+ href="../components/tabs.html">Tabs<br><small>Component</small></a></k-filter-item>
176
+ <k-filter-item filter-keywords="tags tag input components"><a
177
+ href="../components/tags.html">Tags<br><small>Component</small></a></k-filter-item>
178
+ <k-filter-item filter-keywords="text to speech texttospeech tts speak voice synthesis components"><a
179
+ href="../components/text-to-speech.html"
180
+ >Text To Speech<br><small>Component</small></a></k-filter-item>
181
+ <k-filter-item filter-keywords="theme select dropdown dark light components"><a
182
+ href="../components/theme-select.html"
183
+ >Theme Select<br><small>Component</small></a></k-filter-item>
184
+ <k-filter-item filter-keywords="theme switcher dark light components"><a
185
+ href="../components/theme-switcher.html"
186
+ >Theme Switcher<br><small>Component</small></a></k-filter-item>
187
+ <k-filter-item filter-keywords="time picker clock hour minute form components"><a
188
+ href="../components/time.html"
189
+ >Time<br><small>Component</small></a></k-filter-item>
190
+ <k-filter-item filter-keywords="timestamp date time components"><a
191
+ href="../components/timestamp.html"
192
+ >Timestamp<br><small>Component</small></a></k-filter-item>
193
+ <k-filter-item filter-keywords="toast notification alert components"><a
194
+ href="../components/toast.html"
195
+ >Toast<br><small>Component</small></a></k-filter-item>
196
+ <k-filter-item filter-keywords="toggle switch checkbox components"><a
197
+ href="../components/toggle.html"
198
+ >Toggle<br><small>Component</small></a></k-filter-item>
199
+ <k-filter-item filter-keywords="tree treeview components"><a
200
+ href="../components/tree.html">Tree<br><small>Component</small></a></k-filter-item>
201
+ <k-filter-item filter-keywords="voice selector dropdown speech synthesis preference components"><a
202
+ href="../components/voice-selector.html"
203
+ >Voice Selector<br><small>Component</small></a></k-filter-item>
204
+ <k-filter-item filter-keywords="shadow component base"><a
205
+ href="../components/shadow-component.html"
206
+ >Shadow Component<br><small>Base Component</small></a></k-filter-item>
207
+ <k-filter-item filter-keywords="light component base"><a
208
+ href="../components/light-component.html">Light Component<br><small>Base
209
+ Component</small></a></k-filter-item>
210
+ <k-filter-item filter-keywords="hybrid component base"><a
211
+ href="../components/hybrid-component.html"
212
+ >Hybrid Component<br><small>Base Component</small></a></k-filter-item>
213
+ <k-filter-item filter-keywords="cookie utils utility"><a
214
+ href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
215
+ <k-filter-item filter-keywords="context utils utility"><a
216
+ href="../utils/context.html">context<br><small>Utility</small></a></k-filter-item>
217
+ <k-filter-item filter-keywords="debounce utils utility"><a
218
+ href="../utils/debounce.html">debounce<br><small>Utility</small></a></k-filter-item>
219
+ <k-filter-item filter-keywords="drag utils utility"><a
220
+ href="../utils/drag.html">drag<br><small>Utility</small></a></k-filter-item>
221
+ <k-filter-item filter-keywords="elevation z-index stacking utils"><a
222
+ href="../utils/elevation.html">elevation<br><small>Utility</small></a></k-filter-item>
223
+ <k-filter-item filter-keywords="formattimestamp timestamp format date time utils utility"><a
224
+ href="../utils/formatTimestamp.html"
225
+ >formatTimestamp<br><small>Utility</small></a></k-filter-item>
226
+ <k-filter-item filter-keywords="object utils utility"><a
227
+ href="../utils/object.html">object<br><small>Utility</small></a></k-filter-item>
228
+ <k-filter-item filter-keywords="propconverters prop converters utils utility"><a
229
+ href="../utils/propConverters.html"
230
+ >propConverters<br><small>Utility</small></a></k-filter-item>
231
+ <k-filter-item filter-keywords="string utils utility"><a
232
+ href="../utils/string.html">string<br><small>Utility</small></a></k-filter-item>
233
+ <k-filter-item filter-keywords="theme utils utility"><a
234
+ href="../utils/theme.html">theme<br><small>Utility</small></a></k-filter-item>
235
+ <k-filter-item filter-keywords="type utils utility"><a
236
+ href="../utils/type.html">type<br><small>Utility</small></a></k-filter-item>
237
+ <k-filter-item filter-keywords="voice speech synthesis preference utils utility"><a
238
+ href="../utils/voice.html">voice<br><small>Utility</small></a></k-filter-item>
239
+ <k-filter-item filter-keywords="wait async utils utility"><a
240
+ href="../utils/wait.html">wait<br><small>Utility</small></a></k-filter-item>
241
+ </k-filter-list>
242
+ </div>
243
+ </div>
244
+ <div class="flex"></div>
245
+ <a
246
+ href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20"
247
+ target="_blank"
248
+ ><k-icon name="license"></k-icon></a>
249
+ <a
250
+ href="https://www.npmjs.com/package/kempo-ui"
251
+ target="_blank"
252
+ ><k-icon name="npm"></k-icon></a>
253
+ <a
254
+ href="https://github.com/dustinpoissant/kempo-ui"
255
+ target="_blank"
256
+ ><k-icon name="github-mark"></k-icon></a>
257
+ <k-theme-switcher
258
+ class="mr"
259
+ style="
260
+ --padding: 0.5rem;
261
+ --c_active: var(--tc_on_primary);
262
+ --tc_active: var(--c_primary);
263
+ --c_inactive__hover: rgba(255, 255, 255, 0.1);
264
+ "
265
+ ></k-theme-switcher>
266
+ </k-nav>
267
+ <div style="width: 100%; height: 4rem;"></div>
268
+ <k-aside
269
+ id="navSideMenu"
270
+ main="overlay"
271
+ state="offscreen"
272
+ >
273
+ <menu>
274
+ <a
275
+ href="../"
276
+ class="ta-center bb mb r0"
277
+ >
278
+ <h1 class="tc-primary">Kempo UI</h1>
279
+ <img
280
+ src="../media/icon128.png"
281
+ alt="Kempo UI Icon"
282
+ />
283
+ </a>
284
+
285
+ <div class="pl mb">
286
+ <h3>Components</h3>
287
+ <a href="../components/accordion.html">Accordion</a>
288
+ <a href="../components/aside.html">Aside</a>
289
+ <a href="../components/calendar.html">Calendar</a>
290
+ <a href="../components/card.html">Card</a>
291
+ <a href="../components/code-editor.html">Code Editor</a>
292
+ <a href="../components/combobox.html">Combobox</a>
293
+ <a href="../components/color-picker.html">ColorPicker</a>
294
+ <a href="../components/content-slider.html">Content Slider</a>
295
+ <a href="../components/context.html">Context</a>
296
+ <a href="../components/dialog.html">Dialog</a>
297
+ <a href="../components/dropdown.html">Dropdown</a>
298
+ <a href="../components/filter-list.html">Filter List</a>
299
+ <a href="../components/focus-capture.html">FocusCapture</a>
300
+ <a href="../components/html-editor.html">HTML Editor</a>
301
+ <a href="../components/icon.html">Icon</a>
302
+ <a href="../components/import.html">Import</a>
303
+ <a href="../components/nav.html">Nav</a>
304
+ <a href="../components/nav-spacer.html">Nav Spacer</a>
305
+ <a href="../components/photo-viewer.html">Photo Viewer</a>
306
+ <a href="../components/progress.html">Progress</a>
307
+ <a href="../components/resize.html">Resize</a>
308
+ <a href="../components/show-more.html">Show More</a>
309
+ <a href="../components/slider.html">Slider</a>
310
+ <a href="../components/sortable.html">Sortable</a>
311
+ <a href="../components/speech-to-text.html">Speech To Text</a>
312
+ <a href="../components/spinner.html">Spinner</a>
313
+ <a href="../components/split.html">Split</a>
314
+ <a href="../components/table.html">Table</a>
315
+ <a href="../components/tabs.html">Tabs</a>
316
+ <a href="../components/tags.html">Tags</a>
317
+ <a href="../components/text-to-speech.html">Text To Speech</a>
318
+ <a href="../components/theme-select.html">Theme Select</a>
319
+ <a href="../components/theme-switcher.html">Theme Switcher</a>
320
+ <a href="../components/time.html">Time</a>
321
+ <a href="../components/timestamp.html">Timestamp</a>
322
+ <a href="../components/toast.html">Toast</a>
323
+ <a href="../components/toggle.html">Toggle</a>
324
+ <a href="../components/tree.html">Tree</a>
325
+ <a href="../components/voice-selector.html">Voice Selector</a>
326
+ </div>
327
+
328
+ <h5 class="mb0">Base Components</h5>
329
+ <div class="pl mb">
330
+ <a href="../components/shadow-component.html">Shadow Component</a>
331
+ <a href="../components/light-component.html">Light Component</a>
332
+ <a href="../components/hybrid-component.html">Hybrid Component</a>
333
+ </div>
334
+
335
+ <h5 class="mb0">Utils</h5>
336
+ <div class="pl mb">
337
+ <a href="../utils/cookie.html">cookie</a>
338
+ <a href="../utils/context.html">context</a>
339
+ <a href="../utils/debounce.html">debounce</a>
340
+ <a href="../utils/drag.html">drag</a>
341
+ <a href="../utils/elevation.html">elevation</a>
342
+ <a href="../utils/formatTimestamp.html">formatTimestamp</a>
343
+ <a href="../utils/object.html">object</a>
344
+ <a href="../utils/propConverters.html">propConverters</a>
345
+ <a href="../utils/string.html">string</a>
346
+ <a href="../utils/theme.html">theme</a>
347
+ <a href="../utils/type.html">type</a>
348
+ <a href="../utils/voice.html">voice</a>
349
+ <a href="../utils/wait.html">wait</a>
350
+ </div>
351
+ </menu>
352
+ </k-aside>
353
+ <style>
354
+ #navSearchList a {
355
+ display: block;
356
+ padding: .25rem .5rem;
357
+ border-radius: var(--radius);
358
+ text-decoration: none;
359
+ color: var(--tc);
360
+ }
361
+
362
+ #navSearchList a:hover {
363
+ background: rgba(128, 128, 128, .15);
364
+ }
365
+
366
+ #navSearchList a small {
367
+ display: block;
368
+ color: var(--tc_muted);
369
+ }
370
+ </style>
371
+ <script
372
+ src="../src/components/Nav.js"
373
+ type="module"
374
+ ></script>
375
+ <script
376
+ src="../src/components/FilterList.js"
377
+ type="module"
378
+ ></script>
379
+ <script
380
+ src="../src/components/FilterItem.js"
381
+ type="module"
382
+ ></script>
383
+ <script
384
+ src="../src/components/Aside.js"
385
+ type="module"
386
+ ></script>
387
+ <script
388
+ src="../src/components/Icon.js"
389
+ type="module"
390
+ ></script>
391
+ <script
392
+ src="../src/components/ThemeSwitcher.js"
393
+ type="module"
394
+ ></script>
395
+ <script type="module">
396
+ import debounce from '../src/utils/debounce.js';
397
+
398
+ document.getElementById('toggleNavSideMenu').addEventListener('click', async () => {
399
+ await window.customElements.whenDefined('k-aside');
400
+ document.getElementById('navSideMenu').toggle();
401
+ });
402
+
403
+ document.addEventListener('click', function (e) {
404
+ if (e.target.matches('a[href^="#"]')) {
405
+ e.preventDefault();
406
+ const targetId = e.target.getAttribute('href').replace('#', '');
407
+ const target = document.getElementById(targetId);
408
+ if (target) {
409
+ target.scrollIntoView({ behavior: 'smooth' });
410
+ const url = window.location.pathname + window.location.search + '#' + targetId;
411
+ history.replaceState(null, '', url);
412
+ }
413
+ }
414
+ });
415
+
416
+ /*
417
+ Nav Search
418
+ */
419
+ const searchInput = document.getElementById('navSearchInput');
420
+ const searchDropdown = document.getElementById('navSearchDropdown');
421
+ let navSearchList = null;
422
+
423
+ const openSearch = async () => {
424
+ await customElements.whenDefined('k-filter-list');
425
+ if (!navSearchList) navSearchList = document.getElementById('navSearchList');
426
+ navSearchList.filter(searchInput.value);
427
+ searchDropdown.hidden = false;
428
+ };
429
+
430
+ const closeSearch = () => {
431
+ searchDropdown.hidden = true;
432
+ navSearchList?.clearFocus();
433
+ };
434
+
435
+ searchInput.addEventListener('focus', openSearch);
436
+
437
+ searchInput.addEventListener('input', debounce(e => {
438
+ navSearchList?.filter(e.target.value);
439
+ }, 150));
440
+
441
+ searchInput.addEventListener('keydown', e => {
442
+ if (e.key === 'Escape') {
443
+ searchInput.value = '';
444
+ searchInput.blur();
445
+ closeSearch();
446
+ } else if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter') {
447
+ navSearchList?.handleKeydown(e);
448
+ }
449
+ });
450
+
451
+ searchInput.addEventListener('blur', () => {
452
+ setTimeout(closeSearch, 150);
453
+ });
454
+
455
+ document.addEventListener('keydown', e => {
456
+ let active = document.activeElement;
457
+ while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
458
+ const tag = active?.tagName;
459
+ if (tag === 'INPUT' || tag === 'TEXTAREA' || active?.isContentEditable) return;
460
+ if (e.metaKey || e.ctrlKey || e.altKey) return;
461
+ if (e.key.length === 1) {
462
+ searchInput.focus();
463
+ }
464
+ });
465
+ </script>
466
+
467
+
468
+ <h1 class="ta-center">Speech To Text</h1>
469
+
470
+ <k-main>
471
+
472
+ <k-accordion persistent-id="toc" class="b r mb">
473
+ <k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
474
+ <k-accordion-panel name="toc-panel">
475
+ <div class="m pl">
476
+ <h6>Examples</h6>
477
+ <a href="#basicUsage">Basic Usage</a><br />
478
+ <a href="#liveTranscript">Live Transcript</a><br />
479
+ <a href="#continuous">Continuous</a><br />
480
+ <a href="#language">Language</a><br />
481
+ <a href="#minConfidence">Min Confidence</a><br />
482
+ <a href="#timeout">Timeout</a><br />
483
+ <a href="#disabled">Disabled</a><br />
484
+
485
+ <h6 class="mt"><a href="#jsRef" class="no-link">JavaScript Reference</a></h6>
486
+ <a href="#constructor">Constructor</a><br />
487
+ <a href="#requirements">Requirements</a><br />
488
+ <a href="#properties">Properties</a><br />
489
+ <a href="#methods">Methods</a><br />
490
+ <a href="#cssVariables">CSS Variables</a><br />
491
+ <a href="#events">Events</a><br />
492
+ </div>
493
+ </k-accordion-panel>
494
+ </k-accordion>
495
+
496
+ <p>Wraps the browser's <a href="https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition" target="_blank">Web Speech API</a> in a single microphone button. Click the button to start listening; the browser stops automatically when the user pauses (or click again to stop manually). Requires a secure context (HTTPS or <code>localhost</code>) and a Chromium-based browser at the time of writing.</p>
497
+
498
+ <h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
499
+ <p>The simplest setup &mdash; click the mic, speak, and the recognized text appears in the paragraph when you stop. The <code>end</code> event fires once with the full transcript.</p>
500
+ <div class="row -mx">
501
+ <div class="col m-span-12 px">
502
+ <k-card label="HTML">
503
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;basicSpeech&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;basicSpeechOutput&quot;</span>&gt;</span>(say something...)<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"><br> <span class="hljs-keyword">const</span> $stt = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;basicSpeech&#x27;</span>);<br> <span class="hljs-keyword">const</span> $out = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;basicSpeechOutput&#x27;</span>);<br> $stt.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">&#x27;end&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {<br> $out.<span class="hljs-property">textContent</span> = e.<span class="hljs-property">detail</span>.<span class="hljs-property">text</span> || <span class="hljs-string">&#x27;(nothing heard)&#x27;</span>;<br> });<br></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre>
504
+ </k-card>
505
+ </div>
506
+ <div class="col m-span-12 px">
507
+ <k-card label="Output">
508
+ <k-speech-to-text id="basicSpeech"></k-speech-to-text>
509
+ <p id="basicSpeechOutput" class="mt">(say something...)</p>
510
+ <script>
511
+ const $stt = document.getElementById('basicSpeech');
512
+ const $out = document.getElementById('basicSpeechOutput');
513
+ $stt.addEventListener('end', (e) => {
514
+ $out.textContent = e.detail.text || '(nothing heard)';
515
+ });
516
+ </script>
517
+ </k-card>
518
+ </div>
519
+ </div>
520
+
521
+ <h3 id="liveTranscript"><a href="#liveTranscript" class="no-link">Live Transcript</a></h3>
522
+ <p>Add the <code>interim</code> attribute and listen for the <code>result</code> event to update the paragraph as the user speaks. <code>detail.isFinal</code> indicates whether the chunk is finalized.</p>
523
+ <div class="row -mx">
524
+ <div class="col m-span-12 px">
525
+ <k-card label="HTML">
526
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;liveSpeech&quot;</span> <span class="hljs-attr">interim</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;liveSpeechOutput&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"><br> <span class="hljs-keyword">const</span> $stt = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;liveSpeech&#x27;</span>);<br> <span class="hljs-keyword">const</span> $out = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;liveSpeechOutput&#x27;</span>);<br> $stt.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">&#x27;result&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {<br> $out.<span class="hljs-property">textContent</span> = e.<span class="hljs-property">detail</span>.<span class="hljs-property">text</span>;<br> });<br></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></code></pre>
527
+ </k-card>
528
+ </div>
529
+ <div class="col m-span-12 px">
530
+ <k-card label="Output">
531
+ <k-speech-to-text id="liveSpeech" interim></k-speech-to-text>
532
+ <p id="liveSpeechOutput" class="mt">&nbsp;</p>
533
+ <script>
534
+ const $sttLive = document.getElementById('liveSpeech');
535
+ const $outLive = document.getElementById('liveSpeechOutput');
536
+ $sttLive.addEventListener('result', (e) => {
537
+ $outLive.textContent = e.detail.text;
538
+ });
539
+ </script>
540
+ </k-card>
541
+ </div>
542
+ </div>
543
+
544
+ <h3 id="continuous"><a href="#continuous" class="no-link">Continuous</a></h3>
545
+ <p>By default the recognizer stops automatically after a brief pause. Add <code>continuous</code> so it keeps listening until the user clicks the button a second time.</p>
546
+ <div class="row -mx">
547
+ <div class="col m-span-12 px">
548
+ <k-card label="HTML">
549
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">continuous</span> <span class="hljs-attr">interim</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;contSpeech&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;contSpeechOutput&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></code></pre>
550
+ </k-card>
551
+ </div>
552
+ <div class="col m-span-12 px">
553
+ <k-card label="Output">
554
+ <k-speech-to-text id="contSpeech" continuous interim></k-speech-to-text>
555
+ <p id="contSpeechOutput" class="mt">&nbsp;</p>
556
+ <script>
557
+ const $sttCont = document.getElementById('contSpeech');
558
+ const $outCont = document.getElementById('contSpeechOutput');
559
+ $sttCont.addEventListener('result', (e) => {
560
+ $outCont.textContent = e.detail.text;
561
+ });
562
+ </script>
563
+ </k-card>
564
+ </div>
565
+ </div>
566
+
567
+ <h3 id="language"><a href="#language" class="no-link">Language</a></h3>
568
+ <p>Set the recognition <code>language</code> using a BCP&#x2011;47 tag (e.g. <code>"es-ES"</code>, <code>"fr-FR"</code>, <code>"de-DE"</code>). Defaults to <code>"en-US"</code>.</p>
569
+ <div class="row -mx">
570
+ <div class="col m-span-12 px">
571
+ <k-card label="HTML">
572
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">language</span>=<span class="hljs-string">&quot;es-ES&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span></code></pre>
573
+ </k-card>
574
+ </div>
575
+ <div class="col m-span-12 px">
576
+ <k-card label="Output">
577
+ <k-speech-to-text language="es-ES"></k-speech-to-text>
578
+ </k-card>
579
+ </div>
580
+ </div>
581
+
582
+ <h3 id="minConfidence"><a href="#minConfidence" class="no-link">Min Confidence</a></h3>
583
+ <p>Set <code>min-confidence</code> to a number between <code>0</code> and <code>1</code> to drop low-confidence transcripts. Chrome's recognizer reports a confidence score on each finalized result; values below your threshold are skipped (they don't accumulate into <code>end.detail.text</code>). Interim chunks usually have <code>confidence === 0</code> in Chrome, so any positive threshold also filters those out &mdash; useful when you want to ignore background noise or ambient audio. Default is <code>0</code> (no filtering).</p>
584
+ <div class="row -mx">
585
+ <div class="col m-span-12 px">
586
+ <k-card label="HTML">
587
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;confSpeech&quot;</span> <span class="hljs-attr">min-confidence</span>=<span class="hljs-string">&quot;0.7&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;confSpeechOutput&quot;</span>&gt;</span>(only confident speech...)<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></code></pre>
588
+ </k-card>
589
+ </div>
590
+ <div class="col m-span-12 px">
591
+ <k-card label="Output">
592
+ <k-speech-to-text id="confSpeech" min-confidence="0.7"></k-speech-to-text>
593
+ <p id="confSpeechOutput" class="mt">(only confident speech...)</p>
594
+ <script>
595
+ const $sttConf = document.getElementById('confSpeech');
596
+ const $outConf = document.getElementById('confSpeechOutput');
597
+ $sttConf.addEventListener('end', (e) => {
598
+ $outConf.textContent = e.detail.text || '(no high-confidence speech detected)';
599
+ });
600
+ </script>
601
+ </k-card>
602
+ </div>
603
+ </div>
604
+
605
+ <h3 id="timeout"><a href="#timeout" class="no-link">Timeout</a></h3>
606
+ <p>Set <code>timeout</code> to the maximum number of seconds the component should listen before stopping itself. The recognition stops automatically and the <code>end</code> event fires with whatever transcript was captured. Default is <code>0</code> (no timeout &mdash; recognition runs until the user stops, or the browser auto-stops on a pause when <code>continuous</code> is unset).</p>
607
+ <div class="row -mx">
608
+ <div class="col m-span-12 px">
609
+ <k-card label="HTML">
610
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;timeoutSpeech&quot;</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">&quot;5&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;timeoutSpeechOutput&quot;</span>&gt;</span>(stops after 5 seconds...)<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></code></pre>
611
+ </k-card>
612
+ </div>
613
+ <div class="col m-span-12 px">
614
+ <k-card label="Output">
615
+ <k-speech-to-text id="timeoutSpeech" timeout="5" continuous interim></k-speech-to-text>
616
+ <p id="timeoutSpeechOutput" class="mt">(stops after 5 seconds...)</p>
617
+ <script>
618
+ const $sttTimeout = document.getElementById('timeoutSpeech');
619
+ const $outTimeout = document.getElementById('timeoutSpeechOutput');
620
+ $sttTimeout.addEventListener('result', (e) => {
621
+ $outTimeout.textContent = e.detail.text;
622
+ });
623
+ $sttTimeout.addEventListener('end', (e) => {
624
+ if(!e.detail.text) $outTimeout.textContent = '(no speech captured)';
625
+ });
626
+ </script>
627
+ </k-card>
628
+ </div>
629
+ </div>
630
+
631
+ <h3 id="disabled"><a href="#disabled" class="no-link">Disabled</a></h3>
632
+ <p>The <code>disabled</code> attribute prevents user interaction. The button also auto-disables when the browser doesn't support the Web Speech API.</p>
633
+ <div class="row -mx">
634
+ <div class="col m-span-12 px">
635
+ <k-card label="HTML">
636
+ <pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">k-speech-to-text</span> <span class="hljs-attr">disabled</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">k-speech-to-text</span>&gt;</span></code></pre>
637
+ </k-card>
638
+ </div>
639
+ <div class="col m-span-12 px">
640
+ <k-card label="Output">
641
+ <k-speech-to-text disabled></k-speech-to-text>
642
+ </k-card>
643
+ </div>
644
+ </div>
645
+
646
+ <h2 id="jsRef"><a href="#jsRef" class="no-link">JavaScript Reference</a></h2>
647
+
648
+ <h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
649
+ <h6>Extends <a href="./shadow-component.html">ShadowComponent</a></h6>
650
+ <h5><code>new SpeechToText()</code></h5>
651
+
652
+ <h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
653
+ <ul>
654
+ <li><a href="./shadow-component.html">ShadowComponent</a></li>
655
+ <li>A browser that supports <code>SpeechRecognition</code> (Chrome, Edge, Safari 14.1+, etc.) served over HTTPS or <code>localhost</code></li>
656
+ </ul>
657
+
658
+ <h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
659
+ <h5><code>language<i>: String</i></code></h5>
660
+ <p>BCP&#x2011;47 language tag passed to the underlying <code>SpeechRecognition.lang</code> (e.g. <code>"en-US"</code>, <code>"es-ES"</code>). Default is <code>"en-US"</code>. Syncs to <code>language</code> attribute.</p>
661
+
662
+ <h5><code>continuous<i>: Boolean</i></code></h5>
663
+ <p>When <code>true</code>, recognition keeps listening past pauses until <code>stop()</code> is called. Default is <code>false</code>. Syncs to <code>continuous</code> attribute.</p>
664
+
665
+ <h5><code>interim<i>: Boolean</i></code></h5>
666
+ <p>When <code>true</code>, the recognizer emits unfinalized results as the user speaks (the <code>result</code> event fires for interim chunks too). Note that the underlying <code>SpeechRecognition.interimResults</code> is always <code>true</code> internally so the <code>end</code> event has a fallback transcript when the engine doesn't finalize; this attribute only controls public <code>result</code> dispatching. Default is <code>false</code>. Syncs to <code>interim</code> attribute.</p>
667
+
668
+ <h5><code>minConfidence<i>: Number</i></code></h5>
669
+ <p>A floor (<code>0</code>&ndash;<code>1</code>) on the confidence score Chrome reports for each result. Anything below the threshold is dropped. Useful for ignoring background noise: at <code>0.7</code> you'll only capture speech the engine is confident about. Default is <code>0</code> (accept everything). Syncs to <code>min-confidence</code> attribute.</p>
670
+
671
+ <h5><code>timeout<i>: Number</i></code></h5>
672
+ <p>Maximum recording duration in seconds. When non-zero, the component automatically calls <code>stop()</code> after this many seconds, firing the <code>end</code> event with the captured transcript. Default is <code>0</code> (no timeout). Syncs to <code>timeout</code> attribute.</p>
673
+
674
+ <h5><code>disabled<i>: Boolean</i></code></h5>
675
+ <p>When <code>true</code>, the button cannot be clicked. Syncs to <code>disabled</code> attribute.</p>
676
+
677
+ <h5><code>listening<i>: Boolean</i></code></h5>
678
+ <p>Read-only-ish state that reflects whether recognition is active. The button shows a pulsing red state while listening. Syncs to <code>listening</code> attribute.</p>
679
+
680
+ <h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
681
+ <h5><code>start()<i>: void</i></code></h5>
682
+ <p>Begin listening. No-op if already listening, disabled, or unsupported.</p>
683
+
684
+ <h5><code>stop()<i>: void</i></code></h5>
685
+ <p>Stop listening and finalize the transcript.</p>
686
+
687
+ <h5><code>toggle()<i>: void</i></code></h5>
688
+ <p>Calls <code>start()</code> if idle, <code>stop()</code> if currently listening &mdash; the same behavior as clicking the button.</p>
689
+
690
+ <h3 id="cssVariables"><a href="#cssVariables" class="no-link">CSS Variables</a></h3>
691
+ <table class="b">
692
+ <thead><tr><th>Variable</th><th>Default</th><th>Description</th></tr></thead>
693
+ <tbody>
694
+ <tr><td><code>--btn_size</code></td><td><code>2.5rem</code></td><td>Diameter of the microphone button</td></tr>
695
+ <tr><td><code>--btn_bg</code></td><td><code>var(--c_bg)</code></td><td>Background of the idle button</td></tr>
696
+ <tr><td><code>--btn_bg__listening</code></td><td><code>var(--c_danger, #d32f2f)</code></td><td>Background while actively listening</td></tr>
697
+ <tr><td><code>--btn_tc__listening</code></td><td><code>white</code></td><td>Icon color while listening</td></tr>
698
+ </tbody>
699
+ </table>
700
+
701
+ <h3 id="events"><a href="#events" class="no-link">Events</a></h3>
702
+ <h5><code>start</code></h5>
703
+ <p>Fires when recognition begins.</p>
704
+
705
+ <h5><code>result</code></h5>
706
+ <p>Fires for each recognized chunk. <code>detail</code> contains <code>{ text: String, isFinal: Boolean }</code>. With <code>interim</code> enabled, this fires repeatedly as the user speaks.</p>
707
+
708
+ <h5><code>end</code></h5>
709
+ <p>Fires when recognition stops (auto pause, manual stop, or error). <code>detail</code> contains <code>{ text: String }</code> &mdash; the full final transcript.</p>
710
+
711
+ <h5><code>error</code></h5>
712
+ <p>Fires when the underlying <code>SpeechRecognition</code> reports an error. <code>detail</code> contains <code>{ error: String, message: String }</code>.</p>
713
+
714
+ </k-main>
715
+ <div style="height:33vh"></div>
716
+ <script type="module" src="../src/components/Main.js"></script>
717
+
718
+ <script type="module" src="../src/components/SpeechToText.js"></script>
719
+ <script type="module" src="../src/components/Icon.js"></script>
720
+ <script type="module" src="../src/components/Accordion.js"></script>
721
+ <script type="module" src="../src/components/Card.js"></script>
722
+
723
+ </body>
724
+ </html>