@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
@@ -12,31 +12,31 @@ var _chunkWQJKUKBLcjs = require('../chunk-WQJKUKBL.cjs');
12
12
 
13
13
 
14
14
  var _chunkWDXEJDMOcjs = require('../chunk-WDXEJDMO.cjs');
15
- require('../chunk-ZAITUDYD.cjs');
16
15
 
17
16
 
18
- var _chunk373W6VADcjs = require('../chunk-373W6VAD.cjs');
17
+ var _chunkCTYOW3V2cjs = require('../chunk-CTYOW3V2.cjs');
18
+ require('../chunk-ZAITUDYD.cjs');
19
19
 
20
20
 
21
- var _chunkCTYOW3V2cjs = require('../chunk-CTYOW3V2.cjs');
21
+ var _chunk373W6VADcjs = require('../chunk-373W6VAD.cjs');
22
22
  require('../chunk-I6GUOEBO.cjs');
23
23
 
24
24
 
25
25
 
26
- var _chunk667ZCM4Xcjs = require('../chunk-667ZCM4X.cjs');
27
26
 
28
27
 
29
28
 
30
29
 
31
30
 
32
31
 
32
+ var _chunk23UMHZ4Scjs = require('../chunk-23UMHZ4S.cjs');
33
33
 
34
34
 
35
+ var _chunkL4DH72UFcjs = require('../chunk-L4DH72UF.cjs');
35
36
 
36
- var _chunk23UMHZ4Scjs = require('../chunk-23UMHZ4S.cjs');
37
37
 
38
38
 
39
- var _chunkL4DH72UFcjs = require('../chunk-L4DH72UF.cjs');
39
+ var _chunk667ZCM4Xcjs = require('../chunk-667ZCM4X.cjs');
40
40
 
41
41
 
42
42
  var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
@@ -12,18 +12,14 @@ import {
12
12
  DialogHeader,
13
13
  DialogTitle
14
14
  } from "../chunk-3QT5VYZ3.js";
15
+ import {
16
+ Callout
17
+ } from "../chunk-GL5CV4FF.js";
15
18
  import "../chunk-V4LE2HWP.js";
16
19
  import {
17
20
  Text
18
21
  } from "../chunk-EIY5LLSP.js";
19
- import {
20
- Callout
21
- } from "../chunk-GL5CV4FF.js";
22
22
  import "../chunk-D4ZL2OEQ.js";
