@opengeni/react 0.41.0 → 0.44.1
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.
- package/dist/{chunk-SJKT4TKW.js → chunk-23EJ676W.js} +3 -1
- package/dist/chunk-23EJ676W.js.map +1 -0
- package/dist/{chunk-OMCFRWHL.js → chunk-KC27K42G.js} +1443 -101
- package/dist/chunk-KC27K42G.js.map +1 -0
- package/dist/{chunk-KR2SK5GJ.js → chunk-KG5F2OKE.js} +260 -93
- package/dist/chunk-KG5F2OKE.js.map +1 -0
- package/dist/{chunk-4IJCL7YO.js → chunk-LWR4MXSS.js} +4 -1
- package/dist/chunk-LWR4MXSS.js.map +1 -0
- package/dist/{chunk-JALF5FI3.js → chunk-SRFUT2ZU.js} +2 -2
- package/dist/{chunk-WZT5G5OR.js → chunk-U6K24XQD.js} +5 -4
- package/dist/{chunk-WZT5G5OR.js.map → chunk-U6K24XQD.js.map} +1 -1
- package/dist/components/chat-composer.d.ts +5 -1
- package/dist/components/composer-transcription-control.d.ts +16 -1
- package/dist/components/composer.d.ts +6 -4
- package/dist/components/session-chrome.d.ts +1 -1
- package/dist/composer.d.ts +3 -1
- package/dist/composer.js +29 -3
- package/dist/hooks/use-voice-input.d.ts +25 -4
- package/dist/index.d.ts +4 -2
- package/dist/index.js +95 -20
- package/dist/index.js.map +1 -1
- package/dist/model-policy.d.ts +2 -0
- package/dist/model-policy.js +1 -1
- package/dist/realtime/realtime-control.d.ts +29 -1
- package/dist/realtime.d.ts +1 -1
- package/dist/realtime.js +269 -151
- package/dist/realtime.js.map +1 -1
- package/dist/session-ui.js +2 -2
- package/dist/session.js +2 -2
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/parsers.d.ts +13 -8
- package/dist/voice-recording-owner.d.ts +12 -0
- package/dist/voice-recording-store.d.ts +124 -0
- package/package.json +2 -2
- package/src/components/chat-composer.tsx +58 -19
- package/src/components/composer-transcription-control.tsx +258 -117
- package/src/components/composer.tsx +78 -14
- package/src/components/model-policy-picker.tsx +7 -2
- package/src/components/session-chrome.tsx +89 -78
- package/src/composer.ts +30 -1
- package/src/hooks/use-voice-input.ts +893 -67
- package/src/index.ts +32 -1
- package/src/model-policy.ts +4 -0
- package/src/realtime/realtime-control.tsx +307 -137
- package/src/realtime.ts +1 -0
- package/src/timeline/index.ts +2 -0
- package/src/timeline/parsers.ts +201 -19
- package/src/timeline/projection.ts +11 -0
- package/src/timeline/tool-renderers.tsx +7 -5
- package/src/timeline/turn-summary.tsx +7 -2
- package/src/voice-recording-owner.ts +251 -0
- package/src/voice-recording-store.ts +528 -0
- package/styles/tokens.css +8 -5
- package/dist/chunk-4IJCL7YO.js.map +0 -1
- package/dist/chunk-KR2SK5GJ.js.map +0 -1
- package/dist/chunk-OMCFRWHL.js.map +0 -1
- package/dist/chunk-SJKT4TKW.js.map +0 -1
- /package/dist/{chunk-JALF5FI3.js.map → chunk-SRFUT2ZU.js.map} +0 -0
|
@@ -241,25 +241,84 @@ export type UseChatComposerControllerOptions = {
|
|
|
241
241
|
};
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
* tip-follow
|
|
244
|
+
* Off-document mirror for shrink/steady measure. Measuring with
|
|
245
|
+
* `height: auto` on the live `rows={1}` textarea collapses it for a layout
|
|
246
|
+
* frame, expands the flex timeline sibling, and yanks tip-follow — the
|
|
247
|
+
* multi-line typing flicker that stops only once the box is capped.
|
|
248
|
+
*/
|
|
249
|
+
let composerHeightMirror: HTMLTextAreaElement | null = null;
|
|
250
|
+
|
|
251
|
+
function measureComposerContentHeight(textarea: HTMLTextAreaElement): number {
|
|
252
|
+
if (typeof document === "undefined") {
|
|
253
|
+
return textarea.scrollHeight;
|
|
254
|
+
}
|
|
255
|
+
const width = textarea.clientWidth;
|
|
256
|
+
if (width <= 0) {
|
|
257
|
+
return textarea.offsetHeight;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let mirror = composerHeightMirror;
|
|
261
|
+
if (!mirror) {
|
|
262
|
+
mirror = document.createElement("textarea");
|
|
263
|
+
mirror.setAttribute("aria-hidden", "true");
|
|
264
|
+
mirror.tabIndex = -1;
|
|
265
|
+
mirror.rows = 1;
|
|
266
|
+
mirror.style.cssText =
|
|
267
|
+
"position:absolute;top:0;left:0;visibility:hidden;pointer-events:none;height:auto;min-height:0;max-height:none;overflow:hidden;z-index:-1;";
|
|
268
|
+
composerHeightMirror = mirror;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const style = getComputedStyle(textarea);
|
|
272
|
+
mirror.style.width = `${width}px`;
|
|
273
|
+
mirror.style.boxSizing = style.boxSizing;
|
|
274
|
+
mirror.style.font = style.font;
|
|
275
|
+
mirror.style.fontSize = style.fontSize;
|
|
276
|
+
mirror.style.fontFamily = style.fontFamily;
|
|
277
|
+
mirror.style.fontWeight = style.fontWeight;
|
|
278
|
+
mirror.style.fontStyle = style.fontStyle;
|
|
279
|
+
mirror.style.letterSpacing = style.letterSpacing;
|
|
280
|
+
mirror.style.lineHeight = style.lineHeight;
|
|
281
|
+
mirror.style.textTransform = style.textTransform;
|
|
282
|
+
mirror.style.paddingTop = style.paddingTop;
|
|
283
|
+
mirror.style.paddingRight = style.paddingRight;
|
|
284
|
+
mirror.style.paddingBottom = style.paddingBottom;
|
|
285
|
+
mirror.style.paddingLeft = style.paddingLeft;
|
|
286
|
+
mirror.style.borderTopWidth = style.borderTopWidth;
|
|
287
|
+
mirror.style.borderRightWidth = style.borderRightWidth;
|
|
288
|
+
mirror.style.borderBottomWidth = style.borderBottomWidth;
|
|
289
|
+
mirror.style.borderLeftWidth = style.borderLeftWidth;
|
|
290
|
+
mirror.style.borderStyle = style.borderStyle;
|
|
291
|
+
mirror.style.whiteSpace = style.whiteSpace;
|
|
292
|
+
mirror.style.wordBreak = style.wordBreak;
|
|
293
|
+
mirror.style.overflowWrap = style.overflowWrap;
|
|
294
|
+
mirror.value = textarea.value;
|
|
295
|
+
|
|
296
|
+
if (!mirror.isConnected) {
|
|
297
|
+
document.documentElement.appendChild(mirror);
|
|
298
|
+
}
|
|
299
|
+
return mirror.scrollHeight;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Autosize a composer textarea up to `maxPx`. Never writes intermediate
|
|
304
|
+
* `height: auto` / `0` on the live element — only the final pixel height.
|
|
305
|
+
*
|
|
306
|
+
* `measure` is injectable for unit tests; production always uses the off-DOM
|
|
307
|
+
* mirror so shrink/steady never collapses the laid-out box.
|
|
247
308
|
*/
|
|
248
309
|
export function applyComposerTextareaHeight(
|
|
249
310
|
textarea: HTMLTextAreaElement,
|
|
250
311
|
maxPx: number = 220,
|
|
312
|
+
measure: (el: HTMLTextAreaElement) => number = measureComposerContentHeight,
|
|
251
313
|
): void {
|
|
252
|
-
// Grow path: content already overflows — raise height, no measure collapse.
|
|
253
|
-
if (textarea.scrollHeight > textarea.clientHeight + 1) {
|
|
254
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, maxPx)}px`;
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
// Shrink / steady: `auto` measures natural height without flashing empty.
|
|
258
314
|
const before = textarea.offsetHeight;
|
|
259
|
-
|
|
260
|
-
|
|
315
|
+
// Overflow: content taller than the box — scrollHeight is the needed size.
|
|
316
|
+
// Fit/shrink: content fits (or box is oversized) — measure off-DOM.
|
|
317
|
+
const nextPx = Math.min(
|
|
318
|
+
textarea.scrollHeight > textarea.clientHeight + 1 ? textarea.scrollHeight : measure(textarea),
|
|
319
|
+
maxPx,
|
|
320
|
+
);
|
|
261
321
|
if (Math.abs(nextPx - before) < 1) {
|
|
262
|
-
textarea.style.height = `${before}px`;
|
|
263
322
|
return;
|
|
264
323
|
}
|
|
265
324
|
textarea.style.height = `${nextPx}px`;
|
|
@@ -934,7 +993,8 @@ export const Footer = forwardRef<HTMLDivElement, ComposerFooterProps>(function C
|
|
|
934
993
|
ref={ref}
|
|
935
994
|
className={cn(
|
|
936
995
|
"flex items-end gap-1.5 px-2 pb-2 pt-0.5 sm:px-2.5 sm:pb-2.5",
|
|
937
|
-
|
|
996
|
+
// Mobile: one control row — never wrap into a second toolbar line.
|
|
997
|
+
"max-sm:flex-nowrap max-sm:items-center max-sm:gap-1",
|
|
938
998
|
className,
|
|
939
999
|
)}
|
|
940
1000
|
/>
|
|
@@ -987,7 +1047,11 @@ export const Actions = forwardRef<HTMLSpanElement, ComposerActionsProps>(functio
|
|
|
987
1047
|
<span
|
|
988
1048
|
{...props}
|
|
989
1049
|
ref={ref}
|
|
990
|
-
className={cn(
|
|
1050
|
+
className={cn(
|
|
1051
|
+
"ml-auto flex shrink-0 items-center gap-1.5",
|
|
1052
|
+
"max-sm:flex-nowrap max-sm:gap-1",
|
|
1053
|
+
className,
|
|
1054
|
+
)}
|
|
991
1055
|
/>
|
|
992
1056
|
);
|
|
993
1057
|
});
|
|
@@ -545,7 +545,7 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
545
545
|
disabled={props.disabled}
|
|
546
546
|
aria-label={messages.label}
|
|
547
547
|
className={cn(
|
|
548
|
-
"inline-flex h-8 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-xs text-og-fg-muted outline-none transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-7 max-sm:max-w-[
|
|
548
|
+
"inline-flex h-8 min-w-0 max-w-64 items-center gap-1 rounded-full border border-transparent px-2.5 text-xs text-og-fg-muted outline-none transition-colors hover:border-og-border hover:bg-og-surface-2 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 disabled:cursor-not-allowed disabled:opacity-50 max-sm:h-7 max-sm:max-w-[7.5rem] max-sm:px-2",
|
|
549
549
|
props.className,
|
|
550
550
|
)}
|
|
551
551
|
>
|
|
@@ -556,7 +556,12 @@ export function ModelPolicyPicker(props: ModelPolicyPickerProps) {
|
|
|
556
556
|
}
|
|
557
557
|
className="text-og-fg"
|
|
558
558
|
/>
|
|
559
|
-
<span className="truncate font-medium text-og-fg">
|
|
559
|
+
<span className="min-w-0 truncate font-medium text-og-fg max-sm:hidden">
|
|
560
|
+
{selected?.label ?? props.model}
|
|
561
|
+
</span>
|
|
562
|
+
<span className="min-w-0 truncate font-medium text-og-fg sm:hidden">
|
|
563
|
+
{selected?.shortLabel ?? selected?.label ?? props.model}
|
|
564
|
+
</span>
|
|
560
565
|
<span className="max-sm:hidden">{labelReasoningEffort(props.effort)}</span>
|
|
561
566
|
{props.latencyMode === "fast" ? (
|
|
562
567
|
<ZapIcon
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* | --- | --- |
|
|
12
12
|
* | `--og-session-chrome-surface` / `-open` | Dock fill (collapsed / expanded) |
|
|
13
13
|
* | `--og-session-chrome-border` / `-open` | Dock edge |
|
|
14
|
-
* | `--og-session-chrome-highlight` | Sliding chip selection
|
|
14
|
+
* | `--og-session-chrome-highlight` / `-ring` | Sliding chip selection fill + edge |
|
|
15
15
|
* | `--og-session-chrome-shadow` / `-open` | Elevation |
|
|
16
16
|
* | `--og-session-chrome-radius` | Dock corner radius |
|
|
17
17
|
* | `--og-session-chrome-chip-min-height` | Signal chip height |
|
|
@@ -394,7 +394,7 @@ export function SessionChrome({
|
|
|
394
394
|
const chipRefs = useRef<Partial<Record<SessionChromeSignalId, HTMLButtonElement | null>>>({});
|
|
395
395
|
const railRef = useRef<HTMLDivElement | null>(null);
|
|
396
396
|
const panelBodyRef = useRef<HTMLDivElement | null>(null);
|
|
397
|
-
const [pill, setPill] = useState({ left: 0, width: 0, opacity: 0 });
|
|
397
|
+
const [pill, setPill] = useState({ left: 0, top: 0, width: 0, height: 0, opacity: 0 });
|
|
398
398
|
const [panelHeight, setPanelHeight] = useState(0);
|
|
399
399
|
|
|
400
400
|
const signalIds = signals.map((signal) => signal.id).join(",");
|
|
@@ -421,11 +421,15 @@ export function SessionChrome({
|
|
|
421
421
|
}
|
|
422
422
|
const chip = chipRefs.current[active];
|
|
423
423
|
if (!chip) return;
|
|
424
|
+
// Measure against the chip's own box so a wrapped multi-row rail never
|
|
425
|
+
// stretches the highlight into a tall stripe across every signal.
|
|
424
426
|
const railBox = rail.getBoundingClientRect();
|
|
425
427
|
const chipBox = chip.getBoundingClientRect();
|
|
426
428
|
setPill({
|
|
427
429
|
left: chipBox.left - railBox.left,
|
|
430
|
+
top: chipBox.top - railBox.top,
|
|
428
431
|
width: chipBox.width,
|
|
432
|
+
height: chipBox.height,
|
|
429
433
|
opacity: 1,
|
|
430
434
|
});
|
|
431
435
|
};
|
|
@@ -433,6 +437,9 @@ export function SessionChrome({
|
|
|
433
437
|
if (!rail) return;
|
|
434
438
|
const observer = new ResizeObserver(measure);
|
|
435
439
|
observer.observe(rail);
|
|
440
|
+
for (const chip of Object.values(chipRefs.current)) {
|
|
441
|
+
if (chip) observer.observe(chip);
|
|
442
|
+
}
|
|
436
443
|
window.addEventListener("resize", measure);
|
|
437
444
|
return () => {
|
|
438
445
|
observer.disconnect();
|
|
@@ -568,88 +575,92 @@ export function SessionChrome({
|
|
|
568
575
|
}}
|
|
569
576
|
>
|
|
570
577
|
<div
|
|
571
|
-
|
|
572
|
-
className="relative flex flex-wrap items-stretch"
|
|
578
|
+
className="relative"
|
|
573
579
|
style={{
|
|
574
|
-
|
|
575
|
-
|
|
580
|
+
paddingTop: "var(--og-session-chrome-rail-pad)",
|
|
581
|
+
paddingBottom: "var(--og-session-chrome-rail-pad)",
|
|
582
|
+
paddingLeft: "var(--og-session-chrome-rail-pad)",
|
|
583
|
+
paddingRight: "var(--og-session-chrome-rail-pad)",
|
|
576
584
|
}}
|
|
577
585
|
>
|
|
578
|
-
<
|
|
579
|
-
|
|
580
|
-
className="
|
|
586
|
+
<div
|
|
587
|
+
ref={railRef}
|
|
588
|
+
className="relative flex flex-wrap items-center"
|
|
581
589
|
style={{
|
|
582
|
-
|
|
583
|
-
bottom: "var(--og-session-chrome-rail-pad)",
|
|
584
|
-
background: "var(--og-session-chrome-highlight)",
|
|
590
|
+
gap: "var(--og-session-chrome-chip-gap)",
|
|
585
591
|
}}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
"
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
selected
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
592
|
+
>
|
|
593
|
+
<motion.div
|
|
594
|
+
aria-hidden
|
|
595
|
+
className="pointer-events-none absolute left-0 top-0 rounded-og-md"
|
|
596
|
+
style={{
|
|
597
|
+
background: "var(--og-session-chrome-highlight)",
|
|
598
|
+
boxShadow: "inset 0 0 0 1px var(--og-session-chrome-highlight-ring)",
|
|
599
|
+
}}
|
|
600
|
+
initial={false}
|
|
601
|
+
animate={{
|
|
602
|
+
x: pill.left,
|
|
603
|
+
y: pill.top,
|
|
604
|
+
width: pill.width,
|
|
605
|
+
height: pill.height,
|
|
606
|
+
opacity: pill.opacity,
|
|
607
|
+
}}
|
|
608
|
+
transition={{ duration: shellDuration, ease }}
|
|
609
|
+
/>
|
|
610
|
+
{signals.map((signal) => {
|
|
611
|
+
const selected = active === signal.id;
|
|
612
|
+
return (
|
|
613
|
+
<button
|
|
614
|
+
key={signal.id}
|
|
615
|
+
type="button"
|
|
616
|
+
ref={(node) => {
|
|
617
|
+
chipRefs.current[signal.id] = node;
|
|
618
|
+
}}
|
|
619
|
+
aria-expanded={selected}
|
|
620
|
+
aria-controls={panelId}
|
|
621
|
+
aria-label={selected ? `Close ${signal.label}` : undefined}
|
|
622
|
+
data-testid={`session-chrome-${signal.id}`}
|
|
623
|
+
data-og-session-chrome-signal={signal.id}
|
|
624
|
+
onClick={() => setActive(selected ? null : signal.id)}
|
|
625
|
+
className={cn(
|
|
626
|
+
"group relative z-[1] inline-flex min-h-[var(--og-session-chrome-chip-min-height)] max-w-full items-center gap-1 rounded-og-md py-1 text-left text-og-xs outline-none",
|
|
627
|
+
// Coarse pointers keep a 44px target (session-pins acceptance).
|
|
628
|
+
"pointer-coarse:min-h-11",
|
|
629
|
+
"transition-colors duration-150 motion-reduce:transition-none",
|
|
630
|
+
"hover:text-og-fg focus-visible:bg-og-surface-3/50",
|
|
631
|
+
selected ? "text-og-fg" : "text-og-fg-muted",
|
|
632
|
+
)}
|
|
633
|
+
style={{
|
|
634
|
+
paddingInline: "var(--og-session-chrome-chip-pad-x)",
|
|
635
|
+
}}
|
|
636
|
+
>
|
|
637
|
+
<span className={cn("shrink-0", toneClass(signal.tone, selected))}>
|
|
638
|
+
{signal.icon}
|
|
639
|
+
</span>
|
|
640
|
+
<span className="shrink-0 font-medium text-og-fg">{signal.label}</span>
|
|
641
|
+
{signal.detail ? (
|
|
642
|
+
<>
|
|
643
|
+
<span aria-hidden className="shrink-0 text-og-fg-subtle/60">
|
|
644
|
+
·
|
|
645
|
+
</span>
|
|
646
|
+
<span className="min-w-0 max-w-[8.5rem] truncate text-og-fg sm:max-w-[12rem]">
|
|
647
|
+
{signal.detail}
|
|
648
|
+
</span>
|
|
649
|
+
</>
|
|
650
|
+
) : null}
|
|
651
|
+
{selected ? (
|
|
652
|
+
<span
|
|
653
|
+
data-testid="session-chrome-close"
|
|
654
|
+
className="ml-0.5 inline-flex size-4 shrink-0 items-center justify-center rounded-og-sm text-og-fg-subtle transition-colors group-hover:text-og-fg pointer-coarse:size-5"
|
|
655
|
+
aria-hidden
|
|
656
|
+
>
|
|
657
|
+
<XIcon className="size-3" />
|
|
630
658
|
</span>
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
)
|
|
635
|
-
|
|
636
|
-
<AnimatePresence initial={false}>
|
|
637
|
-
{open ? (
|
|
638
|
-
<motion.button
|
|
639
|
-
key="close"
|
|
640
|
-
type="button"
|
|
641
|
-
aria-label="Close session chrome panel"
|
|
642
|
-
onClick={() => setActive(null)}
|
|
643
|
-
initial={reduceMotion ? false : { opacity: 0 }}
|
|
644
|
-
animate={{ opacity: 1 }}
|
|
645
|
-
exit={reduceMotion ? { opacity: 1 } : { opacity: 0 }}
|
|
646
|
-
transition={{ duration: crossfadeDuration, ease }}
|
|
647
|
-
className="relative z-[1] ml-auto inline-flex size-7 shrink-0 items-center justify-center rounded-og-md text-og-fg-subtle outline-none transition-colors hover:bg-og-surface-3/60 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/40 pointer-coarse:size-11"
|
|
648
|
-
>
|
|
649
|
-
<XIcon className="size-3" />
|
|
650
|
-
</motion.button>
|
|
651
|
-
) : null}
|
|
652
|
-
</AnimatePresence>
|
|
659
|
+
) : null}
|
|
660
|
+
</button>
|
|
661
|
+
);
|
|
662
|
+
})}
|
|
663
|
+
</div>
|
|
653
664
|
</div>
|
|
654
665
|
|
|
655
666
|
<motion.div
|
package/src/composer.ts
CHANGED
|
@@ -71,9 +71,38 @@ export type {
|
|
|
71
71
|
ComposerTranscriptionControlProps,
|
|
72
72
|
ComposerTranscriptionMessages,
|
|
73
73
|
} from "./components/composer-transcription-control";
|
|
74
|
-
export {
|
|
74
|
+
export {
|
|
75
|
+
VOICE_RECORDING_CLIENT_MAX_DURATION_SECONDS,
|
|
76
|
+
VOICE_RECORDING_OWNER_HEARTBEAT_MILLISECONDS,
|
|
77
|
+
VOICE_RECORDING_OWNER_STALE_MILLISECONDS,
|
|
78
|
+
VOICE_RECORDING_TIMESLICE_MILLISECONDS,
|
|
79
|
+
useVoiceInput,
|
|
80
|
+
} from "./hooks/use-voice-input";
|
|
75
81
|
export type {
|
|
76
82
|
UseVoiceInputOptions,
|
|
77
83
|
UseVoiceInputResult,
|
|
78
84
|
VoiceInputStatus,
|
|
79
85
|
} from "./hooks/use-voice-input";
|
|
86
|
+
export {
|
|
87
|
+
IndexedDbVoiceRecordingStore,
|
|
88
|
+
VoiceRecordingChunkConflictError,
|
|
89
|
+
VoiceRecordingChunkSequenceError,
|
|
90
|
+
VoiceRecordingNotFoundError,
|
|
91
|
+
VoiceRecordingOwnedError,
|
|
92
|
+
VoiceRecordingStorageUnavailableError,
|
|
93
|
+
createVoiceRecordingManifest,
|
|
94
|
+
planVoiceRecordingChunkCommit,
|
|
95
|
+
prepareVoiceRecordingChunk,
|
|
96
|
+
} from "./voice-recording-store";
|
|
97
|
+
export type {
|
|
98
|
+
PersistVoiceRecordingChunkInput,
|
|
99
|
+
PersistVoiceRecordingChunkResult,
|
|
100
|
+
VoiceRecordingCaptureState,
|
|
101
|
+
VoiceRecordingChunk,
|
|
102
|
+
VoiceRecordingChunkUploadState,
|
|
103
|
+
VoiceRecordingFinalizationState,
|
|
104
|
+
VoiceRecordingManifest,
|
|
105
|
+
VoiceRecordingStore,
|
|
106
|
+
VoiceRecordingTranscriptionState,
|
|
107
|
+
VoiceRecordingUploadState,
|
|
108
|
+
} from "./voice-recording-store";
|