@epicbagel/saas-kit 1.0.0 → 1.1.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 (120) hide show
  1. package/README.md +38 -1
  2. package/THIRD_PARTY_NOTICES.md +13 -7
  3. package/dist/chunk-2AU7ZRGX.cjs +96 -0
  4. package/dist/chunk-2BTDBZYN.cjs +154 -0
  5. package/dist/chunk-2HV2KKOE.cjs +38 -0
  6. package/dist/chunk-2KFZQJH5.cjs +29 -0
  7. package/dist/chunk-32Q4XOTU.cjs +204 -0
  8. package/dist/chunk-42RTTHND.js +29 -0
  9. package/dist/chunk-6FC65AZQ.js +38 -0
  10. package/dist/chunk-6V4XMQ6D.js +118 -0
  11. package/dist/chunk-B765DSRG.cjs +66 -0
  12. package/dist/chunk-ELPV44S6.cjs +44 -0
  13. package/dist/chunk-EOUO3ORO.cjs +244 -0
  14. package/dist/chunk-EZCKWTH7.js +204 -0
  15. package/dist/chunk-F366BHWH.js +116 -0
  16. package/dist/chunk-GFG2R5BZ.js +132 -0
  17. package/dist/chunk-HAC32ALJ.js +244 -0
  18. package/dist/chunk-I5UQSBBZ.cjs +118 -0
  19. package/dist/chunk-INNGGLMZ.js +44 -0
  20. package/dist/chunk-IW4ZIXXG.js +66 -0
  21. package/dist/chunk-JZOBIPFC.js +96 -0
  22. package/dist/chunk-KENBU3NV.cjs +27 -0
  23. package/dist/chunk-MHYAVXOE.js +159 -0
  24. package/dist/chunk-RIWLAMME.cjs +159 -0
  25. package/dist/chunk-SUB4BAYE.cjs +73 -0
  26. package/dist/chunk-THWIJG5C.js +73 -0
  27. package/dist/chunk-V4YWTRLD.cjs +116 -0
  28. package/dist/chunk-VY5U4VGV.js +27 -0
  29. package/dist/chunk-XABXUP6L.cjs +132 -0
  30. package/dist/chunk-Z45YKVAM.js +154 -0
  31. package/dist/primitives/action-dock.cjs +8 -0
  32. package/dist/primitives/action-dock.d.cts +10 -0
  33. package/dist/primitives/action-dock.d.ts +10 -0
  34. package/dist/primitives/action-dock.js +8 -0
  35. package/dist/primitives/alert.d.cts +1 -1
  36. package/dist/primitives/alert.d.ts +1 -1
  37. package/dist/primitives/attachment.cjs +25 -203
  38. package/dist/primitives/attachment.d.cts +1 -1
  39. package/dist/primitives/attachment.d.ts +1 -1
  40. package/dist/primitives/attachment.js +12 -190
  41. package/dist/primitives/badge.d.cts +1 -1
  42. package/dist/primitives/badge.d.ts +1 -1
  43. package/dist/primitives/board-view.cjs +3 -3
  44. package/dist/primitives/board-view.js +2 -2
  45. package/dist/primitives/bubble.cjs +14 -0
  46. package/dist/primitives/bubble.d.cts +21 -0
  47. package/dist/primitives/bubble.d.ts +21 -0
  48. package/dist/primitives/bubble.js +14 -0
  49. package/dist/primitives/button.d.cts +2 -2
  50. package/dist/primitives/button.d.ts +2 -2
  51. package/dist/primitives/chat.cjs +864 -0
  52. package/dist/primitives/chat.d.cts +326 -0
  53. package/dist/primitives/chat.d.ts +326 -0
  54. package/dist/primitives/chat.js +864 -0
  55. package/dist/primitives/connection.cjs +6 -6
  56. package/dist/primitives/connection.js +7 -7
  57. package/dist/primitives/file-dropzone.cjs +7 -113
  58. package/dist/primitives/file-dropzone.js +6 -112
  59. package/dist/primitives/input-group.cjs +21 -0
  60. package/dist/primitives/input-group.d.cts +20 -0
  61. package/dist/primitives/input-group.d.ts +20 -0
  62. package/dist/primitives/input-group.js +21 -0
  63. package/dist/primitives/item.cjs +197 -0
  64. package/dist/primitives/item.d.cts +28 -0
  65. package/dist/primitives/item.d.ts +28 -0
  66. package/dist/primitives/item.js +197 -0
  67. package/dist/primitives/lazy-markdown.cjs +10 -0
  68. package/dist/primitives/lazy-markdown.d.cts +20 -0
  69. package/dist/primitives/lazy-markdown.d.ts +20 -0
  70. package/dist/primitives/lazy-markdown.js +10 -0
  71. package/dist/primitives/markdown.cjs +17 -0
  72. package/dist/primitives/markdown.d.cts +32 -0
  73. package/dist/primitives/markdown.d.ts +32 -0
  74. package/dist/primitives/markdown.js +17 -0
  75. package/dist/primitives/marker.cjs +14 -0
  76. package/dist/primitives/marker.d.cts +15 -0
  77. package/dist/primitives/marker.d.ts +15 -0
  78. package/dist/primitives/marker.js +14 -0
  79. package/dist/primitives/message-scroller.cjs +26 -0
  80. package/dist/primitives/message-scroller.d.cts +16 -0
  81. package/dist/primitives/message-scroller.d.ts +16 -0
  82. package/dist/primitives/message-scroller.js +26 -0
  83. package/dist/primitives/message.cjs +7 -84
  84. package/dist/primitives/message.js +8 -85
  85. package/dist/primitives/resource-list.cjs +3 -3
  86. package/dist/primitives/resource-list.js +2 -2
  87. package/dist/primitives/rich-text.cjs +3 -38
  88. package/dist/primitives/rich-text.js +3 -38
  89. package/dist/primitives/section-header.d.cts +1 -1
  90. package/dist/primitives/section-header.d.ts +1 -1
  91. package/dist/primitives/spinner.cjs +23 -0
  92. package/dist/primitives/spinner.d.cts +6 -0
  93. package/dist/primitives/spinner.d.ts +6 -0
  94. package/dist/primitives/spinner.js +23 -0
  95. package/dist/primitives/suggestion.cjs +11 -0
  96. package/dist/primitives/suggestion.d.cts +19 -0
  97. package/dist/primitives/suggestion.d.ts +19 -0
  98. package/dist/primitives/suggestion.js +11 -0
  99. package/dist/primitives/switch-field.cjs +2 -2
  100. package/dist/primitives/switch-field.js +3 -3
  101. package/dist/primitives/textarea.cjs +4 -33
  102. package/dist/primitives/textarea.js +3 -32
  103. package/dist/primitives/toggle-group.d.cts +2 -2
  104. package/dist/primitives/toggle-group.d.ts +2 -2
  105. package/dist/primitives/toggle.d.cts +2 -2
  106. package/dist/primitives/toggle.d.ts +2 -2
  107. package/dist/primitives/trace.cjs +23 -0
  108. package/dist/primitives/trace.d.cts +22 -0
  109. package/dist/primitives/trace.d.ts +22 -0
  110. package/dist/primitives/trace.js +23 -0
  111. package/dist/primitives/voice-dictation-button.cjs +5 -239
  112. package/dist/primitives/voice-dictation-button.js +4 -238
  113. package/package.json +125 -2
  114. package/src/styles/components/bubble.css +81 -0
  115. package/src/styles/components/marker.css +27 -0
  116. package/src/styles/components/message-scroller.css +11 -0
  117. package/src/styles/components.css +3 -0
  118. package/src/styles/utilities.css +3 -2
  119. package/dist/{chunk-UGF2K6NR.js → chunk-HRLP4BHJ.js} +6 -6
  120. package/dist/{chunk-RWWOFWLP.cjs → chunk-IH3COANJ.cjs} +3 -3