23
- import {
24
- Alert,
25
- AlertDescription
26
- } from "../chunk-R4AIM3BQ.js";
27
23
  import {
28
24
  AlertDialog,
29
25
  AlertDialogAction,
@@ -37,6 +33,10 @@ import {
37
33
  import {
38
34
  buttonVariants
39
35
  } from "../chunk-HQRWRRZJ.js";
36
+ import {
37
+ Alert,
38
+ AlertDescription
39
+ } from "../chunk-R4AIM3BQ.js";
40
40
  import {
41
41
  cn
42
42
  } from "../chunk-G6SRSWXB.js";
@@ -1,118 +1,18 @@
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";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
  "use client";
3
3
 
4
4
 
5
- var _chunk373W6VADcjs = require('../chunk-373W6VAD.cjs');
6
5
 
7
6
 
8
7
 
8
+ var _chunkKADJ56AHcjs = require('../chunk-KADJ56AH.cjs');
9
+ require('../chunk-373W6VAD.cjs');
10
+ require('../chunk-U2NES7VR.cjs');
11
+ require('../chunk-L4DH72UF.cjs');
12
+ require('../chunk-KWLSBTB2.cjs');
9
13
 
10
- var _chunkU2NES7VRcjs = require('../chunk-U2NES7VR.cjs');
11
14
 
12
15
 
13
- var _chunkL4DH72UFcjs = require('../chunk-L4DH72UF.cjs');
14
16
 
15
17
 
16
- var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
17
-
18
- // src/primitives/file-dropzone.tsx
19
- var _lucidereact = require('lucide-react');
20
- var _react = require('react');
21
- var _jsxruntime = require('react/jsx-runtime');
22
- function FileDropzone({
23
- onFile,
24
- onFiles,
25
- multiple = false,
26
- accept,
27
- disabled = false,
28
- busy: externalBusy = false,
29
- label = "Drop a file, or choose one",
30
- description,
31
- busyLabel = "Reading file\u2026",
32
- icon,
33
- variant = "dropzone",
34
- className
35
- }) {
36
- const inputRef = _react.useRef.call(void 0, null);
37
- const [dragging, setDragging] = _react.useState.call(void 0, false);
38
- const [internalBusy, setInternalBusy] = _react.useState.call(void 0, false);
39
- const busy = externalBusy || internalBusy;
40
- async function select(files) {
41
- if (files.length === 0 || disabled || busy) return;
42
- setInternalBusy(true);
43
- try {
44
- if (multiple) {
45
- await _optionalChain([onFiles, 'optionalCall', _ => _(files)]);
46
- } else {
47
- const first = files[0];
48
- if (first) await _optionalChain([onFile, 'optionalCall', _2 => _2(first)]);
49
- }
50
- } finally {
51
- setInternalBusy(false);
52
- if (inputRef.current) inputRef.current.value = "";
53
- }
54
- }
55
- function onDrop(event) {
56
- event.preventDefault();
57
- setDragging(false);
58
- void select(Array.from(_nullishCoalesce(event.dataTransfer.files, () => ( []))));
59
- }
60
- const trigger = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
61
- _chunkL4DH72UFcjs.Button,
62
- {
63
- type: "button",
64
- "data-file-dropzone": "true",
65
- variant: "outline",
66
- size: variant === "icon" ? "icon" : "default",
67
- "aria-label": variant === "icon" ? String(busy ? busyLabel : label) : void 0,
68
- disabled: disabled || busy,
69
- onClick: () => _optionalChain([inputRef, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.click, 'call', _5 => _5()]),
70
- onDragEnter: (event) => {
71
- event.preventDefault();
72
- setDragging(true);
73
- },
74
- onDragOver: (event) => {
75
- event.preventDefault();
76
- setDragging(true);
77
- },
78
- onDragLeave: () => setDragging(false),
79
- onDrop,
80
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
81
- variant === "dropzone" ? "h-auto w-full flex-col whitespace-normal border-2 border-dashed px-6 py-8 text-center" : variant === "button" ? "w-fit" : "",
82
- dragging && "border-primary bg-primary/5",
83
- className
84
- ),
85
- children: [
86
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: _chunkKWLSBTB2cjs.cn.call(void 0,
87
- "flex items-center justify-center text-muted-foreground",
88
- variant === "dropzone" && "mb-2 h-10 w-10 rounded-full bg-muted"
89
- ), 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" }))) }),
90
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: variant === "icon" ? "sr-only" : "font-medium", children: busy ? busyLabel : label }),
91
- description && variant === "dropzone" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk373W6VADcjs.Text, { variant: "muted", className: "mt-1 max-w-md text-xs", children: description })
92
- ]
93
- }
94
- );
95
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
96
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
97
- "input",
98
- {
99
- ref: inputRef,
100
- type: "file",
101
- accept,
102
- multiple,
103
- disabled: disabled || busy,
104
- onChange: (event) => void select(Array.from(_nullishCoalesce(event.target.files, () => ( [])))),
105
- className: "sr-only",
106
- tabIndex: -1,
107
- "aria-hidden": "true"
108
- }
109
- ),
110
- variant === "icon" && description ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkU2NES7VRcjs.Tooltip, { children: [
111
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipTrigger, { asChild: true, children: trigger }),
112
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkU2NES7VRcjs.TooltipContent, { children: description })
113
- ] }) : trigger
114
- ] });
115
- }
116
-
117
-
118
- exports.FileDropzone = FileDropzone;
18
+ exports.FileDropArea = _chunkKADJ56AHcjs.FileDropArea; exports.FileDropzone = _chunkKADJ56AHcjs.FileDropzone; exports.installFileDropGuard = _chunkKADJ56AHcjs.installFileDropGuard; exports.useFileDropGuard = _chunkKADJ56AHcjs.useFileDropGuard;
@@ -1,5 +1,6 @@
1
+ import * as React from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
1
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
4
 
