@k2b/ui 0.40.0 → 0.41.0

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 (88) hide show
  1. package/dist/browser/chat/ChatComposer.js +759 -570
  2. package/dist/browser/chat/ChatComposer.js.map +1 -1
  3. package/dist/browser/inputs/ChoiceGroups.js +30 -18
  4. package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
  5. package/dist/browser/inputs/Select.js +32 -19
  6. package/dist/browser/inputs/Select.js.map +1 -1
  7. package/dist/browser/inputs/SpecialInputs.js +54 -25
  8. package/dist/browser/inputs/SpecialInputs.js.map +1 -1
  9. package/dist/browser/inputs/choice.js +4 -1
  10. package/dist/browser/inputs/choice.js.map +1 -1
  11. package/dist/browser/inputs/dictation/Dictation.js +546 -0
  12. package/dist/browser/inputs/dictation/Dictation.js.map +1 -0
  13. package/dist/browser/inputs/dictation/create-dictation.js +324 -0
  14. package/dist/browser/inputs/dictation/create-dictation.js.map +1 -0
  15. package/dist/browser/inputs/dictation/dictation-messages.js +115 -0
  16. package/dist/browser/inputs/dictation/dictation-messages.js.map +1 -0
  17. package/dist/browser/inputs/dictation/text-dictation.js +152 -0
  18. package/dist/browser/inputs/dictation/text-dictation.js.map +1 -0
  19. package/dist/browser/inputs/dictation/types.js +2 -0
  20. package/dist/browser/inputs/dictation/types.js.map +1 -0
  21. package/dist/browser/inputs/icon-messages.js +29 -2
  22. package/dist/browser/inputs/icon-messages.js.map +1 -1
  23. package/dist/browser/inputs/icon-texts.js +172 -0
  24. package/dist/browser/inputs/icon-texts.js.map +1 -0
  25. package/dist/browser/inputs/index.js +2 -0
  26. package/dist/browser/inputs/index.js.map +1 -1
  27. package/dist/browser/layout/AnchoredPopover.js +1 -1
  28. package/dist/browser/layout/AnchoredPopover.js.map +1 -1
  29. package/dist/browser/layout/SettingsModal.js +10 -5
  30. package/dist/browser/layout/SettingsModal.js.map +1 -1
  31. package/dist/browser/text-editor/TextEditor.js +74 -25
  32. package/dist/browser/text-editor/TextEditor.js.map +1 -1
  33. package/dist/browser/text-editor/dictation.js +166 -0
  34. package/dist/browser/text-editor/dictation.js.map +1 -0
  35. package/dist/browser/text-editor.js +1 -0
  36. package/dist/browser/text-editor.js.map +1 -1
  37. package/dist/ssr/chat/ChatComposer.js +271 -99
  38. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  39. package/dist/ssr/inputs/ChoiceGroups.js +12 -3
  40. package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
  41. package/dist/ssr/inputs/Select.js +8 -2
  42. package/dist/ssr/inputs/Select.js.map +1 -1
  43. package/dist/ssr/inputs/SpecialInputs.js +54 -25
  44. package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
  45. package/dist/ssr/inputs/choice.js +4 -1
  46. package/dist/ssr/inputs/choice.js.map +1 -1
  47. package/dist/ssr/inputs/dictation/Dictation.js +386 -0
  48. package/dist/ssr/inputs/dictation/Dictation.js.map +1 -0
  49. package/dist/ssr/inputs/dictation/create-dictation.js +324 -0
  50. package/dist/ssr/inputs/dictation/create-dictation.js.map +1 -0
  51. package/dist/ssr/inputs/dictation/dictation-messages.js +115 -0
  52. package/dist/ssr/inputs/dictation/dictation-messages.js.map +1 -0
  53. package/dist/ssr/inputs/dictation/text-dictation.js +152 -0
  54. package/dist/ssr/inputs/dictation/text-dictation.js.map +1 -0
  55. package/dist/ssr/inputs/dictation/types.js +2 -0
  56. package/dist/ssr/inputs/dictation/types.js.map +1 -0
  57. package/dist/ssr/inputs/icon-messages.js +29 -2
  58. package/dist/ssr/inputs/icon-messages.js.map +1 -1
  59. package/dist/ssr/inputs/icon-texts.js +172 -0
  60. package/dist/ssr/inputs/icon-texts.js.map +1 -0
  61. package/dist/ssr/inputs/index.js +2 -0
  62. package/dist/ssr/inputs/index.js.map +1 -1
  63. package/dist/ssr/layout/AnchoredPopover.js +1 -1
  64. package/dist/ssr/layout/AnchoredPopover.js.map +1 -1
  65. package/dist/ssr/layout/SettingsModal.js +10 -5
  66. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  67. package/dist/ssr/text-editor/TextEditor.js +74 -25
  68. package/dist/ssr/text-editor/TextEditor.js.map +1 -1
  69. package/dist/ssr/text-editor/dictation.js +166 -0
  70. package/dist/ssr/text-editor/dictation.js.map +1 -0
  71. package/dist/ssr/text-editor.js +1 -0
  72. package/dist/ssr/text-editor.js.map +1 -1
  73. package/dist/styles.css +1 -1
  74. package/dist/types/chat/ChatComposer.d.ts +9 -0
  75. package/dist/types/inputs/SpecialInputs.d.ts +8 -0
  76. package/dist/types/inputs/dictation/Dictation.d.ts +26 -0
  77. package/dist/types/inputs/dictation/create-dictation.d.ts +77 -0
  78. package/dist/types/inputs/dictation/dictation-messages.d.ts +54 -0
  79. package/dist/types/inputs/dictation/text-dictation.d.ts +36 -0
  80. package/dist/types/inputs/dictation/types.d.ts +74 -0
  81. package/dist/types/inputs/icon-messages.d.ts +14 -0
  82. package/dist/types/inputs/icon-texts.d.ts +13 -0
  83. package/dist/types/inputs/index.d.ts +5 -0
  84. package/dist/types/layout/AnchoredPopover.d.ts +5 -0
  85. package/dist/types/text-editor/TextEditor.d.ts +10 -1
  86. package/dist/types/text-editor/dictation.d.ts +20 -0
  87. package/dist/types/text-editor.d.ts +1 -0
  88. package/package.json +1 -1
