@nadicodeai/ui 0.10.0 → 0.10.2
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/AGENTS.md +2 -2
- package/README.md +1 -1
- package/dist/components/ai-elements/code-block.d.ts.map +1 -1
- package/dist/components/ai-elements/code-block.js +9 -23
- package/dist/components/ai-elements/commit.d.ts.map +1 -1
- package/dist/components/ai-elements/commit.js +9 -23
- package/dist/components/ai-elements/context.d.ts.map +1 -1
- package/dist/components/ai-elements/context.js +21 -39
- package/dist/components/ai-elements/environment-variables.d.ts.map +1 -1
- package/dist/components/ai-elements/environment-variables.js +4 -29
- package/dist/components/ai-elements/shimmer.d.ts.map +1 -1
- package/dist/components/ai-elements/shimmer.js +12 -8
- package/dist/components/ai-elements/snippet.d.ts.map +1 -1
- package/dist/components/ai-elements/snippet.js +9 -23
- package/dist/components/ai-elements/stack-trace.d.ts.map +1 -1
- package/dist/components/ai-elements/stack-trace.js +8 -21
- package/dist/components/ai-elements/terminal.d.ts.map +1 -1
- package/dist/components/ai-elements/terminal.js +8 -21
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +3 -2
- package/dist/components/badge.js +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +2 -1
- package/dist/components/chart-time-series.d.ts.map +1 -1
- package/dist/components/chart-time-series.js +2 -2
- package/dist/components/chart.js +1 -1
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +3 -2
- package/dist/components/diff-count.d.ts.map +1 -1
- package/dist/components/diff-count.js +10 -2
- package/dist/components/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu.js +2 -1
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/files-preview.d.ts.map +1 -1
- package/dist/components/files-preview.js +2 -1
- package/dist/components/input-otp.js +1 -1
- package/dist/components/logo-band.d.ts.map +1 -1
- package/dist/components/logo-band.js +8 -8
- package/dist/components/pagination.d.ts.map +1 -1
- package/dist/components/pagination.js +1 -1
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +2 -1
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +2 -1
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +3 -2
- package/dist/components/sidebar.js +1 -1
- package/dist/components/stats-band.d.ts.map +1 -1
- package/dist/components/stats-band.js +8 -8
- package/dist/components/toggle.js +1 -1
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +2 -1
- package/dist/lib/message-scroller-primitive/geometry.d.ts +1 -5
- package/dist/lib/message-scroller-primitive/geometry.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/geometry.js +1 -1
- package/dist/lib/message-scroller-primitive/stores.d.ts +2 -3
- package/dist/lib/message-scroller-primitive/stores.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/stores.js +1 -1
- package/dist/lib/message-scroller-primitive/types.d.ts +1 -2
- package/dist/lib/message-scroller-primitive/types.d.ts.map +1 -1
- package/dist/lib/message-scroller-primitive/types.js +1 -1
- package/dist/lib/motion.d.ts +12 -0
- package/dist/lib/motion.d.ts.map +1 -0
- package/dist/lib/motion.js +11 -0
- package/dist/lib/use-copy-to-clipboard.d.ts +11 -0
- package/dist/lib/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist/lib/use-copy-to-clipboard.js +27 -0
- package/dist/styles/globals.css +1 -0
- package/docs/agents/nadicodeai-ui.md +1 -1
- package/package.json +2 -2
- package/skills/nadicodeai-ui/SKILL.md +21 -0
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @nadicodeai/ui - Agent Rules
|
|
2
2
|
|
|
3
|
-
The `@nadicodeai/ui` npm workspace: the shared NadicodeAI React UI package on brand tokens (Tailwind v4, semantic light/dark roles), per ADR 0007. It ships shadcn primitives backed by Base UI, AI Elements, React adapters over the design-system grammar, reusable marketing/section compositions, and plan-approved product components once their source/export/tests/docs exist. It is source-authored in `src/` and published from built `dist` JavaScript, declarations, and CSS. Read this file before working in the component library. For website page assembly, also read
|
|
3
|
+
The `@nadicodeai/ui` npm workspace: the shared NadicodeAI React UI package on brand tokens (Tailwind v4, semantic light/dark roles), per ADR 0007. It ships shadcn primitives backed by Base UI, AI Elements, React adapters over the design-system grammar, reusable marketing/section compositions, and plan-approved product components once their source/export/tests/docs exist. It is source-authored in `src/` and published from built `dist` JavaScript, declarations, and CSS. Read this file before working in the component library. For website page assembly, also read **`../../website/AGENTS.md`**; for portal screens, read **`../../portal/AGENTS.md`**.
|
|
4
4
|
|
|
5
5
|
When this file is read from an installed package, use it as the consumer agent
|
|
6
6
|
contract: import `@nadicodeai/ui/globals.css` and
|
|
@@ -20,7 +20,7 @@ skills.
|
|
|
20
20
|
- **Dark-ready roles, no component `dark:` styling.** The generated design-system Tailwind theme owns the standard shadcn `:root` and `.dark` role maps; `globals.css` owns the Tailwind `@theme inline` bridge and UI-local product aliases. Components consume semantic utilities or product aliases such as `var(--nc-app-surface)`; they must not ship `dark:` Tailwind utilities, OS dark-mode branching, or raw dark palette utilities such as `dark:bg-slate-950` / `dark:text-white`. Enforced by `tests/guards/no-dark.test.ts`, `tests/guards/dark-semantic-roles.test.ts`, and `tests/guards/token-reference-integrity.test.ts`.
|
|
21
21
|
- **Components inherit the brand theme.** Consumers import `@nadicodeai/ui/globals.css` (Tailwind + the generated brand `@theme` + semantic role/alias maps) and `@nadicodeai/design-system/css` (kept `nc-*` geometry, type scale, chat CSS components, motion, and display components). Components carry no theme of their own — they resolve every color/radius from bridged brand tokens, UI-local aliases, and design-system CSS.
|
|
22
22
|
- **Source-authored, built package.** Components are authored as shadcn-style source in this workspace, then emitted to `dist/` for consumption by other apps. Package exports must point at built JS/declarations/CSS, not raw `src/*.tsx`, and `npm pack --dry-run` must include only intentional consumer artifacts.
|
|
23
|
-
- **Public surface changes require a release decision.** Any change to exported components, `src/index.ts`, `src/ai-elements.ts`, package `exports`, `globals.css`, UI-local semantic aliases, theme behavior, package docs, package skills, or design-system token/CSS/theme output consumed by this package must end with an explicit npm release decision before handoff. If the change should reach external consumers, bump the relevant package version(s), run `npm pack --dry-run -w @nadicodeai/ui`, and follow
|
|
23
|
+
- **Public surface changes require a release decision.** Any change to exported components, `src/index.ts`, `src/ai-elements.ts`, package `exports`, `globals.css`, UI-local semantic aliases, theme behavior, package docs, package skills, or design-system token/CSS/theme output consumed by this package must end with an explicit npm release decision before handoff. If the change should reach external consumers, bump the relevant package version(s), run `npm pack --dry-run -w @nadicodeai/ui`, and follow `../../docs/agents/npm-publishing.md`. If it cannot affect npm consumers, include the literal `[no-publish]` marker in a commit message and explain why in that commit body; the pre-push gate requires one of these two decisions. When the UI change depends on modified `@nadicodeai/design-system` output, bump/publish `@nadicodeai/design-system` first, then update `@nadicodeai/ui`'s dependency and publish UI. Never claim a UI package change is shipped to npm until `npm view @nadicodeai/ui version` reports the intended published version.
|
|
24
24
|
- **shadcn and AI Elements are package surface.** The installed shadcn source components under `src/components/` and all 48 Vercel AI Elements under `src/components/ai-elements/` are intentional ready-to-use exports. Keep `src/index.ts`, `src/ai-elements.ts`, package `exports`, README/agent docs, and `website/app/ui-check/elements` synchronized whenever this surface changes.
|
|
25
25
|
- **Base UI is the active primitive base.** `components.json` must resolve through a Base style, currently `base-nova`, and `npx shadcn@latest info --json` must report `base: "base"`. Do not reintroduce `radix-ui`, `@radix-ui/*`, or `vaul` to package source/dependencies or app optimizer configuration. Registry-owned shadcn primitives should stay aligned with current `shadcn@latest` Base UI output; use Base UI `render` composition instead of Radix `asChild`. `cmdk` is allowed only for the stock shadcn Command component while the current `base-nova` registry declares that dependency; do not use it elsewhere or replace it without a shadcn/compatibility decision and tests.
|
|
26
26
|
- **Named shadcn blocks stay named.** When a user, plan, or issue selects a shadcn block/example such as `login-02`, `signup-02`, `dashboard-01`, or `sidebar-*`, use that registry item as the source of truth through shadcn CLI/MCP. Do not replace it with a package-authored abstraction unless the plan explicitly records the substitution, the reason, and the true consumer route that proves it.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ entry stylesheet needed by consuming apps. It is intentionally coupled to
|
|
|
9
9
|
framework-agnostic geometry, fonts, assets, and CSS components; this package owns
|
|
10
10
|
React components and reusable section compositions on those tokens. Shared
|
|
11
11
|
product compositions from
|
|
12
|
-
|
|
12
|
+
`../../docs/plans/2026-06-23-001-feat-nadia-product-ui-package-plan.md` now ship
|
|
13
13
|
when their source, public subpath export, docs, and tests exist.
|
|
14
14
|
|
|
15
15
|
The package ships:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/code-block.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/code-block.tsx"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Button } from "../button.js";
|
|
4
4
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../select.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
6
7
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
7
|
-
import { createContext, memo,
|
|
8
|
+
import { createContext, memo, useContext, useEffect, useMemo, useState } from "react";
|
|
8
9
|
import { createHighlighter } from "shiki";
|
|
9
10
|
// Shiki uses bitflags for font styles: 1=italic, 2=bold, 4=underline
|
|
10
11
|
// oxlint-disable-next-line eslint(no-bitwise)
|
|
@@ -220,29 +221,14 @@ export const CodeBlock = ({ code, language, showLineNumbers = false, className,
|
|
|
220
221
|
return (_jsx(CodeBlockContext.Provider, { value: contextValue, children: _jsxs(CodeBlockContainer, { className: className, language: language, ...props, children: [children, _jsx(CodeBlockContent, { code: code, language: language, showLineNumbers: showLineNumbers })] }) }));
|
|
221
222
|
};
|
|
222
223
|
export const CodeBlockCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }) => {
|
|
223
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
224
|
-
const timeoutRef = useRef(0);
|
|
225
224
|
const { code } = useContext(CodeBlockContext);
|
|
226
|
-
const copyToClipboard =
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
await navigator.clipboard.writeText(code);
|
|
234
|
-
setIsCopied(true);
|
|
235
|
-
onCopy?.();
|
|
236
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
onError?.(error);
|
|
241
|
-
}
|
|
242
|
-
}, [code, onCopy, onError, timeout, isCopied]);
|
|
243
|
-
useEffect(() => () => {
|
|
244
|
-
window.clearTimeout(timeoutRef.current);
|
|
245
|
-
}, []);
|
|
225
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
226
|
+
text: code,
|
|
227
|
+
onCopy,
|
|
228
|
+
onError,
|
|
229
|
+
timeout,
|
|
230
|
+
skipWhileCopied: true,
|
|
231
|
+
});
|
|
246
232
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
247
233
|
return (_jsx(Button, { className: cn("shrink-0", className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 14 }) }));
|
|
248
234
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/commit.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAkB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/commit.tsx"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,9 @@ import { Avatar, AvatarFallback } from "../avatar.js";
|
|
|
4
4
|
import { Button } from "../button.js";
|
|
5
5
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../collapsible.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
7
8
|
import { CheckIcon, CopyIcon, FileIcon, GitCommitIcon, MinusIcon, PlusIcon } from "lucide-react";
|
|
8
|
-
import { useCallback, useEffect,
|
|
9
|
+
import { useCallback, useEffect, useState } from "react";
|
|
9
10
|
export const Commit = ({ className, children, ...props }) => (_jsx(Collapsible, { className: cn("rounded-lg border bg-background", className), ...props, children: children }));
|
|
10
11
|
export const CommitHeader = ({ className, children, ...props }) => (_jsx(CollapsibleTrigger, { nativeButton: false, render: _jsx("div", { className: cn("group flex cursor-pointer items-center justify-between gap-4 p-3 text-left transition-colors hover:opacity-80", className), children: children }), ...props }));
|
|
11
12
|
export const CommitHash = ({ className, children, ...props }) => (_jsxs("span", { className: cn("font-mono text-xs", className), ...props, children: [_jsx(GitCommitIcon, { className: "mr-1 inline-block size-3" }), children] }));
|
|
@@ -38,28 +39,13 @@ export const CommitActions = ({ className, children, ...props }) => (
|
|
|
38
39
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- The group only intercepts bubbled events from its interactive child controls so the parent commit is not activated.
|
|
39
40
|
_jsx("div", { className: cn("flex items-center gap-1", className), onClick: handleActionsClick, onKeyDown: handleActionsKeyDown, role: "group", ...props, children: children }));
|
|
40
41
|
export const CommitCopyButton = ({ hash, onCopy, onError, timeout = 2000, children, className, ...props }) => {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
if (!isCopied) {
|
|
50
|
-
await navigator.clipboard.writeText(hash);
|
|
51
|
-
setIsCopied(true);
|
|
52
|
-
onCopy?.();
|
|
53
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
onError?.(error);
|
|
58
|
-
}
|
|
59
|
-
}, [hash, onCopy, onError, timeout, isCopied]);
|
|
60
|
-
useEffect(() => () => {
|
|
61
|
-
window.clearTimeout(timeoutRef.current);
|
|
62
|
-
}, []);
|
|
42
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
43
|
+
text: hash,
|
|
44
|
+
onCopy,
|
|
45
|
+
onError,
|
|
46
|
+
timeout,
|
|
47
|
+
skipWhileCopied: true,
|
|
48
|
+
});
|
|
63
49
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
64
50
|
return (_jsx(Button, { className: cn("size-7 shrink-0", className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 14 }) }));
|
|
65
51
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAGxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAGxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAqB5C,KAAK,OAAO,GAAG,MAAM,CAAC;AAEtB,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAcD,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG,aAAa,CAAC;AAE5E,eAAO,MAAM,OAAO,GAAI,qDAAqD,YAAY,gCAWxF,CAAC;AA2CF,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc,GAAI,wBAAwB,mBAAmB,gCAmBzE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1E,eAAO,MAAM,cAAc,GAAI,yBAAyB,mBAAmB,gCAE1E,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,GAAI,mCAIlC,yBAAyB,gCAwB3B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE5D,eAAO,MAAM,kBAAkB,GAAI,mCAAmC,uBAAuB,gCAI5F,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,GAAI,mCAIlC,yBAAyB,gCA6B3B,CAAC;AASF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE3D,eAAO,MAAM,iBAAiB,GAAI,mCAAmC,sBAAsB,iVA0B1F,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE5D,eAAO,MAAM,kBAAkB,GAAI,mCAAmC,uBAAuB,iVA0B5F,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE/D,eAAO,MAAM,qBAAqB,GAAI,mCAInC,0BAA0B,iVA0B5B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAE3D,eAAO,MAAM,iBAAiB,GAAI,mCAAmC,sBAAsB,iVA0B1F,CAAC"}
|
|
@@ -11,6 +11,17 @@ const ICON_RADIUS = 10;
|
|
|
11
11
|
const ICON_VIEWBOX = 24;
|
|
12
12
|
const ICON_CENTER = 12;
|
|
13
13
|
const ICON_STROKE_WIDTH = 2;
|
|
14
|
+
const PERCENT_FORMATTER = new Intl.NumberFormat("en-US", {
|
|
15
|
+
maximumFractionDigits: 1,
|
|
16
|
+
style: "percent",
|
|
17
|
+
});
|
|
18
|
+
const COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat("en-US", {
|
|
19
|
+
notation: "compact",
|
|
20
|
+
});
|
|
21
|
+
const USD_FORMATTER = new Intl.NumberFormat("en-US", {
|
|
22
|
+
currency: "USD",
|
|
23
|
+
style: "currency",
|
|
24
|
+
});
|
|
14
25
|
const ContextContext = createContext(null);
|
|
15
26
|
const useContextValue = () => {
|
|
16
27
|
const context = useContext(ContextContext);
|
|
@@ -33,10 +44,7 @@ const ContextIcon = () => {
|
|
|
33
44
|
export const ContextTrigger = ({ children, ...props }) => {
|
|
34
45
|
const { usedTokens, maxTokens } = useContextValue();
|
|
35
46
|
const usedPercent = usedTokens / maxTokens;
|
|
36
|
-
const renderedPercent =
|
|
37
|
-
maximumFractionDigits: 1,
|
|
38
|
-
style: "percent",
|
|
39
|
-
}).format(usedPercent);
|
|
47
|
+
const renderedPercent = PERCENT_FORMATTER.format(usedPercent);
|
|
40
48
|
const trigger = isValidElement(children) ? (children) : (_jsx(Button, { type: "button", variant: "ghost", ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium text-muted-foreground", children: renderedPercent }), _jsx(ContextIcon, {})] })) }));
|
|
41
49
|
return _jsx(HoverCardTrigger, { closeDelay: 0, delay: 0, render: trigger });
|
|
42
50
|
};
|
|
@@ -44,16 +52,9 @@ export const ContextContent = ({ className, ...props }) => (_jsx(HoverCardConten
|
|
|
44
52
|
export const ContextContentHeader = ({ children, className, ...props }) => {
|
|
45
53
|
const { usedTokens, maxTokens } = useContextValue();
|
|
46
54
|
const usedPercent = usedTokens / maxTokens;
|
|
47
|
-
const displayPct =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}).format(usedPercent);
|
|
51
|
-
const used = new Intl.NumberFormat("en-US", {
|
|
52
|
-
notation: "compact",
|
|
53
|
-
}).format(usedTokens);
|
|
54
|
-
const total = new Intl.NumberFormat("en-US", {
|
|
55
|
-
notation: "compact",
|
|
56
|
-
}).format(maxTokens);
|
|
55
|
+
const displayPct = PERCENT_FORMATTER.format(usedPercent);
|
|
56
|
+
const used = COMPACT_NUMBER_FORMATTER.format(usedTokens);
|
|
57
|
+
const total = COMPACT_NUMBER_FORMATTER.format(maxTokens);
|
|
57
58
|
return (_jsx("div", { className: cn("flex w-full flex-col gap-2 p-3", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [_jsx("p", { children: displayPct }), _jsxs("p", { className: "font-mono text-muted-foreground", children: [used, " / ", total] })] }), _jsx("div", { className: "flex flex-col gap-2", children: _jsx(Progress, { className: "bg-muted", value: usedPercent * PERCENT_MAX }) })] })) }));
|
|
58
59
|
};
|
|
59
60
|
export const ContextContentBody = ({ children, className, ...props }) => (_jsx("div", { className: cn("w-full p-3", className), ...props, children: children }));
|
|
@@ -68,17 +69,10 @@ export const ContextContentFooter = ({ children, className, ...props }) => {
|
|
|
68
69
|
},
|
|
69
70
|
}).costUSD?.totalUSD
|
|
70
71
|
: undefined;
|
|
71
|
-
const totalCost =
|
|
72
|
-
currency: "USD",
|
|
73
|
-
style: "currency",
|
|
74
|
-
}).format(costUSD ?? 0);
|
|
72
|
+
const totalCost = USD_FORMATTER.format(costUSD ?? 0);
|
|
75
73
|
return (_jsx("div", { className: cn("flex w-full items-center justify-between gap-3 bg-secondary p-3 text-xs", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-muted-foreground", children: "Total cost" }), _jsx("span", { children: totalCost })] })) }));
|
|
76
74
|
};
|
|
77
|
-
const TokensWithCost = ({ tokens, costText }) => (_jsxs("span", { children: [tokens === undefined
|
|
78
|
-
? "—"
|
|
79
|
-
: new Intl.NumberFormat("en-US", {
|
|
80
|
-
notation: "compact",
|
|
81
|
-
}).format(tokens), costText ? _jsxs("span", { className: "ml-2 text-muted-foreground", children: ["\u2022 ", costText] }) : null] }));
|
|
75
|
+
const TokensWithCost = ({ tokens, costText }) => (_jsxs("span", { children: [tokens === undefined ? "—" : COMPACT_NUMBER_FORMATTER.format(tokens), costText ? _jsxs("span", { className: "ml-2 text-muted-foreground", children: ["\u2022 ", costText] }) : null] }));
|
|
82
76
|
export const ContextInputUsage = ({ className, children, ...props }) => {
|
|
83
77
|
const { usage, modelId } = useContextValue();
|
|
84
78
|
const inputTokens = usage?.inputTokens ?? 0;
|
|
@@ -94,10 +88,7 @@ export const ContextInputUsage = ({ className, children, ...props }) => {
|
|
|
94
88
|
usage: { input: inputTokens, output: 0 },
|
|
95
89
|
}).costUSD?.totalUSD
|
|
96
90
|
: undefined;
|
|
97
|
-
const inputCostText =
|
|
98
|
-
currency: "USD",
|
|
99
|
-
style: "currency",
|
|
100
|
-
}).format(inputCost ?? 0);
|
|
91
|
+
const inputCostText = USD_FORMATTER.format(inputCost ?? 0);
|
|
101
92
|
return (_jsxs("div", { className: cn("flex items-center justify-between text-xs", className), ...props, children: [_jsx("span", { className: "text-muted-foreground", children: "Input" }), _jsx(TokensWithCost, { costText: inputCostText, tokens: inputTokens })] }));
|
|
102
93
|
};
|
|
103
94
|
export const ContextOutputUsage = ({ className, children, ...props }) => {
|
|
@@ -115,10 +106,7 @@ export const ContextOutputUsage = ({ className, children, ...props }) => {
|
|
|
115
106
|
usage: { input: 0, output: outputTokens },
|
|
116
107
|
}).costUSD?.totalUSD
|
|
117
108
|
: undefined;
|
|
118
|
-
const outputCostText =
|
|
119
|
-
currency: "USD",
|
|
120
|
-
style: "currency",
|
|
121
|
-
}).format(outputCost ?? 0);
|
|
109
|
+
const outputCostText = USD_FORMATTER.format(outputCost ?? 0);
|
|
122
110
|
return (_jsxs("div", { className: cn("flex items-center justify-between text-xs", className), ...props, children: [_jsx("span", { className: "text-muted-foreground", children: "Output" }), _jsx(TokensWithCost, { costText: outputCostText, tokens: outputTokens })] }));
|
|
123
111
|
};
|
|
124
112
|
export const ContextReasoningUsage = ({ className, children, ...props }) => {
|
|
@@ -136,10 +124,7 @@ export const ContextReasoningUsage = ({ className, children, ...props }) => {
|
|
|
136
124
|
usage: { reasoningTokens },
|
|
137
125
|
}).costUSD?.totalUSD
|
|
138
126
|
: undefined;
|
|
139
|
-
const reasoningCostText =
|
|
140
|
-
currency: "USD",
|
|
141
|
-
style: "currency",
|
|
142
|
-
}).format(reasoningCost ?? 0);
|
|
127
|
+
const reasoningCostText = USD_FORMATTER.format(reasoningCost ?? 0);
|
|
143
128
|
return (_jsxs("div", { className: cn("flex items-center justify-between text-xs", className), ...props, children: [_jsx("span", { className: "text-muted-foreground", children: "Reasoning" }), _jsx(TokensWithCost, { costText: reasoningCostText, tokens: reasoningTokens })] }));
|
|
144
129
|
};
|
|
145
130
|
export const ContextCacheUsage = ({ className, children, ...props }) => {
|
|
@@ -157,9 +142,6 @@ export const ContextCacheUsage = ({ className, children, ...props }) => {
|
|
|
157
142
|
usage: { cacheReads: cacheTokens, input: 0, output: 0 },
|
|
158
143
|
}).costUSD?.totalUSD
|
|
159
144
|
: undefined;
|
|
160
|
-
const cacheCostText =
|
|
161
|
-
currency: "USD",
|
|
162
|
-
style: "currency",
|
|
163
|
-
}).format(cacheCost ?? 0);
|
|
145
|
+
const cacheCostText = USD_FORMATTER.format(cacheCost ?? 0);
|
|
164
146
|
return (_jsxs("div", { className: cn("flex items-center justify-between text-xs", className), ...props, children: [_jsx("span", { className: "text-muted-foreground", children: "Cache" }), _jsx(TokensWithCost, { costText: cacheCostText, tokens: cacheTokens })] }));
|
|
165
147
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment-variables.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/environment-variables.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"environment-variables.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/environment-variables.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAiB5D,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,4GAOlC,yBAAyB,gCAqB3B,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAE7E,eAAO,MAAM,0BAA0B,GAAI,mCAIxC,+BAA+B,gCAIjC,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAEhF,eAAO,MAAM,yBAAyB,GAAI,mCAIvC,8BAA8B,gCAIhC,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,0BAA0B,GAAI,yBAGxC,+BAA+B,gCAgBjC,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAE9E,eAAO,MAAM,2BAA2B,GAAI,mCAIzC,gCAAgC,gCAIlC,CAAC;AAYF,MAAM,MAAM,6BAA6B,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAE3E,eAAO,MAAM,wBAAwB,GAAI,mCAItC,6BAA6B,gCAI/B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAE3E,eAAO,MAAM,uBAAuB,GAAI,mCAIrC,4BAA4B,gCAQ9B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAE5E,eAAO,MAAM,wBAAwB,GAAI,mCAItC,6BAA6B,gCAkB/B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,gDAMjC,wBAAwB,gCAoB1B,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IAC/E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC1C,CAAC;AAEF,eAAO,MAAM,6BAA6B,GAAI,yEAQ3C,kCAAkC,gCAmBpC,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,cAAc,CAAC,OAAO,KAAK,CAAC,CAAC;AAE5E,eAAO,MAAM,2BAA2B,GAAI,mCAIzC,gCAAgC,gCAIlC,CAAC"}
|
|
@@ -4,8 +4,9 @@ import { Badge } from "../badge.js";
|
|
|
4
4
|
import { Button } from "../button.js";
|
|
5
5
|
import { Switch } from "../switch.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
7
8
|
import { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from "lucide-react";
|
|
8
|
-
import { createContext, useCallback, useContext,
|
|
9
|
+
import { createContext, useCallback, useContext, useMemo, useState } from "react";
|
|
9
10
|
// Default noop for context default value
|
|
10
11
|
// oxlint-disable-next-line eslint(no-empty-function)
|
|
11
12
|
const noop = () => { };
|
|
@@ -50,35 +51,9 @@ export const EnvironmentVariable = ({ name, value, className, children, ...props
|
|
|
50
51
|
return (_jsx(EnvironmentVariableContext.Provider, { value: envVarContextValue, children: _jsx("div", { className: cn("flex items-center justify-between gap-4 px-4 py-3", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx(EnvironmentVariableName, {}) }), _jsx(EnvironmentVariableValue, {})] })) }) }));
|
|
51
52
|
};
|
|
52
53
|
export const EnvironmentVariableCopyButton = ({ onCopy, onError, timeout = 2000, copyFormat = "value", children, className, ...props }) => {
|
|
53
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
54
|
-
const timeoutRef = useRef(0);
|
|
55
54
|
const { name, value } = useContext(EnvironmentVariableContext);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
export: () => `export ${name}="${value}"`,
|
|
59
|
-
name: () => name,
|
|
60
|
-
value: () => value,
|
|
61
|
-
};
|
|
62
|
-
return formatMap[copyFormat]();
|
|
63
|
-
}, [name, value, copyFormat]);
|
|
64
|
-
const copyToClipboard = useCallback(async () => {
|
|
65
|
-
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
|
|
66
|
-
onError?.(new Error("Clipboard API not available"));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
await navigator.clipboard.writeText(getTextToCopy());
|
|
71
|
-
setIsCopied(true);
|
|
72
|
-
onCopy?.();
|
|
73
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
onError?.(error);
|
|
77
|
-
}
|
|
78
|
-
}, [getTextToCopy, onCopy, onError, timeout]);
|
|
79
|
-
useEffect(() => () => {
|
|
80
|
-
window.clearTimeout(timeoutRef.current);
|
|
81
|
-
}, []);
|
|
55
|
+
const text = copyFormat === "export" ? `export ${name}="${value}"` : copyFormat === "name" ? name : value;
|
|
56
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({ text, onCopy, onError, timeout });
|
|
82
57
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
83
58
|
return (_jsx(Button, { className: cn("size-6 shrink-0", className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 12 }) }));
|
|
84
59
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shimmer.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/shimmer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shimmer.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/shimmer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAiB,WAAW,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAsB7D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8CD,eAAO,MAAM,OAAO,kGAtCjB,gBAAgB,iBAsC0B,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { motion } from "motion/react";
|
|
3
|
+
import { motion, useReducedMotion } from "motion/react";
|
|
5
4
|
import { memo, useMemo } from "react";
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
6
|
// Cache motion components at module level to avoid creating during render
|
|
7
7
|
const motionComponentCache = new Map();
|
|
8
8
|
const getMotionComponent = (element) => {
|
|
@@ -14,15 +14,19 @@ const getMotionComponent = (element) => {
|
|
|
14
14
|
return component;
|
|
15
15
|
};
|
|
16
16
|
const ShimmerComponent = ({ children, as: Component = "p", className, duration = 2, spread = 2, }) => {
|
|
17
|
+
const shouldReduceMotion = useReducedMotion();
|
|
17
18
|
const MotionComponent = getMotionComponent(Component);
|
|
18
19
|
const dynamicSpread = useMemo(() => (children?.length ?? 0) * spread, [children, spread]);
|
|
19
|
-
return (_jsx(MotionComponent, { animate: { backgroundPosition: "0% center" }, className: cn("relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent", "[--bg:linear-gradient(90deg,transparent_calc(50%-var(--spread)),var(--color-background),transparent_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]", className), initial: { backgroundPosition: "100% center" }, style: {
|
|
20
|
+
return (_jsx(MotionComponent, { animate: shouldReduceMotion ? undefined : { backgroundPosition: "0% center" }, className: cn("relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent", "[--bg:linear-gradient(90deg,transparent_calc(50%-var(--spread)),var(--color-background),transparent_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]", className), initial: shouldReduceMotion ? false : { backgroundPosition: "100% center" }, style: {
|
|
20
21
|
"--spread": `${dynamicSpread}px`,
|
|
21
22
|
backgroundImage: "var(--bg), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
...(shouldReduceMotion ? { backgroundPosition: "50% center" } : {}),
|
|
24
|
+
}, transition: shouldReduceMotion
|
|
25
|
+
? undefined
|
|
26
|
+
: {
|
|
27
|
+
duration,
|
|
28
|
+
ease: "linear",
|
|
29
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
30
|
+
}, children: children }));
|
|
27
31
|
};
|
|
28
32
|
export const Shimmer = memo(ShimmerComponent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snippet.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/snippet.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACf,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"snippet.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/snippet.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,EACf,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAW5C,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,GAAG;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,yCAAyC,YAAY,gCAU5E,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,eAAe,CAAC,CAAC;AAEvE,eAAO,MAAM,YAAY,GAAI,OAAO,iBAAiB,gCAAmC,CAAC;AAEzF,MAAM,MAAM,gBAAgB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AAErE,eAAO,MAAM,WAAW,GAAI,yBAAyB,gBAAgB,gCAEpE,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;AAEnG,eAAO,MAAM,YAAY,GAAI,yBAAyB,iBAAiB,gCAWtE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC7E,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,6DAO/B,sBAAsB,gCAwBxB,CAAC"}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, } from "../input-group.js";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
5
6
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
6
|
-
import { createContext,
|
|
7
|
+
import { createContext, useContext, useMemo } from "react";
|
|
7
8
|
const SnippetContext = createContext({
|
|
8
9
|
code: "",
|
|
9
10
|
});
|
|
@@ -18,29 +19,14 @@ export const SnippetInput = ({ className, ...props }) => {
|
|
|
18
19
|
return (_jsx(InputGroupInput, { className: cn("text-foreground", className), readOnly: true, value: code, ...props }));
|
|
19
20
|
};
|
|
20
21
|
export const SnippetCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }) => {
|
|
21
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
22
|
-
const timeoutRef = useRef(0);
|
|
23
22
|
const { code } = useContext(SnippetContext);
|
|
24
|
-
const copyToClipboard =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
await navigator.clipboard.writeText(code);
|
|
32
|
-
setIsCopied(true);
|
|
33
|
-
onCopy?.();
|
|
34
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
onError?.(error);
|
|
39
|
-
}
|
|
40
|
-
}, [code, onCopy, onError, timeout, isCopied]);
|
|
41
|
-
useEffect(() => () => {
|
|
42
|
-
window.clearTimeout(timeoutRef.current);
|
|
43
|
-
}, []);
|
|
23
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
24
|
+
text: code,
|
|
25
|
+
onCopy,
|
|
26
|
+
onError,
|
|
27
|
+
timeout,
|
|
28
|
+
skipWhileCopied: true,
|
|
29
|
+
});
|
|
44
30
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
45
31
|
return (_jsx(InputGroupButton, { "aria-label": "Copy", className: className, onClick: copyToClipboard, size: "icon-sm", title: "Copy", ...props, children: children ?? _jsx(Icon, { className: "size-3.5", size: 14 }) }));
|
|
46
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack-trace.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/stack-trace.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAe,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"stack-trace.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/stack-trace.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAe,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAmI5C,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9E,CAAC;AAEF,eAAO,MAAM,UAAU,mIAUlB,eAAe,iCAkCnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9E,eAAO,MAAM,gBAAgB,0EAA4C,qBAAqB,iCAqB5F,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAEzD,eAAO,MAAM,eAAe,0EAA4C,oBAAoB,iCAK1F,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAE9D,eAAO,MAAM,mBAAmB,0EACM,wBAAwB,iCAS7D,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAEjE,eAAO,MAAM,sBAAsB,0EACG,2BAA2B,iCAShE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAS3D,eAAO,MAAM,iBAAiB,0EACQ,sBAAsB,iCAY3D,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACtE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,oBAAoB,oGAQ5B,yBAAyB,iCAuB7B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;AAEhE,eAAO,MAAM,sBAAsB,gEACP,2BAA2B,iCActD,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,kBAAkB,CAAC,GAAG;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,qFACyB,sBAAsB,iCAmB5E,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG;IAC1D,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAqCF,eAAO,MAAM,gBAAgB,oFAC0B,qBAAqB,iCAyC3E,CAAC"}
|
|
@@ -4,8 +4,9 @@ import { useControllableState } from "../../hooks/use-controllable-state.js";
|
|
|
4
4
|
import { Button } from "../button.js";
|
|
5
5
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../collapsible.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
7
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
7
8
|
import { AlertTriangleIcon, CheckIcon, ChevronDownIcon, CopyIcon } from "lucide-react";
|
|
8
|
-
import { createContext, memo, useCallback, useContext,
|
|
9
|
+
import { createContext, memo, useCallback, useContext, useMemo } from "react";
|
|
9
10
|
// Regex patterns for parsing stack traces
|
|
10
11
|
const STACK_FRAME_WITH_PARENS_REGEX = /^at\s+(.+?)\s+\((.+):(\d+):(\d+)\)$/;
|
|
11
12
|
const STACK_FRAME_WITHOUT_FN_REGEX = /^at\s+(.+):(\d+):(\d+)$/;
|
|
@@ -134,27 +135,13 @@ export const StackTraceActions = memo(({ className, children, ...props }) => (
|
|
|
134
135
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- The group only intercepts bubbled events from its interactive child controls so the parent stack frame is not activated.
|
|
135
136
|
_jsx("div", { className: cn("flex shrink-0 items-center gap-1", className), onClick: handleActionsClick, onKeyDown: handleActionsKeyDown, role: "group", ...props, children: children })));
|
|
136
137
|
export const StackTraceCopyButton = memo(({ onCopy, onError, timeout = 2000, className, children, ...props }) => {
|
|
137
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
138
|
-
const timeoutRef = useRef(0);
|
|
139
138
|
const { raw } = useStackTrace();
|
|
140
|
-
const copyToClipboard =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
await navigator.clipboard.writeText(raw);
|
|
147
|
-
setIsCopied(true);
|
|
148
|
-
onCopy?.();
|
|
149
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
150
|
-
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
onError?.(error);
|
|
153
|
-
}
|
|
154
|
-
}, [raw, onCopy, onError, timeout]);
|
|
155
|
-
useEffect(() => () => {
|
|
156
|
-
window.clearTimeout(timeoutRef.current);
|
|
157
|
-
}, []);
|
|
139
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
140
|
+
text: raw,
|
|
141
|
+
onCopy,
|
|
142
|
+
onError,
|
|
143
|
+
timeout,
|
|
144
|
+
});
|
|
158
145
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
159
146
|
return (_jsx(Button, { className: cn("size-7", className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 14 }) }));
|
|
160
147
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/terminal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/components/ai-elements/terminal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAK7C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAgB5D,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAEjE,eAAO,MAAM,cAAc,GAAI,mCAAmC,mBAAmB,gCAUpF,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAEhE,eAAO,MAAM,aAAa,GAAI,mCAAmC,kBAAkB,gCAQlF,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAEjE,eAAO,MAAM,cAAc,GAAI,mCAAmC,mBAAmB,uCAepF,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAElE,eAAO,MAAM,eAAe,GAAI,mCAAmC,oBAAoB,gCAItF,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG;IACpE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,6DAOhC,uBAAuB,gCAyBzB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC;AAErE,eAAO,MAAM,mBAAmB,GAAI,mCAIjC,wBAAwB,uCAqB1B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;AAElE,eAAO,MAAM,eAAe,GAAI,mCAAmC,oBAAoB,gCA0BtF,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,6EAQtB,aAAa,gCAiCf,CAAC"}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { Button } from "../button.js";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { useCopyToClipboard } from "../../lib/use-copy-to-clipboard.js";
|
|
5
6
|
import Ansi from "ansi-to-react";
|
|
6
7
|
import { CheckIcon, CopyIcon, TerminalIcon, Trash2Icon } from "lucide-react";
|
|
7
|
-
import { createContext,
|
|
8
|
+
import { createContext, useContext, useEffect, useMemo, useRef } from "react";
|
|
8
9
|
const TerminalContext = createContext({
|
|
9
10
|
autoScroll: true,
|
|
10
11
|
isStreaming: false,
|
|
@@ -21,27 +22,13 @@ export const TerminalStatus = ({ className, children, ...props }) => {
|
|
|
21
22
|
};
|
|
22
23
|
export const TerminalActions = ({ className, children, ...props }) => (_jsx("div", { className: cn("flex items-center gap-1", className), ...props, children: children }));
|
|
23
24
|
export const TerminalCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }) => {
|
|
24
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
25
|
-
const timeoutRef = useRef(0);
|
|
26
25
|
const { output } = useContext(TerminalContext);
|
|
27
|
-
const copyToClipboard =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await navigator.clipboard.writeText(output);
|
|
34
|
-
setIsCopied(true);
|
|
35
|
-
onCopy?.();
|
|
36
|
-
timeoutRef.current = window.setTimeout(() => setIsCopied(false), timeout);
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
onError?.(error);
|
|
40
|
-
}
|
|
41
|
-
}, [output, onCopy, onError, timeout]);
|
|
42
|
-
useEffect(() => () => {
|
|
43
|
-
window.clearTimeout(timeoutRef.current);
|
|
44
|
-
}, []);
|
|
26
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
27
|
+
text: output,
|
|
28
|
+
onCopy,
|
|
29
|
+
onError,
|
|
30
|
+
timeout,
|
|
31
|
+
});
|
|
45
32
|
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
46
33
|
return (_jsx(Button, { className: cn("size-7 shrink-0 text-primary-foreground/70 hover:bg-primary-foreground/10 hover:text-primary-foreground", className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 14 }) }));
|
|
47
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../src/components/alert-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../src/components/alert-dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAIlF,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,iBAAS,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,IAAI,CAAC,KAAK,qBAEjE;AAED,iBAAS,kBAAkB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,qBAE3E;AAED,iBAAS,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,qBAEzE;AAED,iBAAS,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,QAAQ,CAAC,KAAK,qBAQvF;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GAAG;IACpC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,qBAgBA;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW9E;AAED,iBAAS,iBAAiB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW9E;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW7E;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,KAAK,CAAC,qBAWzD;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,WAAW,CAAC,qBAW/D;AAID,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GACjC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,qBAS9D;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GACjC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,qBAS9D;AAED,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
|
|
4
4
|
import { cn } from "../lib/utils.js";
|
|
5
|
+
import { modalOverlayMotion, overlayBackdropMotion } from "../lib/motion.js";
|
|
5
6
|
import { Button } from "./button.js";
|
|
6
7
|
function AlertDialog({ ...props }) {
|
|
7
8
|
return _jsx(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
|
|
@@ -13,10 +14,10 @@ function AlertDialogPortal({ ...props }) {
|
|
|
13
14
|
return _jsx(AlertDialogPrimitive.Portal, { "data-slot": "alert-dialog-portal", ...props });
|
|
14
15
|
}
|
|
15
16
|
function AlertDialogOverlay({ className, ...props }) {
|
|
16
|
-
return (_jsx(AlertDialogPrimitive.Backdrop, { "data-slot": "alert-dialog-overlay", className: cn("fixed inset-0 isolate z-50 bg-scrim/scrim
|
|
17
|
+
return (_jsx(AlertDialogPrimitive.Backdrop, { "data-slot": "alert-dialog-overlay", className: cn("fixed inset-0 isolate z-50 bg-scrim/scrim", overlayBackdropMotion, className), ...props }));
|
|
17
18
|
}
|
|
18
19
|
function AlertDialogContent({ className, size = "default", ...props }) {
|
|
19
|
-
return (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Popup, { "data-slot": "alert-dialog-content", "data-size": size, className: cn("group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-nadicode-md rounded-2xl border border-border bg-popover p-nadicode-lg text-popover-foreground shadow-dialog
|
|
20
|
+
return (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Popup, { "data-slot": "alert-dialog-content", "data-size": size, className: cn("group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-nadicode-md rounded-2xl border border-border bg-popover p-nadicode-lg text-popover-foreground shadow-dialog outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm", modalOverlayMotion, className), ...props })] }));
|
|
20
21
|
}
|
|
21
22
|
function AlertDialogHeader({ className, ...props }) {
|
|
22
23
|
return (_jsx("div", { "data-slot": "alert-dialog-header", className: cn("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", className), ...props }));
|