@epicbagel/saas-kit 1.0.0 → 1.2.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 +72 -3
  2. package/THIRD_PARTY_NOTICES.md +230 -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-B765DSRG.cjs +66 -0
  11. package/dist/chunk-ELPV44S6.cjs +44 -0
  12. package/dist/chunk-EOUO3ORO.cjs +244 -0
  13. package/dist/chunk-EZCKWTH7.js +204 -0
  14. package/dist/chunk-F366BHWH.js +116 -0
  15. package/dist/chunk-GFG2R5BZ.js +132 -0
  16. package/dist/chunk-HAC32ALJ.js +244 -0
  17. package/dist/chunk-INNGGLMZ.js +44 -0
  18. package/dist/chunk-IW4ZIXXG.js +66 -0
  19. package/dist/chunk-JZOBIPFC.js +96 -0
  20. package/dist/chunk-KADJ56AH.cjs +416 -0
  21. package/dist/chunk-KENBU3NV.cjs +27 -0
  22. package/dist/chunk-M7FYGAGO.js +416 -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/attachment.cjs +25 -203
  36. package/dist/primitives/attachment.d.cts +1 -1
  37. package/dist/primitives/attachment.d.ts +1 -1
  38. package/dist/primitives/attachment.js +12 -190
  39. package/dist/primitives/badge.d.cts +1 -1
  40. package/dist/primitives/badge.d.ts +1 -1
  41. package/dist/primitives/board-view.cjs +3 -3
  42. package/dist/primitives/board-view.js +2 -2
  43. package/dist/primitives/bubble.cjs +14 -0
  44. package/dist/primitives/bubble.d.cts +21 -0
  45. package/dist/primitives/bubble.d.ts +21 -0
  46. package/dist/primitives/bubble.js +14 -0
  47. package/dist/primitives/button.d.cts +3 -3
  48. package/dist/primitives/button.d.ts +3 -3
  49. package/dist/primitives/chat.cjs +881 -0
  50. package/dist/primitives/chat.d.cts +345 -0
  51. package/dist/primitives/chat.d.ts +345 -0
  52. package/dist/primitives/chat.js +881 -0
  53. package/dist/primitives/connection.cjs +6 -6
  54. package/dist/primitives/connection.js +7 -7
  55. package/dist/primitives/file-dropzone.cjs +7 -107
  56. package/dist/primitives/file-dropzone.d.cts +66 -3
  57. package/dist/primitives/file-dropzone.d.ts +66 -3
  58. package/dist/primitives/file-dropzone.js +13 -113
  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,416 @@
