@epicbagel/saas-kit 1.10.0 → 1.11.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.
Files changed (42) hide show
  1. package/README.md +21 -3
  2. package/dist/{chunk-VBKJXNEL.js → chunk-5OF6D3GH.js} +4 -3
  3. package/dist/chunk-D47AMKT4.cjs +293 -0
  4. package/dist/chunk-EDEN7TAL.js +293 -0
  5. package/dist/{chunk-M2ZNC3TK.js → chunk-HLAHOVEI.js} +98 -2
  6. package/dist/{chunk-KUG4ONYC.js → chunk-KF4X37DP.js} +40 -27
  7. package/dist/{chunk-XB2D4NQK.cjs → chunk-NKWHDI4C.cjs} +4 -3
  8. package/dist/{chunk-UW67GSZ4.cjs → chunk-YMI3X2YL.cjs} +38 -25
  9. package/dist/{chunk-O6F3LVZY.cjs → chunk-ZZ7ICQR2.cjs} +120 -24
  10. package/dist/hooks/use-dictation.cjs +2 -2
  11. package/dist/hooks/use-dictation.d.cts +5 -0
  12. package/dist/hooks/use-dictation.d.ts +5 -0
  13. package/dist/hooks/use-dictation.js +1 -1
  14. package/dist/primitives/agent-audio-visualizer-bar.cjs +2 -2
  15. package/dist/primitives/agent-audio-visualizer-bar.d.cts +1 -1
  16. package/dist/primitives/agent-audio-visualizer-bar.d.ts +1 -1
  17. package/dist/primitives/agent-audio-visualizer-bar.js +1 -1
  18. package/dist/primitives/alert.d.cts +1 -1
  19. package/dist/primitives/alert.d.ts +1 -1
  20. package/dist/primitives/badge.d.cts +1 -1
  21. package/dist/primitives/badge.d.ts +1 -1
  22. package/dist/primitives/bubble.d.cts +1 -1
  23. package/dist/primitives/bubble.d.ts +1 -1
  24. package/dist/primitives/button.d.cts +2 -2
  25. package/dist/primitives/button.d.ts +2 -2
  26. package/dist/primitives/chat.cjs +15 -15
  27. package/dist/primitives/chat.d.cts +2 -2
  28. package/dist/primitives/chat.d.ts +2 -2
  29. package/dist/primitives/chat.js +10 -10
  30. package/dist/primitives/dictation-provider.cjs +2 -2
  31. package/dist/primitives/dictation-provider.js +1 -1
  32. package/dist/primitives/voice-dictation-button.cjs +5 -3
  33. package/dist/primitives/voice-dictation-button.d.cts +9 -11
  34. package/dist/primitives/voice-dictation-button.d.ts +9 -11
  35. package/dist/primitives/voice-dictation-button.js +4 -2
  36. package/dist/primitives/voice-session-controls.cjs +3 -3
  37. package/dist/primitives/voice-session-controls.d.cts +3 -1
  38. package/dist/primitives/voice-session-controls.d.ts +3 -1
  39. package/dist/primitives/voice-session-controls.js +2 -2
  40. package/package.json +1 -1
  41. package/dist/chunk-HTCW6AEH.cjs +0 -223
  42. package/dist/chunk-KWV5KTOA.js +0 -223
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import {
4
4
  VoiceSessionControls
5
- } from "../chunk-KUG4ONYC.js";
5
+ } from "../chunk-KF4X37DP.js";
6
6
  import {
7
7
  Trace,
8
8
  TraceLine,
@@ -10,7 +10,7 @@ import {
10
10
  } from "../chunk-Z45YKVAM.js";
11
11
  import {
12
12
  VoiceDictationButton
13
- } from "../chunk-KWV5KTOA.js";
13
+ } from "../chunk-EDEN7TAL.js";
14
14
  import {
15
15
  Suggestion,
16
16
  Suggestions
@@ -75,7 +75,7 @@ import {
75
75
  ActionDock
76
76
  } from "../chunk-42RTTHND.js";
77
77
  import "../chunk-QMA3WVB7.js";
78
- import "../chunk-VBKJXNEL.js";
78
+ import "../chunk-5OF6D3GH.js";
79
79
  import {
80
80
  Button
81
81
  } from "../chunk-W326GKML.js";
@@ -86,7 +86,7 @@ import "../chunk-GJ7S3L6R.js";
86
86
  import {
87
87
  useCopyToClipboard
88
88
  } from "../chunk-ZWZAAGQF.js";
89
- import "../chunk-M2ZNC3TK.js";
89
+ import "../chunk-HLAHOVEI.js";
90
90
  import {
91
91
  useIsMobile
92
92
  } from "../chunk-PIU5SSUV.js";
@@ -465,7 +465,7 @@ function ChatInput({
465
465
  className
466
466
  ),
467
467
  children: [
468
- liveVoiceActive && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-start", className: "w-full border-b border-border", children: /* @__PURE__ */ jsx(VoiceSessionControls, { ...voiceSession }) }),
468
+ liveVoiceActive && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-start", className: "w-full cursor-default border-b border-border p-0 [.border-b]:pb-0", children: /* @__PURE__ */ jsx(VoiceSessionControls, { ...voiceSession }) }),
469
469
  attachments.length > 0 && /* @__PURE__ */ jsx(
470
470
  ChatAttachmentList,
471
471
  {
@@ -489,11 +489,10 @@ function ChatInput({
489
489
  },
490
490
  placeholder,
491
491
  rows: compact ? 1 : composerSize.rows,
492
- wrap: compact ? "off" : void 0,
493
492
  disabled: isDisabled,
494
493
  autoFocus,
495
494
  className: cn(
496
- compact ? "h-[44px] min-h-[44px] max-h-[44px] min-w-0 field-sizing-fixed overflow-hidden whitespace-nowrap text-ellipsis" : composerSize.minHeight,
495
+ compact ? "min-h-[44px] max-h-24 min-w-0" : composerSize.minHeight,
497
496
  // Grows with the text, then scrolls rather than pushing the thread away.
498
497
  "leading-relaxed disabled:opacity-70 placeholder:text-sm",
499
498
  !compact && "max-h-48",
@@ -504,14 +503,14 @@ function ChatInput({
504
503
  /* @__PURE__ */ jsxs(
505
504
  InputGroupAddon,
506
505
  {
507
- align: compact ? "inline-end" : "block-end",
506
+ align: "block-end",
508
507
  "data-slot": "chat-input-actions",
509
508
  onClick: (event) => {
510
509
  if (!event.currentTarget.contains(event.target)) return;
511
510
  if (!event.target.closest("button")) ref.current?.focus();
512
511
  },
513
512
  className: cn(
514
- compact ? "shrink-0 gap-0 p-1" : "gap-2",
513
+ compact ? "gap-1 px-2 pb-2 pt-0" : "gap-2",
515
514
  !compact && (spacious ? "px-5 pb-5 pt-1" : "border-t border-border px-3 py-2.5")
516
515
  ),
517
516
  children: [
@@ -539,7 +538,8 @@ function ChatInput({
539
538
  className: cn("min-w-0 flex-1 truncate px-1 text-center text-xs font-normal text-muted-foreground sm:px-2 sm:text-sm", compact && "hidden"),
540
539
  children: helperText
541
540
  }
542
- ) : /* @__PURE__ */ jsx("div", { className: compact ? "hidden" : "flex-1" }),
541
+ ) : null,
542
+ (!helperText || compact) && /* @__PURE__ */ jsx("div", { className: "flex-1" }),
543
543
  voice && /* @__PURE__ */ jsx(
544
544
  VoiceDictationButton,
545
545
  {
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunkO6F3LVZYcjs = require('../chunk-O6F3LVZY.cjs');
5
+ var _chunkZZ7ICQR2cjs = require('../chunk-ZZ7ICQR2.cjs');
6
6
 
7
7
 
8
- exports.DictationProvider = _chunkO6F3LVZYcjs.DictationProvider;
8
+ exports.DictationProvider = _chunkZZ7ICQR2cjs.DictationProvider;
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import {
4
4
  DictationProvider
5
- } from "../chunk-M2ZNC3TK.js";
5
+ } from "../chunk-HLAHOVEI.js";
6
6
  export {
7
7
  DictationProvider
8
8
  };
@@ -2,10 +2,12 @@
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunkHTCW6AEHcjs = require('../chunk-HTCW6AEH.cjs');
5
+ var _chunkD47AMKT4cjs = require('../chunk-D47AMKT4.cjs');
6
+ require('../chunk-NKWHDI4C.cjs');
6
7
  require('../chunk-JDEXZGIY.cjs');
7
8
  require('../chunk-KWLSBTB2.cjs');
8
- require('../chunk-O6F3LVZY.cjs');
9
+ require('../chunk-2BSFYU22.cjs');
10
+ require('../chunk-ZZ7ICQR2.cjs');
9
11
 
10
12
 
11
- exports.VoiceDictationButton = _chunkHTCW6AEHcjs.VoiceDictationButton;
13
+ exports.VoiceDictationButton = _chunkD47AMKT4cjs.VoiceDictationButton;
@@ -1,14 +1,14 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, RefObject } from 'react';
3
3
 
4
4
  interface VoiceDictationButtonProps {
5
5
  /** Fired when the user taps "Done" with the captured transcript. */
6
6
  onCommit: (text: string) => void;
7
7
  /** Fired if the user closes the overlay without committing. */
8
8
  onCancel?: () => void;
9
- /** Optional title shown above the live transcript inside the overlay. */
9
+ /** Title shown in the recorder. */
10
10
  title?: ReactNode;
11
- /** Tagline shown under the title (small mono caption). Defaults to "listening". */
11
+ /** Recording status label. Defaults to "Recording". */
12
12
  caption?: string;
13
13
  /** BCP-47 language tag. Defaults to "en-US". */
14
14
  lang?: string;
@@ -26,16 +26,14 @@ interface VoiceDictationButtonProps {
26
26
  disabled?: boolean;
27
27
  visibility?: "visible" | "hidden";
28
28
  shrink?: boolean;
29
+ /** Visible desktop anchor for a custom/programmatic trigger. Hidden anchors are ignored. */
30
+ anchorRef?: RefObject<HTMLElement | null>;
29
31
  }
30
32
  /**
31
- * Mic button that opens a fullscreen dictation overlay (portal). When the
32
- * user taps "Done" the captured transcript is committed via onCommit and
33
- * the overlay closes. The overlay strips the page chrome so the user can
34
- * focus on speaking.
35
- *
36
- * Sibling to `<VoiceInput>` which streams chunks inline. Use this when
37
- * dictation should take over the screen instead of typing-into-an-input.
33
+ * Opens beside the invoking control on desktop and fills the screen on
34
+ * mobile, or when no visible anchor exists. Placement changes keep the same
35
+ * recording alive. Done commits its transcript once; Cancel discards it.
38
36
  */
39
- declare function VoiceDictationButton({ onCommit, onCancel, title, caption, lang, continuous, className, size, showLabel, children, disabled, visibility, shrink, }: VoiceDictationButtonProps): react_jsx_runtime.JSX.Element | null;
37
+ declare function VoiceDictationButton({ onCommit, onCancel, title, caption, lang, continuous, className, size, showLabel, children, disabled, visibility, shrink, anchorRef, }: VoiceDictationButtonProps): react_jsx_runtime.JSX.Element | null;
40
38
 
41
39
  export { VoiceDictationButton, type VoiceDictationButtonProps };
@@ -1,14 +1,14 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, RefObject } from 'react';
3
3
 
4
4
  interface VoiceDictationButtonProps {
5
5
  /** Fired when the user taps "Done" with the captured transcript. */
6
6
  onCommit: (text: string) => void;
7
7
  /** Fired if the user closes the overlay without committing. */
8
8
  onCancel?: () => void;
9
- /** Optional title shown above the live transcript inside the overlay. */
9
+ /** Title shown in the recorder. */
10
10
  title?: ReactNode;
11
- /** Tagline shown under the title (small mono caption). Defaults to "listening". */
11
+ /** Recording status label. Defaults to "Recording". */
12
12
  caption?: string;
13
13
  /** BCP-47 language tag. Defaults to "en-US". */
14
14
  lang?: string;
@@ -26,16 +26,14 @@ interface VoiceDictationButtonProps {
26
26
  disabled?: boolean;
27
27
  visibility?: "visible" | "hidden";
28
28
  shrink?: boolean;
29
+ /** Visible desktop anchor for a custom/programmatic trigger. Hidden anchors are ignored. */
30
+ anchorRef?: RefObject<HTMLElement | null>;
29
31
  }
30
32
  /**
31
- * Mic button that opens a fullscreen dictation overlay (portal). When the
32
- * user taps "Done" the captured transcript is committed via onCommit and
33
- * the overlay closes. The overlay strips the page chrome so the user can
34
- * focus on speaking.
35
- *
36
- * Sibling to `<VoiceInput>` which streams chunks inline. Use this when
37
- * dictation should take over the screen instead of typing-into-an-input.
33
+ * Opens beside the invoking control on desktop and fills the screen on
34
+ * mobile, or when no visible anchor exists. Placement changes keep the same
35
+ * recording alive. Done commits its transcript once; Cancel discards it.
38
36
  */
39
- declare function VoiceDictationButton({ onCommit, onCancel, title, caption, lang, continuous, className, size, showLabel, children, disabled, visibility, shrink, }: VoiceDictationButtonProps): react_jsx_runtime.JSX.Element | null;
37
+ declare function VoiceDictationButton({ onCommit, onCancel, title, caption, lang, continuous, className, size, showLabel, children, disabled, visibility, shrink, anchorRef, }: VoiceDictationButtonProps): react_jsx_runtime.JSX.Element | null;
40
38
 
41
39
  export { VoiceDictationButton, type VoiceDictationButtonProps };
@@ -2,10 +2,12 @@
2
2
  "use client";
3
3
  import {
4
4
  VoiceDictationButton
5
- } from "../chunk-KWV5KTOA.js";
5
+ } from "../chunk-EDEN7TAL.js";
6
+ import "../chunk-5OF6D3GH.js";
6
7
  import "../chunk-W326GKML.js";
7
8
  import "../chunk-G6SRSWXB.js";
8
- import "../chunk-M2ZNC3TK.js";
9
+ import "../chunk-GJ7S3L6R.js";
10
+ import "../chunk-HLAHOVEI.js";
9
11
  export {
10
12
  VoiceDictationButton
11
13
  };
@@ -2,11 +2,11 @@
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunkUW67GSZ4cjs = require('../chunk-UW67GSZ4.cjs');
6
- require('../chunk-XB2D4NQK.cjs');
5
+ var _chunkYMI3X2YLcjs = require('../chunk-YMI3X2YL.cjs');
6
+ require('../chunk-NKWHDI4C.cjs');
7
7
  require('../chunk-JDEXZGIY.cjs');
8
8
  require('../chunk-KWLSBTB2.cjs');
9
9
  require('../chunk-2BSFYU22.cjs');
10
10
 
11
11
 
12
- exports.VoiceSessionControls = _chunkUW67GSZ4cjs.VoiceSessionControls;
12
+ exports.VoiceSessionControls = _chunkYMI3X2YLcjs.VoiceSessionControls;
@@ -15,11 +15,13 @@ interface VoiceSessionControlsProps {
15
15
  /** Prevent starting a new session; ending an active session stays available. */
16
16
  disabled?: boolean;
17
17
  error?: string | null;
18
+ /** @deprecated Render transcripts in the conversation thread. Ignored by the controls. */
19
+ transcript?: string;
18
20
  /** Audio levels supplied by the host; no media connection is created by the kit. */
19
21
  volumeBands?: number[];
20
22
  /** Optional external audio store, so level changes only re-render these controls. */
21
23
  audioLevels?: VoiceAudioLevelsSource;
22
- labels?: Partial<Record<VoiceSessionState | "start" | "end" | "mute" | "unmute" | "muted" | "retry", string>>;
24
+ labels?: Partial<Record<VoiceSessionState | "start" | "end" | "mute" | "unmute" | "muted" | "retry" | "endShort" | "muteShort" | "unmuteShort" | "transcriptPlaceholder", string>>;
23
25
  size?: "icon" | "hero";
24
26
  className?: string;
25
27
  }
@@ -15,11 +15,13 @@ interface VoiceSessionControlsProps {
15
15
  /** Prevent starting a new session; ending an active session stays available. */
16
16
  disabled?: boolean;
17
17
  error?: string | null;
18
+ /** @deprecated Render transcripts in the conversation thread. Ignored by the controls. */
19
+ transcript?: string;
18
20
  /** Audio levels supplied by the host; no media connection is created by the kit. */
19
21
  volumeBands?: number[];
20
22
  /** Optional external audio store, so level changes only re-render these controls. */
21
23
  audioLevels?: VoiceAudioLevelsSource;
22
- labels?: Partial<Record<VoiceSessionState | "start" | "end" | "mute" | "unmute" | "muted" | "retry", string>>;
24
+ labels?: Partial<Record<VoiceSessionState | "start" | "end" | "mute" | "unmute" | "muted" | "retry" | "endShort" | "muteShort" | "unmuteShort" | "transcriptPlaceholder", string>>;
23
25
  size?: "icon" | "hero";
24
26
  className?: string;
25
27
  }
@@ -2,8 +2,8 @@
2
2
  "use client";
3
3
  import {
4
4
  VoiceSessionControls
5
- } from "../chunk-KUG4ONYC.js";
6
- import "../chunk-VBKJXNEL.js";
5
+ } from "../chunk-KF4X37DP.js";
6
+ import "../chunk-5OF6D3GH.js";
7
7
  import "../chunk-W326GKML.js";
8
8
  import "../chunk-G6SRSWXB.js";
9
9
  import "../chunk-GJ7S3L6R.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epicbagel/saas-kit",
3
- "version": "1.10.0",
3
+ "version": "1.11.1",
4
4
  "description": "Accessible React primitives, layout components and design tokens for SaaS apps, built on Radix UI and Tailwind CSS v4.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -1,223 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
-
3
-
4
- var _chunkJDEXZGIYcjs = require('./chunk-JDEXZGIY.cjs');
5
-
6
-
7
- var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
8
-
9
-
10
- var _chunkO6F3LVZYcjs = require('./chunk-O6F3LVZY.cjs');
11
-
12
- // src/primitives/voice-dictation-button.tsx
13
-
14
-
15
-
16
-
17
-
18
- var _react = require('react');
19
- var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
20
- var _lucidereact = require('lucide-react');
21
- var _jsxruntime = require('react/jsx-runtime');
22
- function VoiceDictationButton({
23
- onCommit,
24
- onCancel,
25
- title = "Dictate your message",
26
- caption = "listening",
27
- lang = "en-US",
28
- continuous = true,
29
- className,
30
- size = "sm",
31
- showLabel = false,
32
- children,
33
- disabled = false,
34
- visibility = "visible",
35
- shrink = true
36
- }) {
37
- const [open, setOpen] = _react.useState.call(void 0, false);
38
- const capture = _chunkO6F3LVZYcjs.useDictation.call(void 0, { lang, continuous });
39
- const { transcript, interimTranscript: interim, supported, error } = capture;
40
- const generation = _react.useRef.call(void 0, 0);
41
- const finishing = _react.useRef.call(void 0, false);
42
- const busy = capture.state === "requesting" || capture.state === "transcribing";
43
- const openOverlay = _react.useCallback.call(void 0, () => {
44
- generation.current++;
45
- finishing.current = false;
46
- setOpen(true);
47
- void capture.start();
48
- }, [capture.start]);
49
- const closeOverlay = _react.useCallback.call(void 0, () => {
50
- generation.current++;
51
- finishing.current = false;
52
- capture.cancel();
53
- setOpen(false);
54
- }, [capture.cancel]);
55
- const handleDone = _react.useCallback.call(void 0, async () => {
56
- if (finishing.current || busy) return;
57
- if (capture.state === "error" && !capture.canRetry) {
58
- void capture.start();
59
- return;
60
- }
61
- finishing.current = true;
62
- const started = generation.current;
63
- const final = await (capture.canRetry ? capture.retry() : capture.stop());
64
- if (started !== generation.current) return;
65
- finishing.current = false;
66
- if (final === null) return;
67
- closeOverlay();
68
- if (final) onCommit(final);
69
- else _optionalChain([onCancel, 'optionalCall', _ => _()]);
70
- }, [busy, capture.canRetry, capture.retry, capture.start, capture.state, capture.stop, onCommit, onCancel, closeOverlay]);
71
- const handleCancel = _react.useCallback.call(void 0, () => {
72
- closeOverlay();
73
- _optionalChain([onCancel, 'optionalCall', _2 => _2()]);
74
- }, [closeOverlay, onCancel]);
75
- _react.useEffect.call(void 0, () => {
76
- if (open && capture.state === "idle") handleCancel();
77
- }, [capture.state, handleCancel, open]);
78
- _react.useEffect.call(void 0, () => {
79
- if (!open) return;
80
- const onKey = (e) => {
81
- if (e.key === "Enter" && !e.shiftKey) {
82
- e.preventDefault();
83
- void handleDone();
84
- }
85
- };
86
- document.addEventListener("keydown", onKey);
87
- return () => document.removeEventListener("keydown", onKey);
88
- }, [open, handleDone]);
89
- _react.useEffect.call(void 0, () => {
90
- return () => {
91
- generation.current++;
92
- };
93
- }, []);
94
- if (!supported) return null;
95
- const displayTranscript = `${transcript}${interim ? (transcript ? " " : "") + interim : ""}`;
96
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
97
- children ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
98
- "button",
99
- {
100
- type: "button",
101
- onClick: openOverlay,
102
- disabled,
103
- "aria-label": "Start dictation",
104
- className: _chunkKWLSBTB2cjs.cn.call(void 0, visibility === "hidden" && "hidden", className),
105
- children
106
- }
107
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
108
- _chunkJDEXZGIYcjs.Button,
109
- {
110
- type: "button",
111
- onClick: openOverlay,
112
- disabled,
113
- variant: "outline",
114
- size,
115
- "aria-label": "Start dictation",
116
- className: _chunkKWLSBTB2cjs.cn.call(void 0, "transition-colors", visibility === "hidden" && "hidden", !shrink && "shrink-0", className),
117
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center justify-center gap-2", children: [
118
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Mic, { className: "h-4 w-4" }),
119
- showLabel && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Speak" })
120
- ] })
121
- }
122
- ),
123
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
124
- DialogPrimitive.Root,
125
- {
126
- open,
127
- onOpenChange: (next) => {
128
- if (!next) handleCancel();
129
- },
130
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Portal, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
131
- DialogPrimitive.Content,
132
- {
133
- "aria-label": "Voice dictation",
134
- onOpenAutoFocus: (e) => e.preventDefault(),
135
- onMouseDown: (e) => {
136
- if (e.target === e.currentTarget) handleCancel();
137
- },
138
- className: "fixed inset-0 z-[200] flex flex-col bg-background outline-hidden md:items-center md:justify-center md:bg-black/40 md:backdrop-blur-sm",
139
- children: [
140
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Title, { className: "sr-only", children: "Voice dictation" }),
141
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Description, { className: "sr-only", children: "Record your message, then choose Done to add the text. Cancel discards the recording." }),
142
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 md:flex-initial w-full md:max-w-lg md:rounded-xl bg-background flex flex-col md:max-h-[80vh] md:shadow-2xl md:border md:border-border", children: [
143
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between px-4 py-3 border-b border-border md:rounded-t-xl", children: [
144
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "status", className: "font-mono text-xs uppercase tracking-wider text-muted-foreground", children: capture.state === "transcribing" ? "transcribing" : capture.state === "requesting" ? "microphone" : caption }),
145
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
146
- "button",
147
- {
148
- type: "button",
149
- onClick: handleCancel,
150
- "aria-label": "Cancel",
151
- className: "p-1 -m-1 rounded-sm hover:bg-muted/60 transition-colors",
152
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { className: "h-4 w-4" })
153
- }
154
- )
155
- ] }),
156
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 flex flex-col items-center justify-center px-6 text-center", children: [
157
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative w-24 h-24 mb-10 flex items-center justify-center", children: [
158
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
159
- "span",
160
- {
161
- "aria-hidden": true,
162
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
163
- "absolute inset-0 rounded-full",
164
- error || busy || capture.state !== "recording" ? "bg-destructive/20" : "bg-destructive/20 animate-ping"
165
- )
166
- }
167
- ),
168
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
169
- "span",
170
- {
171
- "aria-hidden": true,
172
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
173
- "absolute inset-2 rounded-full",
174
- "bg-destructive/40"
175
- )
176
- }
177
- ),
178
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Mic, { className: "relative h-9 w-9 text-destructive-foreground" })
179
- ] }),
180
- title && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-base font-medium text-muted-foreground mb-3", children: title }),
181
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xl md:text-2xl leading-relaxed min-h-[5rem] max-w-xl text-foreground", children: displayTranscript ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
182
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: transcript }),
183
- interim && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "text-muted-foreground", children: [
184
- transcript ? " " : "",
185
- interim
186
- ] })
187
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground italic text-base", children: capture.state === "transcribing" ? "Converting your recording to text\u2026" : capture.state === "requesting" ? "Allow microphone access to start." : "Start speaking, then choose Done." }) }),
188
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { role: "alert", className: "text-sm text-destructive mt-4", children: error })
189
- ] }),
190
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border-t border-border px-4 py-4 pb-[calc(1rem+env(safe-area-inset-bottom))] md:pb-4 md:rounded-b-xl flex flex-col items-stretch gap-2", children: [
191
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
192
- _chunkJDEXZGIYcjs.Button,
193
- {
194
- size: "lg",
195
- className: "h-12 w-full",
196
- onClick: () => void handleDone(),
197
- disabled: busy,
198
- children: capture.state === "transcribing" ? "Transcribing\u2026" : capture.canRetry ? "Retry transcription" : error ? "Try again" : "Done"
199
- }
200
- ),
201
- capture.canRetry && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJDEXZGIYcjs.Button, { variant: "ghost", onClick: () => void capture.start(), children: "Record again" }),
202
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
203
- "button",
204
- {
205
- type: "button",
206
- onClick: handleCancel,
207
- className: "text-sm text-muted-foreground hover:text-foreground py-1",
208
- children: "Cancel"
209
- }
210
- )
211
- ] })
212
- ] })
213
- ]
214
- }
215
- ) })
216
- }
217
- )
218
- ] });
219
- }
220
-
221
-
222
-
223
- exports.VoiceDictationButton = VoiceDictationButton;