@epicbagel/saas-kit 1.2.2 → 1.3.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.
- package/README.md +84 -0
- package/dist/chunk-2TKLS73N.js +121 -0
- package/dist/chunk-4UUTKR3V.cjs +53 -0
- package/dist/chunk-BTHYGHOH.cjs +143 -0
- package/dist/chunk-GRY77463.cjs +121 -0
- package/dist/chunk-HHV4G77I.js +55 -0
- package/dist/chunk-JTI4244T.js +143 -0
- package/dist/chunk-QEJ2STIV.js +53 -0
- package/dist/chunk-VLXPLKFR.cjs +55 -0
- package/dist/primitives/chat.cjs +46 -19
- package/dist/primitives/chat.d.cts +24 -5
- package/dist/primitives/chat.d.ts +24 -5
- package/dist/primitives/chat.js +42 -15
- package/dist/primitives/code-block.cjs +4 -49
- package/dist/primitives/code-block.js +4 -49
- package/dist/primitives/document-preview.cjs +54 -0
- package/dist/primitives/document-preview.d.cts +30 -0
- package/dist/primitives/document-preview.d.ts +30 -0
- package/dist/primitives/document-preview.js +54 -0
- package/dist/primitives/file-preview-internals.cjs +20 -0
- package/dist/primitives/file-preview-internals.d.cts +44 -0
- package/dist/primitives/file-preview-internals.d.ts +44 -0
- package/dist/primitives/file-preview-internals.js +20 -0
- package/dist/primitives/file-preview.cjs +327 -0
- package/dist/primitives/file-preview.d.cts +92 -0
- package/dist/primitives/file-preview.d.ts +92 -0
- package/dist/primitives/file-preview.js +327 -0
- package/dist/primitives/image.cjs +4 -48
- package/dist/primitives/image.js +3 -47
- package/dist/primitives/responsive-dialog.cjs +26 -142
- package/dist/primitives/responsive-dialog.js +13 -129
- package/package.json +21 -1
package/README.md
CHANGED
|
@@ -135,6 +135,90 @@ public in 1.1.0, and these were the decisions about its props then:
|
|
|
135
135
|
- The drop handling follows AI SDK Elements' `PromptInput` and its
|
|
136
136
|
`globalDrop` (Apache-2.0; see `THIRD_PARTY_NOTICES.md`).
|
|
137
137
|
|
|
138
|
+
### A reply in the background (1.2.3)
|
|
139
|
+
|
|
140
|
+
- **A running turn.** `pending` does two things: it ends the thread on the
|
|
141
|
+
running line, and it locks the composer. A reply worked on in the
|
|
142
|
+
background, while the user keeps writing, needs only the first. Put a turn
|
|
143
|
+
with `status: "running"` in `messages`, and the thread draws the line
|
|
144
|
+
`pending` draws, labelled with the turn's `text` (else `pendingLabel`),
|
|
145
|
+
where the turn sits, while the composer stays free. Replace it with the
|
|
146
|
+
reply when that lands.
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Chat
|
|
150
|
+
messages={[
|
|
151
|
+
...messages,
|
|
152
|
+
...(replyOwed ? [{ id: "reply", role: "assistant", status: "running", text: "Reading your files…" } as const] : []),
|
|
153
|
+
]}
|
|
154
|
+
onSend={send}
|
|
155
|
+
/>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
- **It is not a message.** The row is the one `pending` draws: its own row
|
|
159
|
+
of the log, which announces it as it appears, with no message id, so the
|
|
160
|
+
scroller neither anchors it nor tracks it. It has no time marker, files or
|
|
161
|
+
rich `content`, and the turns either side of it keep their time grouping.
|
|
162
|
+
|
|
163
|
+
## File preview (1.3.0)
|
|
164
|
+
|
|
165
|
+
`primitives/file-preview` shows a file in a dialog without leaving the page:
|
|
166
|
+
the kit's large preview dialog on desktop and its near-full-height drawer on
|
|
167
|
+
mobile, with the file's name, a download action and a close button in the
|
|
168
|
+
header.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { FilePreview } from "@epicbagel/saas-kit/primitives/file-preview";
|
|
172
|
+
|
|
173
|
+
<FilePreview
|
|
174
|
+
open={open}
|
|
175
|
+
onOpenChange={setOpen}
|
|
176
|
+
title={file.name}
|
|
177
|
+
mediaType={file.mediaType}
|
|
178
|
+
file={blob} // fetched by the app, with its own authentication
|
|
179
|
+
loading={!blob && !error}
|
|
180
|
+
error={error}
|
|
181
|
+
onDownload={download}
|
|
182
|
+
/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
- **Each type its own way.** A PDF opens in the browser's own viewer (no PDF
|
|
186
|
+
engine in the bundle), an image as an image, text (plain text, CSV, JSON,
|
|
187
|
+
code) as it is, Markdown rendered through `LazyMarkdown`, audio and video
|
|
188
|
+
in the browser's player. Office documents, archives and anything else say
|
|
189
|
+
"No preview for this file." and offer the download; `fallback` replaces
|
|
190
|
+
that message. An image, player or text that won't load says so, with the
|
|
191
|
+
download.
|
|
192
|
+
- **The app fetches.** The dialog is presentation only. Pass the file as a
|
|
193
|
+
`Blob` (`file`), fetched with whatever authentication the app needs, or a
|
|
194
|
+
short-lived, safe URL (`src`). Text and Markdown are read from the `Blob`,
|
|
195
|
+
or fetched from `src`, which must then allow it (the same origin, or
|
|
196
|
+
CORS). Nothing is read or fetched while the dialog is closed.
|
|
197
|
+
- **Safe by construction.** A `Blob` is shown through an object URL the
|
|
198
|
+
dialog revokes when it closes or the file changes. A PDF from a `Blob` is
|
|
199
|
+
always shown as `application/pdf`, whatever type the blob carries, so a
|
|
200
|
+
file can never render as a page of your origin; text is never
|
|
201
|
+
interpreted; a Markdown file's raw HTML is ignored and its links open in a
|
|
202
|
+
new tab. A `src` is framed as it is, so serve it with its real type.
|
|
203
|
+
- **Telling the type.** `filePreviewKind({ name, mediaType })` returns `pdf`,
|
|
204
|
+
`image`, `text`, `markdown`, `audio`, `video` or `none`, which is what the
|
|
205
|
+
dialog uses unless you pass `kind`. The media type decides when it says
|
|
206
|
+
something, and the extension when it is missing or generic
|
|
207
|
+
(`application/octet-stream`); text named `.md` is Markdown, and a name
|
|
208
|
+
that says text wins over a type with no preview (Windows reports a `.csv`
|
|
209
|
+
as `application/vnd.ms-excel`). Call it to choose between opening a
|
|
210
|
+
preview and downloading straight away.
|
|
211
|
+
- **Long text.** A text file over 500,000 characters shows its start, cut at
|
|
212
|
+
a line break, under `truncatedLabel`.
|
|
213
|
+
- **Copy.** `downloadLabel` ("Download file"), `loadingLabel` ("Loading
|
|
214
|
+
preview…"), `unavailableLabel` ("No preview for this file."),
|
|
215
|
+
`failedLabel` ("This file couldn't be shown here.") and `truncatedLabel`
|
|
216
|
+
can all be replaced; the close button's name ("Close preview") is fixed
|
|
217
|
+
for now.
|
|
218
|
+
|
|
219
|
+
`primitives/document-preview` is the same dialog with every `src` in the
|
|
220
|
+
browser's viewer, as it was in ui-kit; its API is unchanged.
|
|
221
|
+
|
|
138
222
|
## License
|
|
139
223
|
|
|
140
224
|
MIT. Some components and styles are adapted from shadcn/ui, and the file
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
ResponsiveDialog,
|
|
4
|
+
ResponsiveDialogClose,
|
|
5
|
+
ResponsiveDialogContent,
|
|
6
|
+
ResponsiveDialogDescription,
|
|
7
|
+
ResponsiveDialogHeader,
|
|
8
|
+
ResponsiveDialogTitle
|
|
9
|
+
} from "./chunk-JTI4244T.js";
|
|
10
|
+
import {
|
|
11
|
+
Icon
|
|
12
|
+
} from "./chunk-KN4RPX35.js";
|
|
13
|
+
import {
|
|
14
|
+
Button
|
|
15
|
+
} from "./chunk-HQRWRRZJ.js";
|
|
16
|
+
import {
|
|
17
|
+
cn
|
|
18
|
+
} from "./chunk-G6SRSWXB.js";
|
|
19
|
+
|
|
20
|
+
// src/primitives/file-preview-internals.tsx
|
|
21
|
+
import { Download, Loader2, X } from "lucide-react";
|
|
22
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
|
+
function PreviewDialog({
|
|
24
|
+
open,
|
|
25
|
+
onOpenChange,
|
|
26
|
+
title,
|
|
27
|
+
onDownload,
|
|
28
|
+
downloading,
|
|
29
|
+
downloadLabel,
|
|
30
|
+
children
|
|
31
|
+
}) {
|
|
32
|
+
return /* @__PURE__ */ jsx(ResponsiveDialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(ResponsiveDialogContent, { presentation: "preview", className: "h-[92dvh] outline-none", children: [
|
|
33
|
+
/* @__PURE__ */ jsxs(ResponsiveDialogHeader, { className: "shrink-0 border-b border-border", children: [
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
35
|
+
/* @__PURE__ */ jsx(ResponsiveDialogTitle, { className: "min-w-0 flex-1 truncate text-left", children: title }),
|
|
36
|
+
onDownload && /* @__PURE__ */ jsx(
|
|
37
|
+
Button,
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
size: "icon-compact",
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
onClick: onDownload,
|
|
43
|
+
disabled: downloading,
|
|
44
|
+
title: downloadLabel,
|
|
45
|
+
"aria-label": downloadLabel,
|
|
46
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: downloading ? Loader2 : Download, size: "sm", spin: downloading })
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
/* @__PURE__ */ jsx(ResponsiveDialogClose, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
50
|
+
Button,
|
|
51
|
+
{
|
|
52
|
+
type: "button",
|
|
53
|
+
size: "icon-compact",
|
|
54
|
+
variant: "ghost",
|
|
55
|
+
title: "Close preview",
|
|
56
|
+
"aria-label": "Close preview",
|
|
57
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: X, size: "sm" })
|
|
58
|
+
}
|
|
59
|
+
) })
|
|
60
|
+
] }),
|
|
61
|
+
/* @__PURE__ */ jsxs(ResponsiveDialogDescription, { className: "sr-only", children: [
|
|
62
|
+
"Preview of ",
|
|
63
|
+
title
|
|
64
|
+
] })
|
|
65
|
+
] }),
|
|
66
|
+
children
|
|
67
|
+
] }) });
|
|
68
|
+
}
|
|
69
|
+
function PreviewStage({
|
|
70
|
+
layout = "center",
|
|
71
|
+
label,
|
|
72
|
+
children
|
|
73
|
+
}) {
|
|
74
|
+
const scrolls = layout === "scroll";
|
|
75
|
+
return /* @__PURE__ */ jsx(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
"data-slot": "preview-stage",
|
|
79
|
+
role: scrolls ? "region" : void 0,
|
|
80
|
+
"aria-label": scrolls ? label : void 0,
|
|
81
|
+
tabIndex: scrolls ? 0 : void 0,
|
|
82
|
+
className: cn(
|
|
83
|
+
"min-h-0 flex-1",
|
|
84
|
+
scrolls ? "overflow-y-auto overscroll-contain bg-background p-4 outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/50 sm:p-6" : "flex items-center justify-center overflow-hidden bg-muted"
|
|
85
|
+
),
|
|
86
|
+
children
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function PreviewLoading({ label }) {
|
|
91
|
+
return /* @__PURE__ */ jsxs("div", { role: "status", className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Icon, { icon: Loader2, size: "sm", spin: true }),
|
|
93
|
+
label
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
function PreviewNotice({
|
|
97
|
+
icon,
|
|
98
|
+
alert = false,
|
|
99
|
+
message,
|
|
100
|
+
children
|
|
101
|
+
}) {
|
|
102
|
+
return /* @__PURE__ */ jsxs(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
role: alert ? "alert" : void 0,
|
|
106
|
+
className: "flex max-w-sm flex-col items-center gap-3 p-6 text-center text-sm text-muted-foreground",
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ jsx(Icon, { icon, size: "lg" }),
|
|
109
|
+
/* @__PURE__ */ jsx("span", { children: message }),
|
|
110
|
+
children
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
PreviewDialog,
|
|
118
|
+
PreviewStage,
|
|
119
|
+
PreviewLoading,
|
|
120
|
+
PreviewNotice
|
|
121
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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 _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
5
|
+
|
|
6
|
+
// src/primitives/image.tsx
|
|
7
|
+
var _react = require('react');
|
|
8
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
9
|
+
var fitStyles = { cover: "object-cover", contain: "object-contain" };
|
|
10
|
+
var radiusStyles = { none: "", sm: "rounded-sm", md: "rounded-md", xl: "rounded-xl", full: "rounded-full" };
|
|
11
|
+
var Image = _react.forwardRef.call(void 0, function Image2({ fit = "cover", frameHeight, radius = "none", width = "auto", align = "start", border = false, shadow = "none", emphasis = "full", loadingIndicator = "none", className, onLoad, onError, src, ...props }, ref) {
|
|
12
|
+
const [loaded, setLoaded] = _react.useState.call(void 0, loadingIndicator === "none" || !src);
|
|
13
|
+
_react.useEffect.call(void 0, () => {
|
|
14
|
+
setLoaded(loadingIndicator === "none" || !src);
|
|
15
|
+
}, [loadingIndicator, src]);
|
|
16
|
+
const loading = loadingIndicator === "pulse" && !loaded;
|
|
17
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
18
|
+
"img",
|
|
19
|
+
{
|
|
20
|
+
ref,
|
|
21
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
22
|
+
fitStyles[fit],
|
|
23
|
+
radiusStyles[radius],
|
|
24
|
+
frameHeight === "sm" && "h-16",
|
|
25
|
+
frameHeight === "md" && "h-28",
|
|
26
|
+
width === "full" && "w-full",
|
|
27
|
+
width === "preview" && "w-full max-w-[380px]",
|
|
28
|
+
width === "preview-lg" && "w-full max-w-[440px]",
|
|
29
|
+
align === "center" && "mx-auto",
|
|
30
|
+
border && "border",
|
|
31
|
+
shadow === "subtle" && "shadow-xs",
|
|
32
|
+
loading && "animate-pulse bg-muted",
|
|
33
|
+
emphasis === "soft-until-parent-hover" && "transition-opacity duration-200 md:opacity-70 md:group-hover:opacity-100",
|
|
34
|
+
className
|
|
35
|
+
),
|
|
36
|
+
src,
|
|
37
|
+
...props,
|
|
38
|
+
"aria-busy": loading || void 0,
|
|
39
|
+
onLoad: (event) => {
|
|
40
|
+
setLoaded(true);
|
|
41
|
+
_optionalChain([onLoad, 'optionalCall', _ => _(event)]);
|
|
42
|
+
},
|
|
43
|
+
onError: (event) => {
|
|
44
|
+
setLoaded(true);
|
|
45
|
+
_optionalChain([onError, 'optionalCall', _2 => _2(event)]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
exports.Image = Image;
|
|
@@ -0,0 +1,143 @@
|
|
|
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; } }"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
var _chunk2BHI5ZWJcjs = require('./chunk-2BHI5ZWJ.cjs');
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _chunkWDXEJDMOcjs = require('./chunk-WDXEJDMO.cjs');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
25
|
+
|
|
26
|
+
// src/primitives/responsive-dialog.tsx
|
|
27
|
+
var _react = require('react'); var React = _interopRequireWildcard(_react);
|
|
28
|
+
var _reactresponsive = require('react-responsive');
|
|
29
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
30
|
+
var DesktopContext = React.createContext(false);
|
|
31
|
+
var useIsDesktop = () => React.useContext(DesktopContext);
|
|
32
|
+
var DESKTOP_QUERY = { minWidth: 1024 };
|
|
33
|
+
var ResponsiveDialog = ({ children, ...props }) => {
|
|
34
|
+
const isDesktop = _reactresponsive.useMediaQuery.call(void 0, DESKTOP_QUERY);
|
|
35
|
+
const Root = isDesktop ? _chunkWDXEJDMOcjs.Dialog : _chunk2BHI5ZWJcjs.Drawer;
|
|
36
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DesktopContext.Provider, { value: isDesktop, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Root, { ...props, children }) });
|
|
37
|
+
};
|
|
38
|
+
ResponsiveDialog.displayName = "ResponsiveDialog";
|
|
39
|
+
var ResponsiveDialogTrigger = ({
|
|
40
|
+
children,
|
|
41
|
+
...props
|
|
42
|
+
}) => {
|
|
43
|
+
const Trigger = useIsDesktop() ? _chunkWDXEJDMOcjs.DialogTrigger : _chunk2BHI5ZWJcjs.DrawerTrigger;
|
|
44
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Trigger, { ...props, children });
|
|
45
|
+
};
|
|
46
|
+
ResponsiveDialogTrigger.displayName = "ResponsiveDialogTrigger";
|
|
47
|
+
var ResponsiveDialogClose = ({
|
|
48
|
+
children,
|
|
49
|
+
...props
|
|
50
|
+
}) => {
|
|
51
|
+
const Close = useIsDesktop() ? _chunkWDXEJDMOcjs.DialogClose : _chunk2BHI5ZWJcjs.DrawerClose;
|
|
52
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Close, { ...props, children });
|
|
53
|
+
};
|
|
54
|
+
ResponsiveDialogClose.displayName = "ResponsiveDialogClose";
|
|
55
|
+
var ResponsiveDialogContent = React.forwardRef(({ className, children, presentation = "default", ...props }, ref) => {
|
|
56
|
+
if (useIsDesktop()) {
|
|
57
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
58
|
+
_chunkWDXEJDMOcjs.DialogContent,
|
|
59
|
+
{
|
|
60
|
+
ref,
|
|
61
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
62
|
+
"flex max-h-[85vh] max-w-md flex-col gap-0 overflow-hidden p-0",
|
|
63
|
+
presentation === "preview" && "max-w-2xl sm:h-[85vh] [&>button:last-child]:hidden",
|
|
64
|
+
className
|
|
65
|
+
),
|
|
66
|
+
...props,
|
|
67
|
+
children
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
72
|
+
_chunk2BHI5ZWJcjs.DrawerContent,
|
|
73
|
+
{
|
|
74
|
+
ref,
|
|
75
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, "max-h-[92vh]", className),
|
|
76
|
+
...props,
|
|
77
|
+
children
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
ResponsiveDialogContent.displayName = "ResponsiveDialogContent";
|
|
82
|
+
var ResponsiveDialogHeader = ({
|
|
83
|
+
className,
|
|
84
|
+
visibility = "visible",
|
|
85
|
+
...props
|
|
86
|
+
}) => {
|
|
87
|
+
const Header = useIsDesktop() ? _chunkWDXEJDMOcjs.DialogHeader : _chunk2BHI5ZWJcjs.DrawerHeader;
|
|
88
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
89
|
+
Header,
|
|
90
|
+
{
|
|
91
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0, useIsDesktop() && "p-4", visibility === "screen-reader" && "sr-only", className),
|
|
92
|
+
...props
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
ResponsiveDialogHeader.displayName = "ResponsiveDialogHeader";
|
|
97
|
+
var ResponsiveDialogBody = ({
|
|
98
|
+
className,
|
|
99
|
+
...props
|
|
100
|
+
}) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-h-0 flex-1 overflow-y-auto px-4 pb-6", className), ...props });
|
|
101
|
+
ResponsiveDialogBody.displayName = "ResponsiveDialogBody";
|
|
102
|
+
var ResponsiveDialogFooter = ({
|
|
103
|
+
className,
|
|
104
|
+
layout = "auto",
|
|
105
|
+
...props
|
|
106
|
+
}) => {
|
|
107
|
+
const isDesktop = useIsDesktop();
|
|
108
|
+
const Footer = isDesktop ? _chunkWDXEJDMOcjs.DialogFooter : _chunk2BHI5ZWJcjs.DrawerFooter;
|
|
109
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
110
|
+
Footer,
|
|
111
|
+
{
|
|
112
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
113
|
+
"mt-0 shrink-0 gap-2 border-t bg-background p-4",
|
|
114
|
+
layout === "fill" ? "flex-row space-x-0 [&>*]:min-w-0 [&>*]:flex-1" : isDesktop ? "flex-row justify-end space-x-0 [&>*]:flex-none" : "grid grid-cols-2 [&>*]:w-full",
|
|
115
|
+
className
|
|
116
|
+
),
|
|
117
|
+
...props
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
ResponsiveDialogFooter.displayName = "ResponsiveDialogFooter";
|
|
122
|
+
var ResponsiveDialogTitle = React.forwardRef(({ className, visuallyHidden = false, ...props }, ref) => {
|
|
123
|
+
const Title = useIsDesktop() ? _chunkWDXEJDMOcjs.DialogTitle : _chunk2BHI5ZWJcjs.DrawerTitle;
|
|
124
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title, { ref, className: _chunkKWLSBTB2cjs.cn.call(void 0, visuallyHidden && "sr-only", className), ...props });
|
|
125
|
+
});
|
|
126
|
+
ResponsiveDialogTitle.displayName = "ResponsiveDialogTitle";
|
|
127
|
+
var ResponsiveDialogDescription = React.forwardRef(({ className, visuallyHidden = false, ...props }, ref) => {
|
|
128
|
+
const Description = useIsDesktop() ? _chunkWDXEJDMOcjs.DialogDescription : _chunk2BHI5ZWJcjs.DrawerDescription;
|
|
129
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Description, { ref, className: _chunkKWLSBTB2cjs.cn.call(void 0, visuallyHidden && "sr-only", className), ...props });
|
|
130
|
+
});
|
|
131
|
+
ResponsiveDialogDescription.displayName = "ResponsiveDialogDescription";
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
exports.ResponsiveDialog = ResponsiveDialog; exports.ResponsiveDialogTrigger = ResponsiveDialogTrigger; exports.ResponsiveDialogClose = ResponsiveDialogClose; exports.ResponsiveDialogContent = ResponsiveDialogContent; exports.ResponsiveDialogHeader = ResponsiveDialogHeader; exports.ResponsiveDialogBody = ResponsiveDialogBody; exports.ResponsiveDialogFooter = ResponsiveDialogFooter; exports.ResponsiveDialogTitle = ResponsiveDialogTitle; exports.ResponsiveDialogDescription = ResponsiveDialogDescription;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
var _chunkBTHYGHOHcjs = require('./chunk-BTHYGHOH.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkT2ZFSPE4cjs = require('./chunk-T2ZFSPE4.cjs');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
var _chunkL4DH72UFcjs = require('./chunk-L4DH72UF.cjs');
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
var _chunkKWLSBTB2cjs = require('./chunk-KWLSBTB2.cjs');
|
|
19
|
+
|
|
20
|
+
// src/primitives/file-preview-internals.tsx
|
|
21
|
+
var _lucidereact = require('lucide-react');
|
|
22
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
23
|
+
function PreviewDialog({
|
|
24
|
+
open,
|
|
25
|
+
onOpenChange,
|
|
26
|
+
title,
|
|
27
|
+
onDownload,
|
|
28
|
+
downloading,
|
|
29
|
+
downloadLabel,
|
|
30
|
+
children
|
|
31
|
+
}) {
|
|
32
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialogContent, { presentation: "preview", className: "h-[92dvh] outline-none", children: [
|
|
33
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialogHeader, { className: "shrink-0 border-b border-border", children: [
|
|
34
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
35
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialogTitle, { className: "min-w-0 flex-1 truncate text-left", children: title }),
|
|
36
|
+
onDownload && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
37
|
+
_chunkL4DH72UFcjs.Button,
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
size: "icon-compact",
|
|
41
|
+
variant: "ghost",
|
|
42
|
+
onClick: onDownload,
|
|
43
|
+
disabled: downloading,
|
|
44
|
+
title: downloadLabel,
|
|
45
|
+
"aria-label": downloadLabel,
|
|
46
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: downloading ? _lucidereact.Loader2 : _lucidereact.Download, size: "sm", spin: downloading })
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialogClose, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
50
|
+
_chunkL4DH72UFcjs.Button,
|
|
51
|
+
{
|
|
52
|
+
type: "button",
|
|
53
|
+
size: "icon-compact",
|
|
54
|
+
variant: "ghost",
|
|
55
|
+
title: "Close preview",
|
|
56
|
+
"aria-label": "Close preview",
|
|
57
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: _lucidereact.X, size: "sm" })
|
|
58
|
+
}
|
|
59
|
+
) })
|
|
60
|
+
] }),
|
|
61
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkBTHYGHOHcjs.ResponsiveDialogDescription, { className: "sr-only", children: [
|
|
62
|
+
"Preview of ",
|
|
63
|
+
title
|
|
64
|
+
] })
|
|
65
|
+
] }),
|
|
66
|
+
children
|
|
67
|
+
] }) });
|
|
68
|
+
}
|
|
69
|
+
function PreviewStage({
|
|
70
|
+
layout = "center",
|
|
71
|
+
label,
|
|
72
|
+
children
|
|
73
|
+
}) {
|
|
74
|
+
const scrolls = layout === "scroll";
|
|
75
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
"data-slot": "preview-stage",
|
|
79
|
+
role: scrolls ? "region" : void 0,
|
|
80
|
+
"aria-label": scrolls ? label : void 0,
|
|
81
|
+
tabIndex: scrolls ? 0 : void 0,
|
|
82
|
+
className: _chunkKWLSBTB2cjs.cn.call(void 0,
|
|
83
|
+
"min-h-0 flex-1",
|
|
84
|
+
scrolls ? "overflow-y-auto overscroll-contain bg-background p-4 outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/50 sm:p-6" : "flex items-center justify-center overflow-hidden bg-muted"
|
|
85
|
+
),
|
|
86
|
+
children
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function PreviewLoading({ label }) {
|
|
91
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { role: "status", className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
92
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon: _lucidereact.Loader2, size: "sm", spin: true }),
|
|
93
|
+
label
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
function PreviewNotice({
|
|
97
|
+
icon,
|
|
98
|
+
alert = false,
|
|
99
|
+
message,
|
|
100
|
+
children
|
|
101
|
+
}) {
|
|
102
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
role: alert ? "alert" : void 0,
|
|
106
|
+
className: "flex max-w-sm flex-col items-center gap-3 p-6 text-center text-sm text-muted-foreground",
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkT2ZFSPE4cjs.Icon, { icon, size: "lg" }),
|
|
109
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: message }),
|
|
110
|
+
children
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
exports.PreviewDialog = PreviewDialog; exports.PreviewStage = PreviewStage; exports.PreviewLoading = PreviewLoading; exports.PreviewNotice = PreviewNotice;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
CopyButton
|
|
4
|
+
} from "./chunk-NW3OWKBN.js";
|
|
5
|
+
import {
|
|
6
|
+
cn
|
|
7
|
+
} from "./chunk-G6SRSWXB.js";
|
|
8
|
+
|
|
9
|
+
// src/primitives/code-block.tsx
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var HEIGHTS = {
|
|
12
|
+
none: "",
|
|
13
|
+
sm: "max-h-40 overflow-y-auto",
|
|
14
|
+
md: "max-h-64 overflow-y-auto",
|
|
15
|
+
lg: "max-h-96 overflow-y-auto",
|
|
16
|
+
viewport: "min-h-[55vh] max-h-[65vh] overflow-y-auto"
|
|
17
|
+
};
|
|
18
|
+
function CodeBlock({
|
|
19
|
+
children,
|
|
20
|
+
copy,
|
|
21
|
+
copyLabel,
|
|
22
|
+
wrap = false,
|
|
23
|
+
maxHeight = "none",
|
|
24
|
+
className
|
|
25
|
+
}) {
|
|
26
|
+
const copyText = typeof copy === "string" ? copy : children;
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
"pre",
|
|
30
|
+
{
|
|
31
|
+
className: cn(
|
|
32
|
+
"rounded-md border border-border bg-muted/40 p-3 font-mono text-xs leading-relaxed",
|
|
33
|
+
wrap ? "whitespace-pre-wrap break-words" : "overflow-x-auto",
|
|
34
|
+
HEIGHTS[maxHeight],
|
|
35
|
+
copy ? "pr-12" : void 0
|
|
36
|
+
),
|
|
37
|
+
children
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
copy ? /* @__PURE__ */ jsx(
|
|
41
|
+
CopyButton,
|
|
42
|
+
{
|
|
43
|
+
text: copyText,
|
|
44
|
+
label: copyLabel,
|
|
45
|
+
size: "sm",
|
|
46
|
+
variant: "ghost",
|
|
47
|
+
className: "absolute right-1.5 top-1.5"
|
|
48
|
+
}
|
|
49
|
+
) : null
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
CodeBlock
|
|
55
|
+
};
|