1
+ "use client";
2
+ import {
3
+ Text
4
+ } from "./chunk-EIY5LLSP.js";
5
+ import {
6
+ Tooltip,
7
+ TooltipContent,
8
+ TooltipTrigger
9
+ } from "./chunk-ZRLUUZHK.js";
10
+ import {
11
+ Button
12
+ } from "./chunk-HQRWRRZJ.js";
13
+ import {
14
+ cn
15
+ } from "./chunk-G6SRSWXB.js";
16
+
17
+ // src/primitives/file-dropzone.tsx
18
+ import { FileUp, Loader2 } from "lucide-react";
19
+ import { createPortal } from "react-dom";
20
+ import {
21
+ forwardRef,
22
+ useCallback,
23
+ useEffect,
24
+ useRef,
25
+ useState
26
+ } from "react";
27
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
28
+ function FileDropzone({
29
+ onFile,
30
+ onFiles,
31
+ multiple = false,
32
+ accept,
33
+ disabled = false,
34
+ busy: externalBusy = false,
35
+ label = "Drop a file, or choose one",
36
+ description,
37
+ busyLabel = "Reading file\u2026",
38
+ icon,
39
+ variant = "dropzone",
40
+ className
41
+ }) {
42
+ const inputRef = useRef(null);
43
+ const [dragging, setDragging] = useState(false);
44
+ const [internalBusy, setInternalBusy] = useState(false);
45
+ const busy = externalBusy || internalBusy;
46
+ useFileDropGuard();
47
+ async function select(files) {
48
+ if (files.length === 0 || disabled || busy) return;
49
+ setInternalBusy(true);
50
+ try {
51
+ if (multiple) {
52
+ await onFiles?.(files);
53
+ } else {
54
+ const first = files[0];
55
+ if (first) await onFile?.(first);
56
+ }
57
+ } finally {
58
+ setInternalBusy(false);
59
+ if (inputRef.current) inputRef.current.value = "";
60
+ }
61
+ }
62
+ function onDrop(event) {
63
+ event.preventDefault();
64
+ setDragging(false);
65
+ void select(Array.from(event.dataTransfer.files ?? []));
66
+ }
67
+ const trigger = /* @__PURE__ */ jsx(
68
+ Button,
69
+ {
70
+ type: "button",
71
+ "data-file-dropzone": "true",
72
+ variant: "outline",
73
+ size: variant === "icon" ? "icon" : "default",
74
+ "aria-label": variant === "icon" ? String(busy ? busyLabel : label) : void 0,
75
+ disabled: disabled || busy,
76
+ onClick: () => inputRef.current?.click(),
77
+ onDragEnter: (event) => {
78
+ event.preventDefault();
79
+ setDragging(true);
80
+ },
81
+ onDragOver: (event) => {
82
+ event.preventDefault();
83
+ setDragging(true);
84
+ },
85
+ onDragLeave: () => setDragging(false),
86
+ onDrop,
87
+ className: cn(
88
+ variant === "dropzone" ? "h-auto w-full flex-col whitespace-normal border-2 border-dashed px-6 py-8 text-center" : variant === "button" ? "w-fit" : "",
89
+ dragging && "border-primary bg-primary/5",
90
+ className
91
+ ),
92
+ children: /* @__PURE__ */ jsx(
93
+ FileDropPrompt,
94
+ {
95
+ variant,
96
+ icon: busy ? /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin" }) : icon ?? /* @__PURE__ */ jsx(FileUp, { className: "h-5 w-5" }),
97
+ label: busy ? busyLabel : label,
98
+ description
99
+ }
100
+ )
101
+ }
102
+ );
103
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
104
+ /* @__PURE__ */ jsx(
105
+ "input",
106
+ {
107
+ ref: inputRef,
108
+ type: "file",
109
+ accept,
110
+ multiple,
111
+ disabled: disabled || busy,
112
+ onChange: (event) => void select(Array.from(event.target.files ?? [])),
113
+ className: "sr-only",
114
+ tabIndex: -1,
115
+ "aria-hidden": "true"
116
+ }
117
+ ),
118
+ variant === "icon" && description ? /* @__PURE__ */ jsxs(Tooltip, { children: [
119
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: trigger }),
120
+ /* @__PURE__ */ jsx(TooltipContent, { children: description })
121
+ ] }) : trigger
122
+ ] });
123
+ }
124
+ function carriesFiles(data) {
125
+ if (!data) return false;
126
+ return Array.from(data.types ?? []).includes("Files") || (data.files?.length ?? 0) > 0;
127
+ }
128
+ function isNativeFileInput(target) {
129
+ const element = target;
130
+ return element?.tagName === "INPUT" && element.type === "file";
131
+ }
132
+ var inPageDrag = false;
133
+ var inPageDragUsers = 0;
134
+ var markInPageDrag = () => {
135
+ inPageDrag = true;
136
+ };
137
+ var clearInPageDrag = () => {
138
+ inPageDrag = false;
139
+ };
140
+ var clearAfterDrop = () => {
141
+ window.setTimeout(clearInPageDrag, 0);
142
+ };
143
+ var clearOnMove = () => {
144
+ if (inPageDrag) inPageDrag = false;
145
+ };
146
+ function trackInPageDrags() {
147
+ if (inPageDragUsers++ === 0) {
148
+ window.addEventListener("dragstart", markInPageDrag, true);
149
+ window.addEventListener("dragend", clearInPageDrag, true);
150
+ window.addEventListener("drop", clearAfterDrop);
151
+ window.addEventListener("mousemove", clearOnMove, { passive: true });
152
+ }
153
+ return () => {
154
+ if (--inPageDragUsers > 0) return;
155
+ window.removeEventListener("dragstart", markInPageDrag, true);
156
+ window.removeEventListener("dragend", clearInPageDrag, true);
157
+ window.removeEventListener("drop", clearAfterDrop);
158
+ window.removeEventListener("mousemove", clearOnMove);
159
+ inPageDrag = false;
160
+ };
161
+ }
162
+ function isUnclaimedFileDrag(event) {
163
+ return !event.defaultPrevented && !inPageDrag && carriesFiles(event.dataTransfer) && !isNativeFileInput(event.target);
164
+ }
165
+ function installFileDropGuard() {
166
+ if (typeof window === "undefined") return () => void 0;
167
+ const release = trackInPageDrags();
168
+ const onDragOver = (event) => {
169
+ if (!isUnclaimedFileDrag(event)) return;
170
+ event.preventDefault();
171
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "none";
172
+ };
173
+ const onDrop = (event) => {
174
+ if (isUnclaimedFileDrag(event)) event.preventDefault();
175
+ };
176
+ window.addEventListener("dragover", onDragOver);
177
+ window.addEventListener("drop", onDrop);
178
+ let installed = true;
179
+ return () => {
180
+ if (!installed) return;
181
+ installed = false;
182
+ window.removeEventListener("dragover", onDragOver);
183
+ window.removeEventListener("drop", onDrop);
184
+ release();
185
+ };
186
+ }
187
+ function useFileDropGuard(enabled = true) {
188
+ useEffect(() => enabled ? installFileDropGuard() : void 0, [enabled]);
189
+ }
190
+ function FileDropPrompt({
191
+ icon,
192
+ label,
193
+ description,
194
+ variant = "dropzone"
195
+ }) {
196
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
197
+ /* @__PURE__ */ jsx("span", { className: cn(
198
+ "flex items-center justify-center text-muted-foreground",
199
+ variant === "dropzone" && "mb-2 h-10 w-10 rounded-full bg-muted"
200
+ ), children: icon }),
201
+ /* @__PURE__ */ jsx("span", { className: variant === "icon" ? "sr-only" : "font-medium", children: label }),
202
+ description && variant === "dropzone" && /* @__PURE__ */ jsx(Text, { variant: "muted", className: "mt-1 max-w-md text-xs", children: description })
203
+ ] });
204
+ }
205
+ var DRAG_HEARTBEAT_MS = 1e3;
206
+ function visibleBand(element) {
207
+ const rect = element.getBoundingClientRect();
208
+ const viewport = window.innerHeight;
209
+ if (rect.top >= 0 && rect.bottom <= viewport) return null;
210
+ const top = Math.max(rect.top, 0);
211
+ const bottom = Math.min(rect.bottom, viewport);
212
+ return bottom > top ? { top: top - rect.top, height: bottom - top } : null;
213
+ }
214
+ var FileDropArea = forwardRef(function FileDropArea2({
215
+ onFiles,
216
+ disabled = false,
217
+ scope = "area",
218
+ label = "Drop to attach",
219
+ description,
220
+ icon,
221
+ className,
222
+ children,
223
+ onDragEnter,
224
+ onDragOver,
225
+ onDragLeave,
226
+ ...props
227
+ }, ref) {
228
+ const active = Boolean(onFiles) && !disabled;
229
+ const [dragging, setDragging] = useState(false);
230
+ const [band, setBand] = useState(null);
231
+ const root = useRef(null);
232
+ const entered = useRef([]);
233
+ useFileDropGuard(Boolean(onFiles));
234
+ const setRoot = useCallback(
235
+ (node) => {
236
+ root.current = node;
237
+ if (typeof ref === "function") ref(node);
238
+ else if (ref) ref.current = node;
239
+ },
240
+ [ref]
241
+ );
242
+ const reset = useCallback(() => {
243
+ entered.current = [];
244
+ setDragging(false);
245
+ }, []);
246
+ const enter = useCallback((target) => {
247
+ if (target && !entered.current.includes(target)) entered.current.push(target);
248
+ setDragging(true);
249
+ }, []);
250
+ const leave = useCallback((target, container) => {
251
+ entered.current = entered.current.filter(
252
+ (node) => node !== target && node instanceof Node && node.isConnected && container.contains(node)
253
+ );
254
+ if (entered.current.length === 0) setDragging(false);
255
+ }, []);
256
+ const deliver = useCallback(
257
+ (data) => {
258
+ const files = Array.from(data?.files ?? []);
259
+ if (files.length > 0) void onFiles?.(files);
260
+ },
261
+ [onFiles]
262
+ );
263
+ useEffect(() => {
264
+ if (scope !== "page" || !active) return;
265
+ const onEnter = (event) => {
266
+ if (!isUnclaimedFileDrag(event)) return;
267
+ event.preventDefault();
268
+ enter(event.target);
269
+ };
270
+ const onOver = (event) => {
271
+ if (!isUnclaimedFileDrag(event)) return;
272
+ event.preventDefault();
273
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "copy";
274
+ if (entered.current.length === 0) enter(event.target);
275
+ };
276
+ const onLeave = (event) => leave(event.target, document);
277
+ const onDrop = (event) => {
278
+ reset();
279
+ if (!isUnclaimedFileDrag(event)) return;
280
+ event.preventDefault();
281
+ deliver(event.dataTransfer);
282
+ };
283
+ document.addEventListener("dragenter", onEnter);
284
+ document.addEventListener("dragover", onOver);
285
+ document.addEventListener("dragleave", onLeave);
286
+ document.addEventListener("drop", onDrop);
287
+ return () => {
288
+ document.removeEventListener("dragenter", onEnter);
289
+ document.removeEventListener("dragover", onOver);
290
+ document.removeEventListener("dragleave", onLeave);
291
+ document.removeEventListener("drop", onDrop);
292
+ };
293
+ }, [active, deliver, enter, leave, reset, scope]);
294
+ useEffect(() => {
295
+ if (!dragging) return;
296
+ let heartbeat = window.setTimeout(reset, DRAG_HEARTBEAT_MS);
297
+ const onDragOverAnywhere = () => {
298
+ window.clearTimeout(heartbeat);
299
+ heartbeat = window.setTimeout(reset, DRAG_HEARTBEAT_MS);
300
+ };
301
+ const onLeaveWindow = (event) => {
302
+ if (event.relatedTarget) return;
303
+ const { clientX: x, clientY: y } = event;
304
+ if (x <= 0 || y <= 0 || x >= window.innerWidth || y >= window.innerHeight) reset();
305
+ };
306
+ window.addEventListener("dragover", onDragOverAnywhere, true);
307
+ window.addEventListener("drop", reset);
308
+ window.addEventListener("dragend", reset);
309
+ window.addEventListener("dragleave", onLeaveWindow);
310
+ window.addEventListener("mousemove", reset, { passive: true });
311
+ return () => {
312
+ window.clearTimeout(heartbeat);
313
+ window.removeEventListener("dragover", onDragOverAnywhere, true);
314
+ window.removeEventListener("drop", reset);
315
+ window.removeEventListener("dragend", reset);
316
+ window.removeEventListener("dragleave", onLeaveWindow);
317
+ window.removeEventListener("mousemove", reset);
318
+ };
319
+ }, [dragging, reset]);
320
+ const showOverlay = dragging && active;
321
+ useEffect(() => {
322
+ if (!showOverlay || scope !== "area") return;
323
+ const measure = () => {
324
+ if (root.current) setBand(visibleBand(root.current));
325
+ };
326
+ measure();
327
+ window.addEventListener("scroll", measure, { capture: true, passive: true });
328
+ window.addEventListener("resize", measure);
329
+ return () => {
330
+ window.removeEventListener("scroll", measure, { capture: true });
331
+ window.removeEventListener("resize", measure);
332
+ setBand(null);
333
+ };
334
+ }, [scope, showOverlay]);
335
+ const handlesHere = active && scope === "area";
336
+ const prompt = /* @__PURE__ */ jsx(FileDropPrompt, { icon: icon ?? /* @__PURE__ */ jsx(FileUp, { className: "h-5 w-5" }), label, description });
337
+ let overlay = null;
338
+ if (showOverlay && scope === "page" && typeof document !== "undefined") {
339
+ overlay = createPortal(
340
+ /* @__PURE__ */ jsx(
341
+ "div",
342
+ {
343
+ "data-slot": "file-drop-overlay",
344
+ "data-scope": "page",
345
+ "aria-hidden": "true",
346
+ className: "pointer-events-none fixed inset-0 z-50 bg-background/80 p-3 supports-backdrop-filter:backdrop-blur-sm motion-safe:animate-in motion-safe:fade-in-0",
347
+ children: /* @__PURE__ */ jsx("div", { className: "flex h-full flex-col items-center justify-center rounded-xl border-2 border-dashed border-primary p-6 text-center text-sm", children: prompt })
348
+ }
349
+ ),
350
+ document.body
351
+ );
352
+ } else if (showOverlay && scope === "area") {
353
+ overlay = /* @__PURE__ */ jsx(
354
+ "div",
355
+ {
356
+ "data-slot": "file-drop-overlay",
357
+ "data-scope": "area",
358
+ "aria-hidden": "true",
359
+ className: "absolute inset-0 z-30 rounded-[inherit] border-2 border-dashed border-primary bg-background/90 text-sm supports-backdrop-filter:backdrop-blur-sm motion-safe:animate-in motion-safe:fade-in-0 [&_*]:pointer-events-none",
360
+ children: /* @__PURE__ */ jsx(
361
+ "div",
362
+ {
363
+ "data-slot": "file-drop-prompt",
364
+ className: "absolute inset-x-0 flex flex-col items-center justify-center p-6 text-center",
365
+ style: band ?? { top: 0, height: "100%" },
366
+ children: prompt
367
+ }
368
+ )
369
+ }
370
+ );
371
+ }
372
+ return /* @__PURE__ */ jsxs(
373
+ "div",
374
+ {
375
+ ref: setRoot,
376
+ "data-file-drop": showOverlay ? "active" : void 0,
377
+ className: cn("relative", className),
378
+ ...props,
379
+ onDragEnter: (event) => {
380
+ onDragEnter?.(event);
381
+ if (!handlesHere || !isUnclaimedFileDrag(event.nativeEvent)) return;
382
+ event.preventDefault();
383
+ enter(event.target);
384
+ },
385
+ onDragOver: (event) => {
386
+ onDragOver?.(event);
387
+ if (!handlesHere || !isUnclaimedFileDrag(event.nativeEvent)) return;
388
+ event.preventDefault();
389
+ event.dataTransfer.dropEffect = "copy";
390
+ if (entered.current.length === 0) enter(event.target);
391
+ },
392
+ onDragLeave: (event) => {
393
+ onDragLeave?.(event);
394
+ if (scope === "area") leave(event.target, event.currentTarget);
395
+ },
396
+ onDrop: (event) => {
397
+ if (scope !== "area") return;
398
+ reset();
399
+ if (!onFiles || !isUnclaimedFileDrag(event.nativeEvent)) return;
400
+ event.preventDefault();
401
+ if (!disabled) deliver(event.dataTransfer);
402
+ },
403
+ children: [
404
+ children,
405
+ overlay
406
+ ]
407
+ }
408
+ );
409
+ });
410
+
411
+ export {
412
+ FileDropzone,
413
+ installFileDropGuard,
414
+ useFileDropGuard,
415
+ FileDropArea
416
+ };
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import {
3
+ Textarea
4
+ } from "./chunk-6FC65AZQ.js";
5
+ import {
6
+ Input
7
+ } from "./chunk-QMA3WVB7.js";
8
+ import {
9
+ Button
10
+ } from "./chunk-HQRWRRZJ.js";
11
+ import {
12
+ cn
13
+ } from "./chunk-G6SRSWXB.js";
14
+
15
+ // src/primitives/input-group.tsx
16
+ import { cva } from "class-variance-authority";
17
+ import { jsx } from "react/jsx-runtime";
18
+ function InputGroup({ className, ...props }) {
19
+ return /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ "data-slot": "input-group",
23
+ role: "group",
24
+ className: cn(
25
+ "group/input-group relative flex h-9 w-full min-w-0 items-center rounded-md border border-input shadow-xs transition-[color,box-shadow] outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
26
+ className
27
+ ),
28
+ ...props
29
+ }
30
+ );
31
+ }
32
+ var inputGroupAddonVariants = cva(
33
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
34
+ {
35
+ variants: {
36
+ align: {
37
+ "inline-start": "order-first pl-2 has-[>button]:-ml-1 has-[>kbd]:ml-[-0.15rem]",
38
+ "inline-end": "order-last pr-2 has-[>button]:-mr-1 has-[>kbd]:mr-[-0.15rem]",
39
+ "block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
40
+ "block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
41
+ }
42
+ },
43
+ defaultVariants: {
44
+ align: "inline-start"
45
+ }
46
+ }
47
+ );
48
+ function InputGroupAddon({
49
+ className,
50
+ align = "inline-start",
51
+ ...props
52
+ }) {
53
+ return /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ role: "group",
57
+ "data-slot": "input-group-addon",
58
+ "data-align": align,
59
+ className: cn(inputGroupAddonVariants({ align }), className),
60
+ onClick: (e) => {
61
+ if (e.target.closest("button")) {
62
+ return;
63
+ }
64
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
65
+ },
66
+ ...props
67
+ }
68
+ );
69
+ }
70
+ var inputGroupButtonVariants = cva(
71
+ "flex items-center gap-2 text-sm shadow-none",
72
+ {
73
+ variants: {
74
+ size: {
75
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
76
+ sm: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
77
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
78
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
79
+ }
80
+ },
81
+ defaultVariants: {
82
+ size: "xs"
83
+ }
84
+ }
85
+ );
86
+ function InputGroupButton({
87
+ className,
88
+ type = "button",
89
+ variant = "ghost",
90
+ size = "xs",
91
+ ...props
92
+ }) {
93
+ return /* @__PURE__ */ jsx(
94
+ Button,
95
+ {
96
+ type,
97
+ size: "bare",
98
+ "data-size": size,
99
+ variant,
100
+ className: cn(inputGroupButtonVariants({ size }), className),
101
+ ...props
102
+ }
103
+ );
104
+ }
105
+ function InputGroupText({ className, ...props }) {
106
+ return /* @__PURE__ */ jsx(
107
+ "span",
108
+ {
109
+ className: cn(
110
+ "flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
111
+ className
112
+ ),
113
+ ...props
114
+ }
115
+ );
116
+ }
117
+ function InputGroupInput({
118
+ className,
119
+ ...props
120
+ }) {
121
+ return /* @__PURE__ */ jsx(
122
+ Input,
123
+ {
124
+ "data-slot": "input-group-control",
125
+ controlSize: "sm",
126
+ surface: "ghost",
127
+ className: cn(
128
+ "min-w-0 flex-1 rounded-none border-0 bg-transparent px-2.5 py-1 shadow-none ring-0 focus-visible:ring-0 focus-visible:ring-offset-0 aria-invalid:ring-0 dark:bg-transparent",
129
+ className
130
+ ),
131
+ ...props
132
+ }
133
+ );
134
+ }
135
+ function InputGroupTextarea({
136
+ className,
137
+ ...props
138
+ }) {
139
+ return /* @__PURE__ */ jsx(
140
+ Textarea,
141
+ {
142
+ "data-slot": "input-group-control",
143
+ className: cn(
144
+ "field-sizing-content min-h-16 flex-1 resize-none rounded-none border-0 bg-transparent px-2.5 py-2 shadow-none ring-0 focus-visible:ring-0 focus-visible:ring-offset-0 aria-invalid:ring-0 dark:bg-transparent",
145
+ className
146
+ ),
147
+ ...props
148
+ }
149
+ );
150
+ }
151
+
152
+ export {
153
+ InputGroup,
154
+ InputGroupAddon,
155
+ InputGroupButton,
156
+ InputGroupText,
157
+ InputGroupInput,
158
+ InputGroupTextarea
159
+ };