@@ -0,0 +1,116 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-G6SRSWXB.js";
5
+
6
+ // src/primitives/bubble.tsx
7
+ import { cva } from "class-variance-authority";
8
+ import { Slot } from "radix-ui";
9
+ import { jsx } from "react/jsx-runtime";
10
+ function BubbleGroup({ className, ...props }) {
11
+ return /* @__PURE__ */ jsx(
12
+ "div",
13
+ {
14
+ "data-slot": "bubble-group",
15
+ className: cn("cn-bubble-group flex min-w-0 flex-col", className),
16
+ ...props
17
+ }
18
+ );
19
+ }
20
+ var bubbleVariants = cva(
21
+ "cn-bubble group/bubble relative flex w-fit min-w-0 flex-col",
22
+ {
23
+ variants: {
24
+ variant: {
25
+ default: "cn-bubble-variant-default",
26
+ secondary: "cn-bubble-variant-secondary",
27
+ muted: "cn-bubble-variant-muted",
28
+ tinted: "cn-bubble-variant-tinted",
29
+ outline: "cn-bubble-variant-outline",
30
+ ghost: "cn-bubble-variant-ghost",
31
+ destructive: "cn-bubble-variant-destructive"
32
+ }
33
+ },
34
+ defaultVariants: {
35
+ variant: "default"
36
+ }
37
+ }
38
+ );
39
+ function Bubble({
40
+ variant = "default",
41
+ align = "start",
42
+ className,
43
+ ...props
44
+ }) {
45
+ return /* @__PURE__ */ jsx(
46
+ "div",
47
+ {
48
+ "data-slot": "bubble",
49
+ "data-variant": variant,
50
+ "data-align": align,
51
+ className: cn(bubbleVariants({ variant }), className),
52
+ ...props
53
+ }
54
+ );
55
+ }
56
+ function BubbleContent({
57
+ asChild = false,
58
+ className,
59
+ ...props
60
+ }) {
61
+ const Comp = asChild ? Slot.Root : "div";
62
+ return /* @__PURE__ */ jsx(
63
+ Comp,
64
+ {
65
+ "data-slot": "bubble-content",
66
+ className: cn(
67
+ "cn-bubble-content w-fit max-w-full min-w-0 overflow-hidden wrap-break-word [button]:text-left [button,a]:transition-colors",
68
+ className
69
+ ),
70
+ ...props
71
+ }
72
+ );
73
+ }
74
+ var bubbleReactionsVariants = cva(
75
+ "cn-bubble-reactions absolute z-10 flex w-fit items-center justify-center",
76
+ {
77
+ variants: {
78
+ side: {
79
+ top: "cn-bubble-reactions-side-top",
80
+ bottom: "cn-bubble-reactions-side-bottom"
81
+ },
82
+ align: {
83
+ start: "cn-bubble-reactions-align-start",
84
+ end: "cn-bubble-reactions-align-end"
85
+ }
86
+ },
87
+ defaultVariants: {
88
+ side: "bottom",
89
+ align: "end"
90
+ }
91
+ }
92
+ );
93
+ function BubbleReactions({
94
+ side = "bottom",
95
+ align = "end",
96
+ className,
97
+ ...props
98
+ }) {
99
+ return /* @__PURE__ */ jsx(
100
+ "div",
101
+ {
102
+ "data-slot": "bubble-reactions",
103
+ "data-align": align,
104
+ "data-side": side,
105
+ className: cn(bubbleReactionsVariants({ side, align }), className),
106
+ ...props
107
+ }
108
+ );
109
+ }
110
+
111
+ export {
112
+ BubbleGroup,
113
+ Bubble,
114
+ BubbleContent,
115
+ BubbleReactions
116
+ };
@@ -0,0 +1,132 @@
1
+ "use client";
2
+ import {
3
+ Button
4
+ } from "./chunk-HQRWRRZJ.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-G6SRSWXB.js";
8
+
9
+ // src/primitives/message-scroller.tsx
10
+ import {
11
+ MessageScroller as MessageScrollerPrimitive,
12
+ useMessageScroller,
13
+ useMessageScrollerScrollable,
14
+ useMessageScrollerVisibility
15
+ } from "@shadcn/react/message-scroller";
16
+ import { ArrowDown } from "lucide-react";
17
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
18
+ function MessageScrollerProvider(props) {
19
+ return /* @__PURE__ */ jsx(MessageScrollerPrimitive.Provider, { ...props });
20
+ }
21
+ function MessageScroller({
22
+ className,
23
+ ...props
24
+ }) {
25
+ return /* @__PURE__ */ jsx(
26
+ MessageScrollerPrimitive.Root,
27
+ {
28
+ "data-slot": "message-scroller",
29
+ className: cn(
30
+ "cn-message-scroller group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden",
31
+ className
32
+ ),
33
+ ...props
34
+ }
35
+ );
36
+ }
37
+ function MessageScrollerViewport({
38
+ className,
39
+ ...props
40
+ }) {
41
+ return /* @__PURE__ */ jsx(
42
+ MessageScrollerPrimitive.Viewport,
43
+ {
44
+ "data-slot": "message-scroller-viewport",
45
+ className: cn(
46
+ // @shadcn/react 0.3: while an automatic scroll runs the scrollbar goes
47
+ // transparent rather than away (so the gutter, and the text, never
48
+ // shift), and the viewport stays invisible until its opening scroll
49
+ // position is applied, so a long thread never flashes its first turn.
50
+ "cn-message-scroller-viewport size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-thumb-transparent data-autoscrolling:scrollbar-track-transparent data-pending-scroll:invisible",
51
+ className
52
+ ),
53
+ ...props
54
+ }
55
+ );
56
+ }
57
+ function MessageScrollerContent({
58
+ className,
59
+ ...props
60
+ }) {
61
+ return /* @__PURE__ */ jsx(
62
+ MessageScrollerPrimitive.Content,
63
+ {
64
+ "data-slot": "message-scroller-content",
65
+ className: cn(
66
+ "cn-message-scroller-content flex h-max min-h-full flex-col",
67
+ className
68
+ ),
69
+ ...props
70
+ }
71
+ );
72
+ }
73
+ function MessageScrollerItem({
74
+ className,
75
+ scrollAnchor = false,
76
+ ...props
77
+ }) {
78
+ return /* @__PURE__ */ jsx(
79
+ MessageScrollerPrimitive.Item,
80
+ {
81
+ "data-slot": "message-scroller-item",
82
+ scrollAnchor,
83
+ className: cn(
84
+ "cn-message-scroller-item min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]",
85
+ className
86
+ ),
87
+ ...props
88
+ }
89
+ );
90
+ }
91
+ function MessageScrollerButton({
92
+ direction = "end",
93
+ className,
94
+ children,
95
+ render,
96
+ variant = "secondary",
97
+ size = "icon-sm",
98
+ ...props
99
+ }) {
100
+ return /* @__PURE__ */ jsx(
101
+ MessageScrollerPrimitive.Button,
102
+ {
103
+ "data-slot": "message-scroller-button",
104
+ "data-direction": direction,
105
+ "data-variant": variant,
106
+ "data-size": size,
107
+ direction,
108
+ className: cn(
109
+ "cn-message-scroller-button absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",
110
+ className
111
+ ),
112
+ render: render ?? /* @__PURE__ */ jsx(Button, { variant, size }),
113
+ ...props,
114
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
115
+ /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" }),
116
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: direction === "end" ? "Scroll to end" : "Scroll to start" })
117
+ ] })
118
+ }
119
+ );
120
+ }
121
+
122
+ export {
123
+ useMessageScroller,
124
+ useMessageScrollerScrollable,
125
+ useMessageScrollerVisibility,
126
+ MessageScrollerProvider,
127
+ MessageScroller,
128
+ MessageScrollerViewport,
129
+ MessageScrollerContent,
130
+ MessageScrollerItem,
131
+ MessageScrollerButton
132
+ };
@@ -0,0 +1,244 @@
1
+ "use client";
2
+ import {
3
+ Button
4
+ } from "./chunk-HQRWRRZJ.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-G6SRSWXB.js";
8
+
9
+ // src/primitives/voice-dictation-button.tsx
10
+ import {
11
+ useCallback,
12
+ useEffect,
13
+ useRef,
14
+ useState
15
+ } from "react";
16
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
17
+ import { Mic, X } from "lucide-react";
18
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
19
+ function VoiceDictationButton({
20
+ onCommit,
21
+ onCancel,
22
+ title = "Dictate your message",
23
+ caption = "listening",
24
+ lang = "en-US",
25
+ continuous = true,
26
+ className,
27
+ size = "sm",
28
+ showLabel = false,
29
+ children,
30
+ disabled = false,
31
+ visibility = "visible",
32
+ shrink = true
33
+ }) {
34
+ const [supported, setSupported] = useState(false);
35
+ const [open, setOpen] = useState(false);
36
+ const [transcript, setTranscript] = useState("");
37
+ const [interim, setInterim] = useState("");
38
+ const [errored, setErrored] = useState(false);
39
+ const recognitionRef = useRef(null);
40
+ useEffect(() => {
41
+ const w = window;
42
+ const Ctor = w.SpeechRecognition ?? w.webkitSpeechRecognition;
43
+ setSupported(typeof Ctor === "function");
44
+ }, []);
45
+ const stop = useCallback(() => {
46
+ recognitionRef.current?.stop();
47
+ recognitionRef.current = null;
48
+ }, []);
49
+ const startRecognition = useCallback(() => {
50
+ const w = window;
51
+ const Ctor = w.SpeechRecognition ?? w.webkitSpeechRecognition;
52
+ if (!Ctor) return;
53
+ const rec = new Ctor();
54
+ rec.continuous = continuous;
55
+ rec.interimResults = true;
56
+ rec.lang = lang;
57
+ rec.onresult = (event) => {
58
+ let finalChunk = "";
59
+ let interimChunk = "";
60
+ for (let i = event.resultIndex; i < event.results.length; i++) {
61
+ const r = event.results[i];
62
+ if (!r) continue;
63
+ if (r.isFinal) finalChunk += r[0].transcript;
64
+ else interimChunk += r[0].transcript;
65
+ }
66
+ if (finalChunk) {
67
+ setTranscript((prev) => prev ? prev + " " + finalChunk : finalChunk);
68
+ setInterim("");
69
+ } else if (interimChunk) {
70
+ setInterim(interimChunk);
71
+ }
72
+ };
73
+ rec.onerror = () => {
74
+ setErrored(true);
75
+ };
76
+ rec.onend = () => {
77
+ recognitionRef.current = null;
78
+ };
79
+ recognitionRef.current = rec;
80
+ setErrored(false);
81
+ rec.start();
82
+ }, [continuous, lang]);
83
+ const openOverlay = useCallback(() => {
84
+ setTranscript("");
85
+ setInterim("");
86
+ setOpen(true);
87
+ startRecognition();
88
+ }, [startRecognition]);
89
+ const closeOverlay = useCallback(() => {
90
+ stop();
91
+ setOpen(false);
92
+ setInterim("");
93
+ }, [stop]);
94
+ const handleDone = useCallback(() => {
95
+ const final = `${transcript} ${interim}`.trim();
96
+ closeOverlay();
97
+ if (final) onCommit(final);
98
+ else onCancel?.();
99
+ }, [transcript, interim, onCommit, onCancel, closeOverlay]);
100
+ const handleCancel = useCallback(() => {
101
+ closeOverlay();
102
+ onCancel?.();
103
+ }, [closeOverlay, onCancel]);
104
+ useEffect(() => {
105
+ if (!open) return;
106
+ const onKey = (e) => {
107
+ if (e.key === "Enter" && !e.shiftKey) handleDone();
108
+ };
109
+ document.addEventListener("keydown", onKey);
110
+ return () => document.removeEventListener("keydown", onKey);
111
+ }, [open, handleDone]);
112
+ useEffect(() => {
113
+ return () => {
114
+ recognitionRef.current?.abort();
115
+ };
116
+ }, []);
117
+ if (!supported) return null;
118
+ const displayTranscript = `${transcript}${interim ? (transcript ? " " : "") + interim : ""}`;
119
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
120
+ children ? /* @__PURE__ */ jsx(
121
+ "button",
122
+ {
123
+ type: "button",
124
+ onClick: openOverlay,
125
+ disabled,
126
+ "aria-label": "Start dictation",
127
+ className: cn(visibility === "hidden" && "hidden", className),
128
+ children
129
+ }
130
+ ) : /* @__PURE__ */ jsx(
131
+ Button,
132
+ {
133
+ type: "button",
134
+ onClick: openOverlay,
135
+ disabled,
136
+ variant: "outline",
137
+ size,
138
+ "aria-label": "Start dictation",
139
+ className: cn("transition-colors", visibility === "hidden" && "hidden", !shrink && "shrink-0", className),
140
+ children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-2", children: [
141
+ /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" }),
142
+ showLabel && /* @__PURE__ */ jsx("span", { children: "Speak" })
143
+ ] })
144
+ }
145
+ ),
146
+ /* @__PURE__ */ jsx(
147
+ DialogPrimitive.Root,
148
+ {
149
+ open,
150
+ onOpenChange: (next) => {
151
+ if (!next) closeOverlay();
152
+ },
153
+ children: /* @__PURE__ */ jsx(DialogPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
154
+ DialogPrimitive.Content,
155
+ {
156
+ "aria-label": "Voice dictation",
157
+ onOpenAutoFocus: (e) => e.preventDefault(),
158
+ onMouseDown: (e) => {
159
+ if (e.target === e.currentTarget) handleCancel();
160
+ },
161
+ 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",
162
+ children: [
163
+ /* @__PURE__ */ jsx(DialogPrimitive.Title, { className: "sr-only", children: "Voice dictation" }),
164
+ /* @__PURE__ */ jsxs("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: [
165
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border md:rounded-t-xl", children: [
166
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-xs uppercase tracking-wider text-muted-foreground", children: caption }),
167
+ /* @__PURE__ */ jsx(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ onClick: handleCancel,
172
+ "aria-label": "Cancel",
173
+ className: "p-1 -m-1 rounded-sm hover:bg-muted/60 transition-colors",
174
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
175
+ }
176
+ )
177
+ ] }),
178
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center px-6 text-center", children: [
179
+ /* @__PURE__ */ jsxs("div", { className: "relative w-24 h-24 mb-10 flex items-center justify-center", children: [
180
+ /* @__PURE__ */ jsx(
181
+ "span",
182
+ {
183
+ "aria-hidden": true,
184
+ className: cn(
185
+ "absolute inset-0 rounded-full",
186
+ errored ? "bg-destructive/20" : "bg-destructive/20 animate-ping"
187
+ )
188
+ }
189
+ ),
190
+ /* @__PURE__ */ jsx(
191
+ "span",
192
+ {
193
+ "aria-hidden": true,
194
+ className: cn(
195
+ "absolute inset-2 rounded-full",
196
+ errored ? "bg-destructive/40" : "bg-destructive/40"
197
+ )
198
+ }
199
+ ),
200
+ /* @__PURE__ */ jsx(Mic, { className: "relative h-9 w-9 text-destructive-foreground" })
201
+ ] }),
202
+ title && /* @__PURE__ */ jsx("div", { className: "text-base font-medium text-muted-foreground mb-3", children: title }),
203
+ /* @__PURE__ */ jsx("p", { className: "text-xl md:text-2xl leading-relaxed min-h-[5rem] max-w-xl text-foreground", children: displayTranscript ? /* @__PURE__ */ jsxs(Fragment, { children: [
204
+ /* @__PURE__ */ jsx("span", { children: transcript }),
205
+ interim && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
206
+ transcript ? " " : "",
207
+ interim
208
+ ] })
209
+ ] }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground italic text-base", children: "Start speaking \u2014 I'm listening." }) }),
210
+ errored && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive mt-4", children: "Couldn't access the microphone. Check permissions." })
211
+ ] }),
212
+ /* @__PURE__ */ jsxs("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: [
213
+ /* @__PURE__ */ jsx(
214
+ Button,
215
+ {
216
+ size: "lg",
217
+ className: "h-12 w-full",
218
+ onClick: handleDone,
219
+ disabled: !displayTranscript.trim(),
220
+ children: "Done"
221
+ }
222
+ ),
223
+ /* @__PURE__ */ jsx(
224
+ "button",
225
+ {
226
+ type: "button",
227
+ onClick: handleCancel,
228
+ className: "text-sm text-muted-foreground hover:text-foreground py-1",
229
+ children: "Cancel"
230
+ }
231
+ )
232
+ ] })
233
+ ] })
234
+ ]
235
+ }
236
+ ) })
237
+ }
238
+ )
239
+ ] });
240
+ }
241
+
242
+ export {
243
+ VoiceDictationButton
244
+ };
@@ -0,0 +1,118 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } 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 _chunk373W6VADcjs = require('./chunk-373W6VAD.cjs');
5
+
6
+
7
+
8
+
9
+ var _chunkU2NES7VRcjs = require('./chunk-U2NES7VR.cjs');
10
+
11
+
12
+ var _chunkL4DH72UFcjs = require('./chunk-L4DH72UF.cjs');
13
+
14
+
15
+ var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
16
+
17
+ // src/primitives/file-dropzone.tsx
18
+ var _lucidereact = require('lucide-react');
19
+ var _react = require('react');
20
+ var _jsxruntime = require('react/jsx-runtime');
21
+ function FileDropzone({
22
+ onFile,
23
+ onFiles,
24
+ multiple = false,
25
+ accept,
26
+ disabled = false,
27
+ busy: externalBusy = false,
28
+ label = "Drop a file, or choose one",
29
+ description,
30
+ busyLabel = "Reading file\u2026",
31
+ icon,
32
+ variant = "dropzone",
33
+ className
34
+ }) {
35
+ const inputRef = _react.useRef.call(void 0, null);
36
+ const [dragging, setDragging] = _react.useState.call(void 0, false);
37
+ const [internalBusy, setInternalBusy] = _react.useState.call(void 0, false);
38
+ const busy = externalBusy || internalBusy;
39
+ async function select(files) {
40
+ if (files.length === 0 || disabled || busy) return;
41
+ setInternalBusy(true);
42
+ try {
43
+ if (multiple) {
44
+ await _optionalChain([onFiles, 'optionalCall', _ => _(files)]);
45
+ } else {
46
+ const first = files[0];
47
+ if (first) await _optionalChain([onFile, 'optionalCall', _2 => _2(first)]);
48
+ }
49
+ } finally {
50
+ setInternalBusy(false);
51
+ if (inputRef.current) inputRef.current.value = "";
52
+ }
53
+ }
54
+ function onDrop(event) {
55
+ event.preventDefault();
56
+ setDragging(false);
57
+ void select(Array.from(_nullishCoalesce(event.dataTransfer.files, () => ( []))));
58
+ }
59
+ const trigger = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
60
+ _chunkL4DH72UFcjs.Button,
61
+ {
62
+ type: "button",
63
+ "data-file-dropzone": "true",
64
+ variant: "outline",
65
+ size: variant === "icon" ? "icon" : "default",
66
+ "aria-label": variant === "icon" ? String(busy ? busyLabel : label) : void 0,
67
+ disabled: disabled || busy,
68
+ onClick: () => _optionalChain([inputRef, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.click, 'call', _5 => _5()]),
69
+ onDragEnter: (event) => {
70
+ event.preventDefault();
71
+ setDragging(true);
72
+ },
73
+ onDragOver: (event) => {
74
+ event.preventDefault();
75
+ setDragging(true);
76
+ },
77
+ onDragLeave: () => setDragging(false),
78
+ onDrop,
79
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
80
+ variant === "dropzone" ? "h-auto w-full flex-col whitespace-normal border-2 border-dashed px-6 py-8 text-center" : variant === "button" ? "w-fit" : "",
81
+ dragging && "border-primary bg-primary/5",
82
+ className
83
+ ),
84
+ children: [
85
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkKWLSBTB2cjs.cn.call(void 0,
86
+ "flex items-center justify-center text-muted-foreground",
87
+ variant === "dropzone" && "mb-2 h-10 w-10 rounded-full bg-muted"
88
+ ), children: busy ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Loader2, { className: "h-5 w-5 animate-spin" }) : _nullishCoalesce(icon, () => ( /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.FileUp, { className: "h-5 w-5" }))) }),
89
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: variant === "icon" ? "sr-only" : "font-medium", children: busy ? busyLabel : label }),
90
+ description && variant === "dropzone" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "muted", className: "mt-1 max-w-md text-xs", children: description })
91
+ ]
92
+ }
93
+ );
94
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
95
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
96
+ "input",
97
+ {
98
+ ref: inputRef,
99
+ type: "file",
100
+ accept,
101
+ multiple,
102
+ disabled: disabled || busy,
103
+ onChange: (event) => void select(Array.from(_nullishCoalesce(event.target.files, () => ( [])))),
104
+ className: "sr-only",
105
+ tabIndex: -1,
106
+ "aria-hidden": "true"
107
+ }
108
+ ),
109
+ variant === "icon" && description ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkU2NES7VRcjs.Tooltip, { children: [
110
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipTrigger, { asChild: true, children: trigger }),
111
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipContent, { children: description })
112
+ ] }) : trigger
113
+ ] });
114
+ }
115
+
116
+
117
+
118
+ exports.FileDropzone = FileDropzone;
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import {
3
+ cn
4
+ } from "./chunk-G6SRSWXB.js";
5
+
6
+ // src/primitives/rich-text.tsx
7
+ import { jsx } from "react/jsx-runtime";
8
+ function RichText({ size = "sm", tone = "default", className, ...props }) {
9
+ return /* @__PURE__ */ jsx(
10
+ "div",
11
+ {
12
+ "data-slot": "rich-text",
13
+ className: cn(
14
+ size === "sm" ? "text-sm" : "text-base",
15
+ tone === "soft" && "text-foreground/90",
16
+ tone === "muted" && "text-muted-foreground",
17
+ "leading-relaxed",
18
+ "[&_p]:mb-2 [&_p:last-child]:mb-0",
19
+ "[&_a]:font-medium [&_a]:underline [&_a]:underline-offset-4",
20
+ "[&_strong]:font-semibold",
21
+ "[&_h1]:mb-3 [&_h1]:mt-6 [&_h1]:text-xl [&_h1]:font-semibold [&_h1]:tracking-tight [&_h1:first-child]:mt-0",
22
+ "[&_h2]:mb-2 [&_h2]:mt-5 [&_h2]:text-base [&_h2]:font-semibold [&_h2]:tracking-tight [&_h2:first-child]:mt-0",
23
+ "[&_h3]:mb-2 [&_h3]:mt-4 [&_h3]:font-semibold [&_h3:first-child]:mt-0",
24
+ "[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5",
25
+ "[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5",
26
+ "[&_li]:my-1 [&_li>p]:mb-0",
27
+ "[&_blockquote]:my-3 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-4 [&_blockquote]:text-muted-foreground",
28
+ "[&_hr]:my-4 [&_hr]:border-border",
29
+ "[&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.875em]",
30
+ "[&_pre]:my-3 [&_pre]:overflow-x-auto [&_pre]:rounded-md [&_pre]:border [&_pre]:border-border [&_pre]:bg-muted/40 [&_pre]:p-3",
31
+ "[&_pre_code]:bg-transparent [&_pre_code]:p-0",
32
+ "[&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_table]:text-left",
33
+ "[&_th]:border-b [&_th]:border-border [&_th]:px-2 [&_th]:py-1.5 [&_th]:font-semibold",
34
+ "[&_td]:border-b [&_td]:border-border/70 [&_td]:px-2 [&_td]:py-1.5",
35
+ className
36
+ ),
37
+ ...props
38
+ }
39
+ );
40
+ }
41
+
42
+ export {
43
+ RichText
44
+ };