@@ -0,0 +1,386 @@
1
+ import { ssrStyleProperty as _$ssrStyleProperty } from "solid-js/web";
2
+ import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
3
+ import { escape as _$escape } from "solid-js/web";
4
+ import { createComponent as _$createComponent } from "solid-js/web";
5
+ import { ssr as _$ssr } from "solid-js/web";
6
+ import { memo as _$memo } from "solid-js/web";
7
+ var _tmpl$ = ["<i class=\"", "\" aria-hidden=\"true\"></i>"],
8
+ _tmpl$2 = ["<p>", "</p>"],
9
+ _tmpl$3 = ["<ol><li>", "</li><li>", "</li></ol>"],
10
+ _tmpl$4 = ["<h3 class=\"k2b-dictation-card__title\"><i class=\"", "\" aria-hidden=\"true\"></i>", "</h3>"],
11
+ _tmpl$5 = ["<div class=\"k2b-dictation-card__body\">", "</div>"],
12
+ _tmpl$6 = ["<div class=\"k2b-dictation-card__actions\">", "", "</div>"],
13
+ _tmpl$7 = "<i class=\"ti ti-x\" aria-hidden=\"true\"></i>",
14
+ _tmpl$8 = ["<div class=\"k2b-dictation-bar__row\" data-state=\"finishing\" role=\"group\"", ">", "<div class=\"k2b-dictation-bar__status\" role=\"status\"><i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\"></i><span class=\"k2b-dictation-bar__message\">", "</span></div><span class=\"k2b-dictation-bar__time\">", "</span><span class=\"k2b-dictation-bar__stop\" data-disabled=\"true\" aria-hidden=\"true\"><span></span></span></div>"],
15
+ _tmpl$9 = ["<span class=\"k2b-dictation-bar__device-name\">", "</span>"],
16
+ _tmpl$0 = "<i class=\"ti ti-chevron-down k2b-dictation-bar__device-chevron\" aria-hidden=\"true\"></i>",
17
+ _tmpl$1 = ["<div class=\"k2b-dictation-bar__row\"", " role=\"group\"", ">", "<span class=\"k2b-dictation-bar__dot\"", " aria-hidden=\"true\"></span><div class=\"k2b-dictation-bar__wave\" aria-hidden=\"true\">", "</div><span class=\"k2b-dictation-bar__time\"", ">", "</span>", "<button type=\"button\" class=\"k2b-dictation-bar__stop\"", "><span aria-hidden=\"true\"></span></button></div>"],
18
+ _tmpl$10 = ["<div class=\"", "\">", "</div>"],
19
+ _tmpl$11 = ["<span style=\"", "\"></span>"],
20
+ _tmpl$12 = ["<div class=\"k2b-dictation-bar__row\" data-state=\"notice\"><div class=\"k2b-dictation-bar__status\"", " role=\"status\"><i class=\"", "\" aria-hidden=\"true\"></i><span class=\"k2b-sr-only\">", "</span><span class=\"k2b-dictation-bar__message k2b-dictation-bar__message--long\" aria-hidden=\"true\">", "</span><span class=\"k2b-dictation-bar__message k2b-dictation-bar__message--short\" aria-hidden=\"true\">", "</span></div>", "", "</div>"];
21
+ import { createEffect, createSignal, Index, Match, onCleanup, Show, Switch } from "solid-js";
22
+ import { Button, IconButton } from "../../actions/Button";
23
+ import { Dropdown } from "../../actions/Dropdown";
24
+ import { useLocale } from "../../intl/locale";
25
+ import { AnchoredPopover } from "../../layout/AnchoredPopover";
26
+ import { isBarNotice } from "./create-dictation";
27
+ import { dictationMessages } from "./dictation-messages";
28
+ const useDictationMessages = () => {
29
+ const locale = useLocale();
30
+ return () => dictationMessages.resolve([locale()]).t;
31
+ };
32
+
33
+ /** Whether the bar stands in for the host's controls: while dictating, finishing, or showing a bar notice. */
34
+ export const dictationBarShown = dictation => dictation.active() || isBarNotice(dictation.notice());
35
+ const clock = ms => {
36
+ const seconds = Math.max(0, Math.floor(ms / 1000));
37
+ return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, "0")}`;
38
+ };
39
+
40
+ /** The quiet countdown starts one minute before the end. */
41
+ const warnMs = 60_000;
42
+ const deviceIcon = device => {
43
+ const label = device?.label ?? "";
44
+ if (/airpods|buds|headset|headphone|kopfhörer/i.test(label)) return "ti-headphones";
45
+ if (/iphone|android|phone|handy|mobile/i.test(label)) return "ti-device-mobile";
46
+ if (/macbook|laptop|built-in|internal|intern/i.test(label) || !label) return "ti-device-laptop";
47
+ return "ti-microphone";
48
+ };
49
+ /**
50
+ * The microphone at its fixed place. A press starts live dictation; offline it stays focusable and says why it waits.
51
+ * Notices that need a decision, such as a blocked microphone or a used-up allowance, open as cards above it.
52
+ */
53
+ export function DictationButton(props) {
54
+ const t = useDictationMessages();
55
+ const [button, setButton] = createSignal();
56
+ const card = () => {
57
+ const notice = props.dictation.notice();
58
+ return notice && !isBarNotice(notice) ? notice : null;
59
+ };
60
+ createEffect(() => props.dictation.bind("microphone", button()));
61
+ onCleanup(() => props.dictation.bind("microphone", undefined));
62
+ return [_$createComponent(IconButton, {
63
+ get size() {
64
+ return props.size ?? "sm";
65
+ },
66
+ get ["class"]() {
67
+ return `k2b-dictation-button ${props.class ?? ""}`;
68
+ },
69
+ get label() {
70
+ return _$memo(() => !!props.dictation.offline())() ? t().dictateOffline : t().dictate;
71
+ },
72
+ get tooltip() {
73
+ return _$memo(() => !!props.dictation.offline())() ? t().offline : t().dictate;
74
+ },
75
+ get ["aria-pressed"]() {
76
+ return props.dictation.active() ? "true" : "false";
77
+ },
78
+ get ["aria-disabled"]() {
79
+ return props.dictation.offline() || !props.dictation.active() && props.dictation.disabled() ? "true" : undefined;
80
+ },
81
+ get ["data-notice"]() {
82
+ return card()?.kind;
83
+ },
84
+ onClick: () => {
85
+ if (props.dictation.offline() || !props.dictation.active() && props.dictation.disabled()) return;
86
+ if (props.dictation.active()) void props.dictation.stop();else props.dictation.start();
87
+ },
88
+ get children() {
89
+ return _$ssr(_tmpl$, `ti ${card()?.kind === "blocked" ? "ti-microphone-off" : "ti-microphone"}`);
90
+ }
91
+ }), _$createComponent(Show, {
92
+ get when() {
93
+ return card();
94
+ },
95
+ children: notice => _$createComponent(DictationCard, {
96
+ get dictation() {
97
+ return props.dictation;
98
+ },
99
+ get notice() {
100
+ return notice();
101
+ },
102
+ get anchor() {
103
+ return props.cardAnchor?.() ?? button();
104
+ }
105
+ })
106
+ })];
107
+ }
108
+ function DictationCard(props) {
109
+ const t = useDictationMessages();
110
+ const locale = useLocale();
111
+ const resetTime = () => {
112
+ const notice = props.notice;
113
+ const at = notice.kind === "quota" && notice.resetsAt ? new Date(notice.resetsAt) : null;
114
+ const time = (at ?? new Date(new Date().setHours(24, 0, 0, 0))).toLocaleTimeString(locale(), {
115
+ hour: "2-digit",
116
+ minute: "2-digit"
117
+ });
118
+ const today = new Date();
119
+ const tomorrow = !at || at.toDateString() !== today.toDateString();
120
+ return tomorrow ? t().quotaBodyTomorrow({
121
+ time
122
+ }) : t().quotaBody({
123
+ time
124
+ });
125
+ };
126
+ const content = () => {
127
+ switch (props.notice.kind) {
128
+ case "blocked":
129
+ return {
130
+ icon: "ti-microphone-off",
131
+ title: t().blockedTitle,
132
+ body: [_$ssr(_tmpl$2, _$escape(t().blockedBody)), _$ssr(_tmpl$3, _$escape(t().blockedStep1), _$escape(t().blockedStep2))],
133
+ retry: true
134
+ };
135
+ case "quota":
136
+ return {
137
+ icon: "ti-hourglass",
138
+ title: t().quotaTitle,
139
+ body: _$ssr(_tmpl$2, _$escape(resetTime())),
140
+ retry: false
141
+ };
142
+ case "overloaded":
143
+ return {
144
+ icon: "ti-hourglass",
145
+ title: t().overloadedTitle,
146
+ body: _$ssr(_tmpl$2, _$escape(props.dictation.alternative?.note ?? t().overloadedBody)),
147
+ retry: true
148
+ };
149
+ case "elsewhere":
150
+ return {
151
+ icon: "ti-microphone",
152
+ title: t().elsewhereTitle,
153
+ body: _$ssr(_tmpl$2, _$escape(t().elsewhereBody)),
154
+ retry: false
155
+ };
156
+ case "unavailable":
157
+ return {
158
+ icon: "ti-microphone-off",
159
+ title: t().unavailableTitle,
160
+ body: _$ssr(_tmpl$2, _$escape(t().unavailableBody)),
161
+ retry: true
162
+ };
163
+ default:
164
+ return {
165
+ icon: "ti-microphone-off",
166
+ title: t().notAvailableTitle,
167
+ body: _$ssr(_tmpl$2, _$escape(t().notAvailableBody)),
168
+ retry: false
169
+ };
170
+ }
171
+ };
172
+ return _$createComponent(AnchoredPopover, {
173
+ get anchor() {
174
+ return props.anchor;
175
+ },
176
+ onClose: () => props.dictation.dismiss(),
177
+ get label() {
178
+ return content().title;
179
+ },
180
+ side: "above",
181
+ align: "end",
182
+ width: "20rem",
183
+ sheet: false,
184
+ "class": "k2b-dictation-card",
185
+ get children() {
186
+ return [_$ssr(_tmpl$4, `ti ${_$escape(content().icon, true)}`, _$escape(content().title)), _$ssr(_tmpl$5, _$escape(content().body)), _$ssr(_tmpl$6, _$escape(_$createComponent(Show, {
187
+ get when() {
188
+ return _$memo(() => props.notice.kind === "overloaded")() ? props.dictation.alternative : undefined;
189
+ },
190
+ children: alternative => _$createComponent(Button, {
191
+ size: "sm",
192
+ variant: "ghost",
193
+ onClick: () => {
194
+ props.dictation.dismiss();
195
+ alternative().run();
196
+ },
197
+ get children() {
198
+ return alternative().label;
199
+ }
200
+ })
201
+ })), _$escape(_$createComponent(Show, {
202
+ get when() {
203
+ return content().retry;
204
+ },
205
+ get fallback() {
206
+ return _$createComponent(Button, {
207
+ size: "sm",
208
+ variant: "ghost",
209
+ get ["class"]() {
210
+ return props.notice.kind === "elsewhere" ? "k2b-dictation-card__primary" : undefined;
211
+ },
212
+ onClick: () => props.dictation.dismiss(),
213
+ get children() {
214
+ return t().ok;
215
+ }
216
+ });
217
+ },
218
+ get children() {
219
+ return _$createComponent(Button, {
220
+ size: "sm",
221
+ variant: "ghost",
222
+ "class": "k2b-dictation-card__primary",
223
+ onClick: () => props.dictation.start(),
224
+ get children() {
225
+ return t().retry;
226
+ }
227
+ });
228
+ }
229
+ })))];
230
+ }
231
+ });
232
+ }
233
+ /**
234
+ * The row that stands in for the host's controls while dictating, at the same place and height: Discard, level, time,
235
+ * microphone and Stop; then "Finishing …" until the last words arrived; and a notice with "Continue" when the session
236
+ * ended early. Render it where `dictationBarShown()` is true. Escape stops, after closing an open menu.
237
+ */
238
+ export function DictationBar(props) {
239
+ const t = useDictationMessages();
240
+ const status = () => props.dictation.status();
241
+ const remaining = () => props.dictation.maxMs() - props.dictation.elapsedMs();
242
+ const warning = () => status() === "live" && remaining() <= warnMs;
243
+ const time = () => warning() ? t().timeLeft({
244
+ time: clock(remaining())
245
+ }) : clock(props.dictation.elapsedMs());
246
+ const slots = 160;
247
+ const bars = () => {
248
+ const levels = props.dictation.levels();
249
+ return Array.from({
250
+ length: slots
251
+ }, (_, index) => levels[levels.length - slots + index] ?? 0);
252
+ };
253
+ const deviceLabel = () => props.dictation.device()?.label || t().microphone;
254
+ const onKey = event => {
255
+ if (event.key !== "Escape" || event.defaultPrevented || status() !== "live") return;
256
+ event.preventDefault();
257
+ void props.dictation.stop();
258
+ };
259
+ createEffect(() => {
260
+ if (status() !== "live") return;
261
+ document.addEventListener("keydown", onKey);
262
+ onCleanup(() => document.removeEventListener("keydown", onKey));
263
+ });
264
+ const bindStop = element => {
265
+ props.dictation.bind("stop", element);
266
+ onCleanup(() => props.dictation.bind("stop", undefined));
267
+ };
268
+ const bindContinue = element => {
269
+ props.dictation.bind("continue", element);
270
+ onCleanup(() => props.dictation.bind("continue", undefined));
271
+ };
272
+ const deviceItems = () => [{
273
+ sectionLabel: t().microphone,
274
+ items: (props.dictation.devices().length ? props.dictation.devices() : props.dictation.device() ? [props.dictation.device()] : []).map(device => ({
275
+ choice: "radio",
276
+ icon: `ti ${deviceIcon(device)}`,
277
+ label: device.id === "default" ? `${device.label || t().microphone} · ${t().systemDefault}` : device.label || t().microphone,
278
+ checked: () => (props.dictation.deviceId() ?? props.dictation.device()?.id) === device.id,
279
+ action: () => props.dictation.chooseDevice(device.id)
280
+ }))
281
+ }];
282
+ return _$ssr(_tmpl$10, `k2b-dictation-bar ${_$escape(props.class ?? "", true)}`, _$escape(_$createComponent(Switch, {
283
+ get children() {
284
+ return [_$createComponent(Match, {
285
+ get when() {
286
+ return status() === "finishing";
287
+ },
288
+ get children() {
289
+ return _$ssr(_tmpl$8, _$ssrAttribute("aria-label", _$escape(t().finishingGroup, true), false), _$escape(_$createComponent(IconButton, {
290
+ size: "sm",
291
+ get label() {
292
+ return t().discard;
293
+ },
294
+ "aria-disabled": "true",
295
+ "class": "k2b-dictation-bar__icon",
296
+ get children() {
297
+ return _$ssr(_tmpl$7);
298
+ }
299
+ })), _$escape(t().finishing), _$escape(clock(props.dictation.elapsedMs())));
300
+ }
301
+ }), _$createComponent(Match, {
302
+ get when() {
303
+ return status() === "live" || status() === "starting";
304
+ },
305
+ get children() {
306
+ return _$ssr(_tmpl$1, _$ssrAttribute("data-state", _$escape(status(), true), false), _$ssrAttribute("aria-label", _$escape(t().running, true), false), _$escape(_$createComponent(IconButton, {
307
+ size: "sm",
308
+ get label() {
309
+ return t().discard;
310
+ },
311
+ "class": "k2b-dictation-bar__icon",
312
+ onClick: () => props.dictation.discard(),
313
+ get children() {
314
+ return _$ssr(_tmpl$7);
315
+ }
316
+ })), _$ssrAttribute("data-live", status() === "live" ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Index, {
317
+ get each() {
318
+ return bars();
319
+ },
320
+ children: level => _$ssr(_tmpl$11, _$ssrStyleProperty("--k2b-dictation-level:", _$escape(String(0.1 + level() * 0.9), true)))
321
+ })), _$ssrAttribute("data-warning", warning() ? "true" : _$escape(undefined, true), false), status() === "starting" ? _$escape(clock(0)) : _$escape(time()), _$escape(_$createComponent(Dropdown, {
322
+ get items() {
323
+ return deviceItems();
324
+ },
325
+ position: "top-left",
326
+ width: "16.25rem",
327
+ onOpenChange: open => {
328
+ if (open) void props.dictation.loadDevices();
329
+ },
330
+ get children() {
331
+ return _$createComponent(Dropdown.Trigger, {
332
+ appearance: "plain",
333
+ "class": "k2b-dictation-bar__device",
334
+ get label() {
335
+ return t().microphoneNamed({
336
+ name: deviceLabel()
337
+ });
338
+ },
339
+ get children() {
340
+ return [_$ssr(_tmpl$, `ti ${_$escape(deviceIcon(props.dictation.device()), true)}`), _$ssr(_tmpl$9, _$escape(deviceLabel())), _$ssr(_tmpl$0)];
341
+ }
342
+ });
343
+ }
344
+ })), _$ssrAttribute("aria-label", _$escape(t().stop, true), false) + _$ssrAttribute("title", _$escape(t().stop, true), false));
345
+ }
346
+ }), _$createComponent(Match, {
347
+ get when() {
348
+ return _$memo(() => !!isBarNotice(props.dictation.notice()))() ? props.dictation.notice() : undefined;
349
+ },
350
+ children: notice => {
351
+ const ended = () => {
352
+ const value = notice();
353
+ return value.kind === "ended" ? value : undefined;
354
+ };
355
+ const minutes = () => Math.round((ended()?.maxMs ?? 600_000) / 60_000);
356
+ const long = () => !ended() ? t().interrupted : ended().reason === "silence" ? t().silenceDone : t().maxDone({
357
+ minutes: minutes()
358
+ });
359
+ const short = () => !ended() ? t().interruptedShort : ended().reason === "silence" ? t().silenceDoneShort : t().maxDoneShort({
360
+ minutes: minutes()
361
+ });
362
+ return _$ssr(_tmpl$12, _$ssrAttribute("data-tone", ended() ? _$escape(undefined, true) : "danger", false), `ti ${ended() ? "ti-clock" : "ti-alert-circle"}`, _$escape(long()), _$escape(long()), _$escape(short()), _$escape(_$createComponent(Button, {
363
+ size: "sm",
364
+ variant: "ghost",
365
+ "class": "k2b-dictation-bar__continue",
366
+ onClick: () => props.dictation.start(),
367
+ get children() {
368
+ return t().continue;
369
+ }
370
+ })), _$escape(_$createComponent(IconButton, {
371
+ size: "sm",
372
+ get label() {
373
+ return t().dismiss;
374
+ },
375
+ "class": "k2b-dictation-bar__icon",
376
+ onClick: () => props.dictation.dismiss(),
377
+ get children() {
378
+ return _$ssr(_tmpl$7);
379
+ }
380
+ })));
381
+ }
382
+ })];
383
+ }
384
+ })));
385
+ }
386
+ //# sourceMappingURL=Dictation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["inputs/dictation/Dictation.tsx"],"sourcesContent":["import { createEffect, createSignal, Index, type JSX, Match, onCleanup, Show, Switch } from \"solid-js\";\nimport { Button, IconButton } from \"../../actions/Button\";\nimport { Dropdown } from \"../../actions/Dropdown\";\nimport { useLocale } from \"../../intl/locale\";\nimport { AnchoredPopover } from \"../../layout/AnchoredPopover\";\nimport { type DictationController, type DictationNotice, isBarNotice } from \"./create-dictation\";\nimport { dictationMessages } from \"./dictation-messages\";\nimport type { DictationDevice } from \"./types\";\n\nconst useDictationMessages = () => {\n const locale = useLocale();\n return () => dictationMessages.resolve([locale()]).t;\n};\n\n/** Whether the bar stands in for the host's controls: while dictating, finishing, or showing a bar notice. */\nexport const dictationBarShown = (dictation: DictationController) => dictation.active() || isBarNotice(dictation.notice());\n\nconst clock = (ms: number) => {\n const seconds = Math.max(0, Math.floor(ms / 1000));\n return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, \"0\")}`;\n};\n\n/** The quiet countdown starts one minute before the end. */\nconst warnMs = 60_000;\n\nconst deviceIcon = (device: DictationDevice | undefined) => {\n const label = device?.label ?? \"\";\n if (/airpods|buds|headset|headphone|kopfhörer/i.test(label)) return \"ti-headphones\";\n if (/iphone|android|phone|handy|mobile/i.test(label)) return \"ti-device-mobile\";\n if (/macbook|laptop|built-in|internal|intern/i.test(label) || !label) return \"ti-device-laptop\";\n return \"ti-microphone\";\n};\n\nexport type DictationButtonProps = {\n dictation: DictationController;\n size?: \"xs\" | \"sm\";\n class?: string;\n /** The box the notice cards line up with, such as the whole composer; defaults to the button. */\n cardAnchor?: () => HTMLElement | undefined;\n};\n\n/**\n * The microphone at its fixed place. A press starts live dictation; offline it stays focusable and says why it waits.\n * Notices that need a decision, such as a blocked microphone or a used-up allowance, open as cards above it.\n */\nexport function DictationButton(props: DictationButtonProps): JSX.Element {\n const t = useDictationMessages();\n const [button, setButton] = createSignal<HTMLButtonElement>();\n const card = () => {\n const notice = props.dictation.notice();\n return notice && !isBarNotice(notice) ? notice : null;\n };\n createEffect(() => props.dictation.bind(\"microphone\", button()));\n onCleanup(() => props.dictation.bind(\"microphone\", undefined));\n return (\n <>\n <IconButton\n ref={setButton}\n size={props.size ?? \"sm\"}\n class={`k2b-dictation-button ${props.class ?? \"\"}`}\n label={props.dictation.offline() ? t().dictateOffline : t().dictate}\n tooltip={props.dictation.offline() ? t().offline : t().dictate}\n aria-pressed={props.dictation.active() ? \"true\" : \"false\"}\n aria-disabled={props.dictation.offline() || (!props.dictation.active() && props.dictation.disabled()) ? \"true\" : undefined}\n data-notice={card()?.kind}\n onClick={() => {\n if (props.dictation.offline() || (!props.dictation.active() && props.dictation.disabled())) return;\n if (props.dictation.active()) void props.dictation.stop();\n else props.dictation.start();\n }}\n >\n <i class={`ti ${card()?.kind === \"blocked\" ? \"ti-microphone-off\" : \"ti-microphone\"}`} aria-hidden=\"true\" />\n </IconButton>\n <Show when={card()}>\n {(notice) => <DictationCard dictation={props.dictation} notice={notice()} anchor={props.cardAnchor?.() ?? button()} />}\n </Show>\n </>\n );\n}\n\nfunction DictationCard(props: { dictation: DictationController; notice: DictationNotice; anchor: HTMLElement | undefined }) {\n const t = useDictationMessages();\n const locale = useLocale();\n const resetTime = () => {\n const notice = props.notice;\n const at = notice.kind === \"quota\" && notice.resetsAt ? new Date(notice.resetsAt) : null;\n const time = (at ?? new Date(new Date().setHours(24, 0, 0, 0))).toLocaleTimeString(locale(), { hour: \"2-digit\", minute: \"2-digit\" });\n const today = new Date();\n const tomorrow = !at || at.toDateString() !== today.toDateString();\n return tomorrow ? t().quotaBodyTomorrow({ time }) : t().quotaBody({ time });\n };\n const content = (): { icon: string; title: string; body: JSX.Element; retry: boolean } => {\n switch (props.notice.kind) {\n case \"blocked\":\n return {\n icon: \"ti-microphone-off\",\n title: t().blockedTitle,\n body: (\n <>\n <p>{t().blockedBody}</p>\n <ol>\n <li>{t().blockedStep1}</li>\n <li>{t().blockedStep2}</li>\n </ol>\n </>\n ),\n retry: true,\n };\n case \"quota\":\n return { icon: \"ti-hourglass\", title: t().quotaTitle, body: <p>{resetTime()}</p>, retry: false };\n case \"overloaded\":\n return {\n icon: \"ti-hourglass\",\n title: t().overloadedTitle,\n body: <p>{props.dictation.alternative?.note ?? t().overloadedBody}</p>,\n retry: true,\n };\n case \"elsewhere\":\n return { icon: \"ti-microphone\", title: t().elsewhereTitle, body: <p>{t().elsewhereBody}</p>, retry: false };\n case \"unavailable\":\n return { icon: \"ti-microphone-off\", title: t().unavailableTitle, body: <p>{t().unavailableBody}</p>, retry: true };\n default:\n return { icon: \"ti-microphone-off\", title: t().notAvailableTitle, body: <p>{t().notAvailableBody}</p>, retry: false };\n }\n };\n return (\n <AnchoredPopover\n anchor={props.anchor}\n onClose={() => props.dictation.dismiss()}\n label={content().title}\n side=\"above\"\n align=\"end\"\n width=\"20rem\"\n sheet={false}\n class=\"k2b-dictation-card\"\n >\n <h3 class=\"k2b-dictation-card__title\">\n <i class={`ti ${content().icon}`} aria-hidden=\"true\" />\n {content().title}\n </h3>\n <div class=\"k2b-dictation-card__body\">{content().body}</div>\n <div class=\"k2b-dictation-card__actions\">\n <Show when={props.notice.kind === \"overloaded\" ? props.dictation.alternative : undefined}>\n {(alternative) => (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n props.dictation.dismiss();\n alternative().run();\n }}\n >\n {alternative().label}\n </Button>\n )}\n </Show>\n <Show\n when={content().retry}\n fallback={\n <Button\n size=\"sm\"\n variant=\"ghost\"\n class={props.notice.kind === \"elsewhere\" ? \"k2b-dictation-card__primary\" : undefined}\n onClick={() => props.dictation.dismiss()}\n >\n {t().ok}\n </Button>\n }\n >\n <Button size=\"sm\" variant=\"ghost\" class=\"k2b-dictation-card__primary\" onClick={() => props.dictation.start()}>\n {t().retry}\n </Button>\n </Show>\n </div>\n </AnchoredPopover>\n );\n}\n\nexport type DictationBarProps = {\n dictation: DictationController;\n class?: string;\n};\n\n/**\n * The row that stands in for the host's controls while dictating, at the same place and height: Discard, level, time,\n * microphone and Stop; then \"Finishing …\" until the last words arrived; and a notice with \"Continue\" when the session\n * ended early. Render it where `dictationBarShown()` is true. Escape stops, after closing an open menu.\n */\nexport function DictationBar(props: DictationBarProps): JSX.Element {\n const t = useDictationMessages();\n const status = () => props.dictation.status();\n const remaining = () => props.dictation.maxMs() - props.dictation.elapsedMs();\n const warning = () => status() === \"live\" && remaining() <= warnMs;\n const time = () => (warning() ? t().timeLeft({ time: clock(remaining()) }) : clock(props.dictation.elapsedMs()));\n const slots = 160;\n const bars = () => {\n const levels = props.dictation.levels();\n return Array.from({ length: slots }, (_, index) => levels[levels.length - slots + index] ?? 0);\n };\n const deviceLabel = () => props.dictation.device()?.label || t().microphone;\n\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || event.defaultPrevented || status() !== \"live\") return;\n event.preventDefault();\n void props.dictation.stop();\n };\n createEffect(() => {\n if (status() !== \"live\") return;\n document.addEventListener(\"keydown\", onKey);\n onCleanup(() => document.removeEventListener(\"keydown\", onKey));\n });\n const bindStop = (element: HTMLElement) => {\n props.dictation.bind(\"stop\", element);\n onCleanup(() => props.dictation.bind(\"stop\", undefined));\n };\n const bindContinue = (element: HTMLElement) => {\n props.dictation.bind(\"continue\", element);\n onCleanup(() => props.dictation.bind(\"continue\", undefined));\n };\n\n const deviceItems = () => [\n {\n sectionLabel: t().microphone,\n items: (props.dictation.devices().length\n ? props.dictation.devices()\n : props.dictation.device()\n ? [props.dictation.device()!]\n : []\n ).map((device) => ({\n choice: \"radio\" as const,\n icon: `ti ${deviceIcon(device)}`,\n label: device.id === \"default\" ? `${device.label || t().microphone} · ${t().systemDefault}` : device.label || t().microphone,\n checked: () => (props.dictation.deviceId() ?? props.dictation.device()?.id) === device.id,\n action: () => props.dictation.chooseDevice(device.id),\n })),\n },\n ];\n\n return (\n <div class={`k2b-dictation-bar ${props.class ?? \"\"}`}>\n <Switch>\n <Match when={status() === \"finishing\"}>\n <div class=\"k2b-dictation-bar__row\" data-state=\"finishing\" role=\"group\" aria-label={t().finishingGroup}>\n <IconButton size=\"sm\" label={t().discard} aria-disabled=\"true\" class=\"k2b-dictation-bar__icon\">\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </IconButton>\n <div class=\"k2b-dictation-bar__status\" role=\"status\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n <span class=\"k2b-dictation-bar__message\">{t().finishing}</span>\n </div>\n <span class=\"k2b-dictation-bar__time\">{clock(props.dictation.elapsedMs())}</span>\n <span class=\"k2b-dictation-bar__stop\" data-disabled=\"true\" aria-hidden=\"true\">\n <span />\n </span>\n </div>\n </Match>\n <Match when={status() === \"live\" || status() === \"starting\"}>\n <div class=\"k2b-dictation-bar__row\" data-state={status()} role=\"group\" aria-label={t().running}>\n <IconButton size=\"sm\" label={t().discard} class=\"k2b-dictation-bar__icon\" onClick={() => props.dictation.discard()}>\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </IconButton>\n <span class=\"k2b-dictation-bar__dot\" data-live={status() === \"live\" ? \"true\" : undefined} aria-hidden=\"true\" />\n <div class=\"k2b-dictation-bar__wave\" aria-hidden=\"true\">\n <Index each={bars()}>{(level) => <span style={{ \"--k2b-dictation-level\": String(0.1 + level() * 0.9) }} />}</Index>\n </div>\n <span class=\"k2b-dictation-bar__time\" data-warning={warning() ? \"true\" : undefined}>\n {status() === \"starting\" ? clock(0) : time()}\n </span>\n <Dropdown\n items={deviceItems()}\n position=\"top-left\"\n width=\"16.25rem\"\n onOpenChange={(open) => {\n if (open) void props.dictation.loadDevices();\n }}\n >\n <Dropdown.Trigger appearance=\"plain\" class=\"k2b-dictation-bar__device\" label={t().microphoneNamed({ name: deviceLabel() })}>\n <i class={`ti ${deviceIcon(props.dictation.device())}`} aria-hidden=\"true\" />\n <span class=\"k2b-dictation-bar__device-name\">{deviceLabel()}</span>\n <i class=\"ti ti-chevron-down k2b-dictation-bar__device-chevron\" aria-hidden=\"true\" />\n </Dropdown.Trigger>\n </Dropdown>\n <button\n ref={bindStop}\n type=\"button\"\n class=\"k2b-dictation-bar__stop\"\n aria-label={t().stop}\n title={t().stop}\n onClick={() => void props.dictation.stop()}\n >\n <span aria-hidden=\"true\" />\n </button>\n </div>\n </Match>\n <Match when={isBarNotice(props.dictation.notice()) ? props.dictation.notice() : undefined}>\n {(notice) => {\n const ended = () => {\n const value = notice();\n return value.kind === \"ended\" ? value : undefined;\n };\n const minutes = () => Math.round((ended()?.maxMs ?? 600_000) / 60_000);\n const long = () =>\n !ended() ? t().interrupted : ended()!.reason === \"silence\" ? t().silenceDone : t().maxDone({ minutes: minutes() });\n const short = () =>\n !ended()\n ? t().interruptedShort\n : ended()!.reason === \"silence\"\n ? t().silenceDoneShort\n : t().maxDoneShort({ minutes: minutes() });\n return (\n <div class=\"k2b-dictation-bar__row\" data-state=\"notice\">\n <div class=\"k2b-dictation-bar__status\" data-tone={ended() ? undefined : \"danger\"} role=\"status\">\n <i class={`ti ${ended() ? \"ti-clock\" : \"ti-alert-circle\"}`} aria-hidden=\"true\" />\n {/* The full message is read on every width; the visible text shortens on narrow rows. */}\n <span class=\"k2b-sr-only\">{long()}</span>\n <span class=\"k2b-dictation-bar__message k2b-dictation-bar__message--long\" aria-hidden=\"true\">\n {long()}\n </span>\n <span class=\"k2b-dictation-bar__message k2b-dictation-bar__message--short\" aria-hidden=\"true\">\n {short()}\n </span>\n </div>\n <Button\n ref={bindContinue}\n size=\"sm\"\n variant=\"ghost\"\n class=\"k2b-dictation-bar__continue\"\n onClick={() => props.dictation.start()}\n >\n {t().continue}\n </Button>\n <IconButton size=\"sm\" label={t().dismiss} class=\"k2b-dictation-bar__icon\" onClick={() => props.dictation.dismiss()}>\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n );\n }}\n </Match>\n </Switch>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}