4
5
  interface FileDropzoneBaseProps {
5
6
  accept?: string;
@@ -29,8 +30,70 @@ type FileDropzoneProps = SingleFileDropzoneProps | MultiFileDropzoneProps;
29
30
  *
30
31
  * The primitive owns the hidden native input, focus state, drag state and
31
32
  * async busy state. It deliberately does not parse, upload or validate file
32
- * contents; those remain consumer concerns.
33
+ * contents; those remain consumer concerns. It installs `useFileDropGuard`,
34
+ * so a file dropped just beside it never opens in the browser.
33
35
  */
34
36
  declare function FileDropzone({ onFile, onFiles, multiple, accept, disabled, busy: externalBusy, label, description, busyLabel, icon, variant, className, }: FileDropzoneProps): react_jsx_runtime.JSX.Element;
37
+ /**
38
+ * Makes sure a file dropped where nothing takes it never opens or downloads
39
+ * in the browser, which is what a browser does by default with a file
40
+ * dropped on a page. Returns the function that removes it again.
41
+ *
42
+ * Listens on `window`, after every other handler: a drag or a drop that a
43
+ * drop target has already accepted (`preventDefault`) is left alone, and so
44
+ * is a native `<input type="file">`, which takes its own drop. Any other file
45
+ * drag is cancelled, with the "no drop" cursor.
46
+ *
47
+ * Call it once in an app's entry, before rendering: it lives outside React,
48
+ * so a render error, an error boundary's fallback or an unmounted root never
49
+ * takes it away. `useFileDropGuard` is the same guard for a component's
50
+ * lifetime.
51
+ */
52
+ declare function installFileDropGuard(): () => void;
53
+ /**
54
+ * `installFileDropGuard` while the component is mounted (and `enabled`).
55
+ * `FileDropzone` and `FileDropArea` install it themselves. For a whole app,
56
+ * prefer `installFileDropGuard()` in the entry: a hook in the app's root
57
+ * component goes when a render error unmounts it.
58
+ */
59
+ declare function useFileDropGuard(enabled?: boolean): void;
60
+ interface FileDropAreaProps extends Omit<HTMLAttributes<HTMLDivElement>, "onDrop"> {
61
+ /**
62
+ * Every dropped file, unfiltered: the callback the region's file picker
63
+ * calls, so the caller validates types, sizes and counts and reports its
64
+ * own errors. Without it the area is a plain div and installs no guard.
65
+ */
66
+ onFiles?: (files: File[]) => void | Promise<void>;
67
+ /** The overlay stays down and drops are ignored; the page guard stays on. */
68
+ disabled?: boolean;
69
+ /**
70
+ * `area` (the default): a file dragged over this element raises an overlay
71
+ * over it, and a drop on it lands here. `page`: a file dragged anywhere in
72
+ * the document raises an overlay over the whole viewport, and a drop
73
+ * anywhere lands here.
74
+ */
75
+ scope?: "area" | "page";
76
+ /** The overlay's label. Defaults to "Drop to attach". */
77
+ label?: ReactNode;
78
+ /** A muted line under the label, such as the accepted types and limits. */
79
+ description?: ReactNode;
80
+ /** The overlay's icon. Defaults to the upload icon `FileDropzone` shows. */
81
+ icon?: ReactNode;
82
+ }
83
+ /**
84
+ * A region that takes files dragged onto it. While a file is dragged over
85
+ * it, an overlay covers it ("Drop to attach"), and a drop hands every file to
86
+ * `onFiles`, the callback its file picker already calls. A file dropped
87
+ * anywhere else in the page never opens in the browser (`useFileDropGuard`).
88
+ *
89
+ * The label stays on screen however the region sits: an area taller than the
90
+ * viewport centres it in the part that shows, and `scope="page"` covers the
91
+ * viewport itself, wherever in the page the region is.
92
+ *
93
+ * The overlay is decorative (`aria-hidden`): keep a picker in the region as
94
+ * the accessible way to add files. A drop target inside it (a
95
+ * `FileDropzone`) keeps its own drops, so a file is never delivered twice.
96
+ */
97
+ declare const FileDropArea: React.ForwardRefExoticComponent<FileDropAreaProps & React.RefAttributes<HTMLDivElement>>;
35
98
 
36
- export { FileDropzone, type FileDropzoneProps };
99
+ export { FileDropArea, type FileDropAreaProps, FileDropzone, type FileDropzoneProps, installFileDropGuard, useFileDropGuard };
@@ -1,5 +1,6 @@
1
+ import * as React from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
1
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
4
 
4
5
  interface FileDropzoneBaseProps {
5
6
  accept?: string;
@@ -29,8 +30,70 @@ type FileDropzoneProps = SingleFileDropzoneProps | MultiFileDropzoneProps;
29
30
  *
30
31
  * The primitive owns the hidden native input, focus state, drag state and
31
32
  * async busy state. It deliberately does not parse, upload or validate file
32
- * contents; those remain consumer concerns.
33
+ * contents; those remain consumer concerns. It installs `useFileDropGuard`,
34
+ * so a file dropped just beside it never opens in the browser.
33
35
  */
34
36
  declare function FileDropzone({ onFile, onFiles, multiple, accept, disabled, busy: externalBusy, label, description, busyLabel, icon, variant, className, }: FileDropzoneProps): react_jsx_runtime.JSX.Element;
37
+ /**
38
+ * Makes sure a file dropped where nothing takes it never opens or downloads
39
+ * in the browser, which is what a browser does by default with a file
40
+ * dropped on a page. Returns the function that removes it again.
41
+ *
42
+ * Listens on `window`, after every other handler: a drag or a drop that a
43
+ * drop target has already accepted (`preventDefault`) is left alone, and so
44
+ * is a native `<input type="file">`, which takes its own drop. Any other file
45
+ * drag is cancelled, with the "no drop" cursor.
46
+ *
47
+ * Call it once in an app's entry, before rendering: it lives outside React,
48
+ * so a render error, an error boundary's fallback or an unmounted root never
49
+ * takes it away. `useFileDropGuard` is the same guard for a component's
50
+ * lifetime.
51
+ */
52
+ declare function installFileDropGuard(): () => void;
53
+ /**
54
+ * `installFileDropGuard` while the component is mounted (and `enabled`).
55
+ * `FileDropzone` and `FileDropArea` install it themselves. For a whole app,
56
+ * prefer `installFileDropGuard()` in the entry: a hook in the app's root
57
+ * component goes when a render error unmounts it.
58
+ */
59
+ declare function useFileDropGuard(enabled?: boolean): void;
60
+ interface FileDropAreaProps extends Omit<HTMLAttributes<HTMLDivElement>, "onDrop"> {
61
+ /**
62
+ * Every dropped file, unfiltered: the callback the region's file picker
63
+ * calls, so the caller validates types, sizes and counts and reports its
64
+ * own errors. Without it the area is a plain div and installs no guard.
65
+ */
66
+ onFiles?: (files: File[]) => void | Promise<void>;
67
+ /** The overlay stays down and drops are ignored; the page guard stays on. */
68
+ disabled?: boolean;
69
+ /**
70
+ * `area` (the default): a file dragged over this element raises an overlay
71
+ * over it, and a drop on it lands here. `page`: a file dragged anywhere in
72
+ * the document raises an overlay over the whole viewport, and a drop
73
+ * anywhere lands here.
74
+ */
75
+ scope?: "area" | "page";
76
+ /** The overlay's label. Defaults to "Drop to attach". */
77
+ label?: ReactNode;
78
+ /** A muted line under the label, such as the accepted types and limits. */
79
+ description?: ReactNode;
80
+ /** The overlay's icon. Defaults to the upload icon `FileDropzone` shows. */
81
+ icon?: ReactNode;
82
+ }
83
+ /**
84
+ * A region that takes files dragged onto it. While a file is dragged over
85
+ * it, an overlay covers it ("Drop to attach"), and a drop hands every file to
86
+ * `onFiles`, the callback its file picker already calls. A file dropped
87
+ * anywhere else in the page never opens in the browser (`useFileDropGuard`).
88
+ *
89
+ * The label stays on screen however the region sits: an area taller than the
90
+ * viewport centres it in the part that shows, and `scope="page"` covers the
91
+ * viewport itself, wherever in the page the region is.
92
+ *
93
+ * The overlay is decorative (`aria-hidden`): keep a picker in the region as
94
+ * the accessible way to add files. A drop target inside it (a
95
+ * `FileDropzone`) keeps its own drops, so a file is never delivered twice.
96
+ */
97
+ declare const FileDropArea: React.ForwardRefExoticComponent<FileDropAreaProps & React.RefAttributes<HTMLDivElement>>;
35
98
 
36
- export { FileDropzone, type FileDropzoneProps };
99
+ export { FileDropArea, type FileDropAreaProps, FileDropzone, type FileDropzoneProps, installFileDropGuard, useFileDropGuard };
@@ -1,118 +1,18 @@
1
1
  "use client";
2
2
  "use client";
3
3
  import {
4
- Text
5
- } from "../chunk-EIY5LLSP.js";
6
- import {
7
- Tooltip,
8
- TooltipContent,
9
- TooltipTrigger
10
- } from "../chunk-ZRLUUZHK.js";
11
- import {
12
- Button
13
- } from "../chunk-HQRWRRZJ.js";
14
- import {
15
- cn
16
- } from "../chunk-G6SRSWXB.js";
17
-
18
- // src/primitives/file-dropzone.tsx
19
- import { FileUp, Loader2 } from "lucide-react";
20
- import { useRef, useState } from "react";
21
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
- function FileDropzone({
23
- onFile,
24
- onFiles,
25
- multiple = false,
26
- accept,
27
- disabled = false,
28
- busy: externalBusy = false,
29
- label = "Drop a file, or choose one",
30
- description,
31
- busyLabel = "Reading file\u2026",
32
- icon,
33
- variant = "dropzone",
34
- className
35
- }) {
36
- const inputRef = useRef(null);
37
- const [dragging, setDragging] = useState(false);
38
- const [internalBusy, setInternalBusy] = useState(false);
39
- const busy = externalBusy || internalBusy;
40
- async function select(files) {
41
- if (files.length === 0 || disabled || busy) return;
42
- setInternalBusy(true);
43
- try {
44
- if (multiple) {
45
- await onFiles?.(files);
46
- } else {
47
- const first = files[0];
48
- if (first) await onFile?.(first);
49
- }
50
- } finally {
51
- setInternalBusy(false);
52
- if (inputRef.current) inputRef.current.value = "";
53
- }
54
- }
55
- function onDrop(event) {
56
- event.preventDefault();
57
- setDragging(false);
58
- void select(Array.from(event.dataTransfer.files ?? []));
59
- }
60
- const trigger = /* @__PURE__ */ jsxs(
61
- Button,
62
- {
63
- type: "button",
64
- "data-file-dropzone": "true",
65
- variant: "outline",
66
- size: variant === "icon" ? "icon" : "default",
67
- "aria-label": variant === "icon" ? String(busy ? busyLabel : label) : void 0,
68
- disabled: disabled || busy,
69
- onClick: () => inputRef.current?.click(),
70
- onDragEnter: (event) => {
71
- event.preventDefault();
72
- setDragging(true);
73
- },
74
- onDragOver: (event) => {
75
- event.preventDefault();
76
- setDragging(true);
77
- },
78
- onDragLeave: () => setDragging(false),
79
- onDrop,
80
- className: cn(
81
- variant === "dropzone" ? "h-auto w-full flex-col whitespace-normal border-2 border-dashed px-6 py-8 text-center" : variant === "button" ? "w-fit" : "",
82
- dragging && "border-primary bg-primary/5",
83
- className
84
- ),
85
- children: [
86
- /* @__PURE__ */ jsx("span", { className: cn(
87
- "flex items-center justify-center text-muted-foreground",
88
- variant === "dropzone" && "mb-2 h-10 w-10 rounded-full bg-muted"
89
- ), children: busy ? /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin" }) : icon ?? /* @__PURE__ */ jsx(FileUp, { className: "h-5 w-5" }) }),
90
- /* @__PURE__ */ jsx("span", { className: variant === "icon" ? "sr-only" : "font-medium", children: busy ? busyLabel : label }),
91
- description && variant === "dropzone" && /* @__PURE__ */ jsx(Text, { variant: "muted", className: "mt-1 max-w-md text-xs", children: description })
92
- ]
93
- }
94
- );
95
- return /* @__PURE__ */ jsxs(Fragment, { children: [
96
- /* @__PURE__ */ jsx(
97
- "input",
98
- {
99
- ref: inputRef,
100
- type: "file",
101
- accept,
102
- multiple,
103
- disabled: disabled || busy,
104
- onChange: (event) => void select(Array.from(event.target.files ?? [])),
105
- className: "sr-only",
106
- tabIndex: -1,
107
- "aria-hidden": "true"
108
- }
109
- ),
110
- variant === "icon" && description ? /* @__PURE__ */ jsxs(Tooltip, { children: [
111
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: trigger }),
112
- /* @__PURE__ */ jsx(TooltipContent, { children: description })
113
- ] }) : trigger
114
- ] });
115
- }
4
+ FileDropArea,
5
+ FileDropzone,
6
+ installFileDropGuard,
7
+ useFileDropGuard
8
+ } from "../chunk-M7FYGAGO.js";
9
+ import "../chunk-EIY5LLSP.js";
10
+ import "../chunk-ZRLUUZHK.js";
11
+ import "../chunk-HQRWRRZJ.js";
12
+ import "../chunk-G6SRSWXB.js";
116
13
  export {
117
- FileDropzone
14
+ FileDropArea,
15
+ FileDropzone,
16
+ installFileDropGuard,
17
+ useFileDropGuard
118
18
  };
@@ -0,0 +1,21 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+ var _chunkRIWLAMMEcjs = require('../chunk-RIWLAMME.cjs');
10
+ require('../chunk-2HV2KKOE.cjs');
11
+ require('../chunk-PQUSJEXL.cjs');
12
+ require('../chunk-L4DH72UF.cjs');
13
+ require('../chunk-KWLSBTB2.cjs');
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ exports.InputGroup = _chunkRIWLAMMEcjs.InputGroup; exports.InputGroupAddon = _chunkRIWLAMMEcjs.InputGroupAddon; exports.InputGroupButton = _chunkRIWLAMMEcjs.InputGroupButton; exports.InputGroupInput = _chunkRIWLAMMEcjs.InputGroupInput; exports.InputGroupText = _chunkRIWLAMMEcjs.InputGroupText; exports.InputGroupTextarea = _chunkRIWLAMMEcjs.InputGroupTextarea;
@@ -0,0 +1,20 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { VariantProps } from 'class-variance-authority';
5
+ import { Button } from './button.cjs';
6
+
7
+ declare function InputGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
8
+ declare const inputGroupAddonVariants: (props?: ({
9
+ align?: "inline-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
10
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
11
+ declare function InputGroupAddon({ className, align, ...props }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): react_jsx_runtime.JSX.Element;
12
+ declare const inputGroupButtonVariants: (props?: ({
13
+ size?: "xs" | "sm" | "icon-sm" | "icon-xs" | null | undefined;
14
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
15
+ declare function InputGroupButton({ className, type, variant, size, ...props }: Omit<React.ComponentProps<typeof Button>, "size"> & VariantProps<typeof inputGroupButtonVariants>): react_jsx_runtime.JSX.Element;
16
+ declare function InputGroupText({ className, ...props }: React.ComponentProps<"span">): react_jsx_runtime.JSX.Element;
17
+ declare function InputGroupInput({ className, ...props }: React.ComponentProps<"input">): react_jsx_runtime.JSX.Element;
18
+ declare function InputGroupTextarea({ className, ...props }: React.ComponentProps<"textarea">): react_jsx_runtime.JSX.Element;
19
+
20
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
@@ -0,0 +1,20 @@
1
+ import * as class_variance_authority_types from 'class-variance-authority/types';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import * as React from 'react';
4
+ import { VariantProps } from 'class-variance-authority';
5
+ import { Button } from './button.js';
6
+
7
+ declare function InputGroup({ className, ...props }: React.ComponentProps<"div">): react_jsx_runtime.JSX.Element;
8
+ declare const inputGroupAddonVariants: (props?: ({
9
+ align?: "inline-start" | "inline-end" | "block-start" | "block-end" | null | undefined;
10
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
11
+ declare function InputGroupAddon({ className, align, ...props }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>): react_jsx_runtime.JSX.Element;
12
+ declare const inputGroupButtonVariants: (props?: ({
13
+ size?: "xs" | "sm" | "icon-sm" | "icon-xs" | null | undefined;
14
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
15
+ declare function InputGroupButton({ className, type, variant, size, ...props }: Omit<React.ComponentProps<typeof Button>, "size"> & VariantProps<typeof inputGroupButtonVariants>): react_jsx_runtime.JSX.Element;
16
+ declare function InputGroupText({ className, ...props }: React.ComponentProps<"span">): react_jsx_runtime.JSX.Element;
17
+ declare function InputGroupInput({ className, ...props }: React.ComponentProps<"input">): react_jsx_runtime.JSX.Element;
18
+ declare function InputGroupTextarea({ className, ...props }: React.ComponentProps<"textarea">): react_jsx_runtime.JSX.Element;
19
+
20
+ export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea };
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import {
3
+ InputGroup,
4
+ InputGroupAddon,
5
+ InputGroupButton,
6
+ InputGroupInput,
7
+ InputGroupText,
8
+ InputGroupTextarea
9
+ } from "../chunk-MHYAVXOE.js";
10
+ import "../chunk-6FC65AZQ.js";
11
+ import "../chunk-QMA3WVB7.js";
12
+ import "../chunk-HQRWRRZJ.js";
13
+ import "../chunk-G6SRSWXB.js";
14
+ export {
15
+ InputGroup,
16
+ InputGroupAddon,
17
+ InputGroupButton,
18
+ InputGroupInput,
19
+ InputGroupText,
20
+ InputGroupTextarea
21
+ };