@burtson-labs/ui 0.5.1 → 0.7.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 (35) hide show
  1. package/README.md +1 -1
  2. package/dist/components/composer.d.ts +30 -0
  3. package/dist/components/composer.js +95 -0
  4. package/dist/components/composer.js.map +1 -0
  5. package/dist/components/conversation.d.ts +14 -0
  6. package/dist/components/conversation.js +78 -0
  7. package/dist/components/conversation.js.map +1 -0
  8. package/dist/components/copy-button.d.ts +15 -0
  9. package/dist/components/copy-button.js +47 -0
  10. package/dist/components/copy-button.js.map +1 -0
  11. package/dist/components/markdown.d.ts +33 -0
  12. package/dist/components/markdown.js +177 -0
  13. package/dist/components/markdown.js.map +1 -0
  14. package/dist/components/message.d.ts +21 -0
  15. package/dist/components/message.js +56 -0
  16. package/dist/components/message.js.map +1 -0
  17. package/dist/components/reasoning.d.ts +14 -0
  18. package/dist/components/reasoning.js +61 -0
  19. package/dist/components/reasoning.js.map +1 -0
  20. package/dist/components/secret-input.d.ts +11 -0
  21. package/dist/components/secret-input.js +40 -0
  22. package/dist/components/secret-input.js.map +1 -0
  23. package/dist/components/slider.d.ts +15 -0
  24. package/dist/components/slider.js +31 -0
  25. package/dist/components/slider.js.map +1 -0
  26. package/dist/components/toaster.d.ts +20 -0
  27. package/dist/components/toaster.js +61 -0
  28. package/dist/components/toaster.js.map +1 -0
  29. package/dist/components/tool-call.d.ts +32 -0
  30. package/dist/components/tool-call.js +152 -0
  31. package/dist/components/tool-call.js.map +1 -0
  32. package/dist/index.d.ts +10 -0
  33. package/dist/index.js +13 -3
  34. package/dist/styles.css +1 -1
  35. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.js","names":[],"sources":["../../src/components/message.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport type MessageRole = 'user' | 'assistant' | 'system';\n\nexport interface MessageProps extends React.ComponentProps<'div'> {\n /** Who wrote it. (Not `role`, which is the ARIA attribute.) */\n from: MessageRole;\n /** Avatar or agent mark beside assistant messages. */\n avatar?: React.ReactNode;\n /** Sender name shown above the message, e.g. the agent's name. */\n name?: React.ReactNode;\n /** Timestamp or status text. */\n meta?: React.ReactNode;\n /** Actions such as copy and retry, shown on hover and focus. */\n actions?: React.ReactNode;\n}\n\n/**\n * One turn in a conversation. User turns sit on the right in a quiet bubble,\n * assistant turns read full width with an optional avatar, and system notes\n * are centred and small.\n */\nfunction Message({\n from,\n avatar,\n name,\n meta,\n actions,\n children,\n className,\n ...props\n}: MessageProps) {\n if (from === 'system') {\n return (\n <div\n data-slot=\"message\"\n data-role=\"system\"\n className={cn('mx-auto max-w-prose text-center text-xs text-muted-foreground', className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n const user = from === 'user';\n return (\n <div\n data-slot=\"message\"\n data-role={from}\n className={cn(\n 'group/message flex animate-in gap-3',\n user ? 'justify-end' : 'justify-start',\n className,\n )}\n {...props}\n >\n {!user && avatar && (\n <div className=\"mt-0.5 grid size-7 shrink-0 place-items-center overflow-hidden rounded-md border border-brand/15 bg-brand-soft text-brand [&_svg]:size-4\">\n {avatar}\n </div>\n )}\n <div\n className={cn('grid min-w-0 gap-1.5', user ? 'max-w-[85%] justify-items-end' : 'flex-1')}\n >\n {(name || meta) && (\n <div className=\"flex items-baseline gap-2 text-xs\">\n {name && <span className=\"font-semibold text-foreground\">{name}</span>}\n {meta && <span className=\"text-muted-foreground\">{meta}</span>}\n </div>\n )}\n <div\n data-slot=\"message-body\"\n className={cn(\n 'min-w-0 text-sm leading-6',\n user && 'rounded-lg rounded-tr-xs bg-secondary px-3.5 py-2 text-secondary-foreground',\n )}\n >\n {children}\n </div>\n {actions && (\n <div className=\"flex gap-1 opacity-0 transition-opacity group-focus-within/message:opacity-100 group-hover/message:opacity-100 max-md:opacity-100\">\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport { Message };\n"],"mappings":";;;;;;;;;AAwBA,SAAS,QAAQ,EACf,MACA,QACA,MACA,MACA,SACA,UACA,WACA,GAAG,SACY;CACf,IAAI,SAAS,UACX,OACE,oBAAC,OAAD;EACE,aAAU;EACV,aAAU;EACV,WAAW,GAAG,iEAAiE,SAAS;EACxF,GAAI;EAEH;CACE,CAAA;CAGT,MAAM,OAAO,SAAS;CACtB,OACE,qBAAC,OAAD;EACE,aAAU;EACV,aAAW;EACX,WAAW,GACT,uCACA,OAAO,gBAAgB,iBACvB,SACF;EACA,GAAI;EARN,UAAA,CAUG,CAAC,QAAQ,UACR,oBAAC,OAAD;GAAK,WAAU;GACZ,UAAA;EACE,CAAA,GAEP,qBAAC,OAAD;GACE,WAAW,GAAG,wBAAwB,OAAO,kCAAkC,QAAQ;GADzF,UAAA;KAGI,QAAQ,SACR,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACG,QAAQ,oBAAC,QAAD;MAAM,WAAU;MAAiC,UAAA;KAAW,CAAA,GACpE,QAAQ,oBAAC,QAAD;MAAM,WAAU;MAAyB,UAAA;KAAW,CAAA,CAC1D;;IAEP,oBAAC,OAAD;KACE,aAAU;KACV,WAAW,GACT,6BACA,QAAQ,6EACV;KAEC;IACE,CAAA;IACJ,WACC,oBAAC,OAAD;KAAK,WAAU;KACZ,UAAA;IACE,CAAA;GAEJ;EACF,CAAA,CAAA;;AAET"}
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ export interface ReasoningProps extends React.ComponentProps<'div'> {
3
+ /** True while the model is still thinking. */
4
+ streaming?: boolean;
5
+ durationMs?: number;
6
+ defaultOpen?: boolean;
7
+ }
8
+ /** A model's reasoning, collapsed to one line ("Thought for 3s") unless opened. */
9
+ declare function Reasoning({ streaming, durationMs, defaultOpen, children, className, ...props }: ReasoningProps): React.JSX.Element;
10
+ /** Three pulsing dots while a reply is on its way. Still under reduced motion. */
11
+ declare function StreamingIndicator({ className, label, ...props }: React.ComponentProps<'span'> & {
12
+ label?: string;
13
+ }): React.JSX.Element;
14
+ export { Reasoning, StreamingIndicator };
@@ -0,0 +1,61 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Collapsible } from "radix-ui";
3
+ import "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import ChevronRight from "@burtson-labs/icons/react/chevron-right";
6
+ import Lightbulb from "@burtson-labs/icons/react/lightbulb";
7
+ //#region src/components/reasoning.tsx
8
+ /** A model's reasoning, collapsed to one line ("Thought for 3s") unless opened. */
9
+ function Reasoning({ streaming = false, durationMs, defaultOpen = false, children, className, ...props }) {
10
+ const label = streaming ? "Thinking…" : durationMs !== void 0 ? `Thought for ${Math.max(1, Math.round(durationMs / 1e3))}s` : "Reasoning";
11
+ return /* @__PURE__ */ jsx(Collapsible.Root, {
12
+ defaultOpen,
13
+ children: /* @__PURE__ */ jsxs("div", {
14
+ "data-slot": "reasoning",
15
+ className: cn("grid gap-1.5", className),
16
+ ...props,
17
+ children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
18
+ className: "group/reasoning inline-flex w-fit items-center gap-1.5 rounded-sm text-xs text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20",
19
+ children: [
20
+ /* @__PURE__ */ jsx(Lightbulb, {
21
+ className: cn("size-3.5", streaming && "animate-pulse"),
22
+ "aria-hidden": true
23
+ }),
24
+ label,
25
+ /* @__PURE__ */ jsx(ChevronRight, {
26
+ "aria-hidden": true,
27
+ className: "size-3.5 transition-transform group-data-[state=open]/reasoning:rotate-90"
28
+ })
29
+ ]
30
+ }), /* @__PURE__ */ jsx(Collapsible.Content, {
31
+ className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
32
+ children: /* @__PURE__ */ jsx("div", {
33
+ className: "border-l-2 border-border-strong pl-3 text-[13px] leading-6 text-muted-foreground",
34
+ children
35
+ })
36
+ })]
37
+ })
38
+ });
39
+ }
40
+ /** Three pulsing dots while a reply is on its way. Still under reduced motion. */
41
+ function StreamingIndicator({ className, label = "Assistant is typing", ...props }) {
42
+ return /* @__PURE__ */ jsx("span", {
43
+ "data-slot": "streaming-indicator",
44
+ role: "status",
45
+ "aria-label": label,
46
+ className: cn("inline-flex h-5 items-center gap-1", className),
47
+ ...props,
48
+ children: [
49
+ 0,
50
+ 150,
51
+ 300
52
+ ].map((delay) => /* @__PURE__ */ jsx("span", {
53
+ className: "size-1.5 animate-bounce rounded-full bg-muted-foreground motion-reduce:animate-none",
54
+ style: { animationDelay: `${delay}ms` }
55
+ }, delay))
56
+ });
57
+ }
58
+ //#endregion
59
+ export { Reasoning, StreamingIndicator };
60
+
61
+ //# sourceMappingURL=reasoning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning.js","names":["CollapsiblePrimitive"],"sources":["../../src/components/reasoning.tsx"],"sourcesContent":["import ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport Lightbulb from '@burtson-labs/icons/react/lightbulb';\nimport { Collapsible as CollapsiblePrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface ReasoningProps extends React.ComponentProps<'div'> {\n /** True while the model is still thinking. */\n streaming?: boolean;\n durationMs?: number;\n defaultOpen?: boolean;\n}\n\n/** A model's reasoning, collapsed to one line (\"Thought for 3s\") unless opened. */\nfunction Reasoning({\n streaming = false,\n durationMs,\n defaultOpen = false,\n children,\n className,\n ...props\n}: ReasoningProps) {\n const label = streaming\n ? 'Thinking…'\n : durationMs !== undefined\n ? `Thought for ${Math.max(1, Math.round(durationMs / 1000))}s`\n : 'Reasoning';\n return (\n <CollapsiblePrimitive.Root defaultOpen={defaultOpen}>\n <div data-slot=\"reasoning\" className={cn('grid gap-1.5', className)} {...props}>\n <CollapsiblePrimitive.Trigger className=\"group/reasoning inline-flex w-fit items-center gap-1.5 rounded-sm text-xs text-muted-foreground outline-none hover:text-foreground focus-visible:ring-[3px] focus-visible:ring-ring/20\">\n <Lightbulb className={cn('size-3.5', streaming && 'animate-pulse')} aria-hidden />\n {label}\n <ChevronRight\n aria-hidden\n className=\"size-3.5 transition-transform group-data-[state=open]/reasoning:rotate-90\"\n />\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content className=\"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down\">\n <div className=\"border-l-2 border-border-strong pl-3 text-[13px] leading-6 text-muted-foreground\">\n {children}\n </div>\n </CollapsiblePrimitive.Content>\n </div>\n </CollapsiblePrimitive.Root>\n );\n}\n\n/** Three pulsing dots while a reply is on its way. Still under reduced motion. */\nfunction StreamingIndicator({\n className,\n label = 'Assistant is typing',\n ...props\n}: React.ComponentProps<'span'> & { label?: string }) {\n return (\n <span\n data-slot=\"streaming-indicator\"\n role=\"status\"\n aria-label={label}\n className={cn('inline-flex h-5 items-center gap-1', className)}\n {...props}\n >\n {[0, 150, 300].map((delay) => (\n <span\n key={delay}\n className=\"size-1.5 animate-bounce rounded-full bg-muted-foreground motion-reduce:animate-none\"\n style={{ animationDelay: `${delay}ms` }}\n />\n ))}\n </span>\n );\n}\n\nexport { Reasoning, StreamingIndicator };\n"],"mappings":";;;;;;;;AAeA,SAAS,UAAU,EACjB,YAAY,OACZ,YACA,cAAc,OACd,UACA,WACA,GAAG,SACc;CACjB,MAAM,QAAQ,YACV,cACA,eAAe,KAAA,IACb,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,GAAI,CAAC,EAAE,KAC1D;CACN,OACE,oBAACA,YAAqB,MAAtB;EAAwC;EACtC,UAAA,qBAAC,OAAD;GAAK,aAAU;GAAY,WAAW,GAAG,gBAAgB,SAAS;GAAG,GAAI;GAAzE,UAAA,CACE,qBAACA,YAAqB,SAAtB;IAA8B,WAAU;IAAxC,UAAA;KACE,oBAAC,WAAD;MAAW,WAAW,GAAG,YAAY,aAAa,eAAe;MAAG,eAAA;KAAa,CAAA;KAChF;KACD,oBAAC,cAAD;MACE,eAAA;MACA,WAAU;KACX,CAAA;IAC2B;GAC9B,CAAA,GAAA,oBAACA,YAAqB,SAAtB;IAA8B,WAAU;IACtC,UAAA,oBAAC,OAAD;KAAK,WAAU;KACZ;IACE,CAAA;GACuB,CAAA,CAC3B;;CACoB,CAAA;AAE/B;;AAGA,SAAS,mBAAmB,EAC1B,WACA,QAAQ,uBACR,GAAG,SACiD;CACpD,OACE,oBAAC,QAAD;EACE,aAAU;EACV,MAAK;EACL,cAAY;EACZ,WAAW,GAAG,sCAAsC,SAAS;EAC7D,GAAI;EAEH,UAAA;GAAC;GAAG;GAAK;EAAG,CAAC,CAAC,KAAK,UAClB,oBAAC,QAAD;GAEE,WAAU;GACV,OAAO,EAAE,gBAAgB,GAAG,MAAM,IAAI;EACvC,GAHM,KAGN,CACF;CACG,CAAA;AAEV"}
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ export interface SecretInputProps extends Omit<React.ComponentProps<'input'>, 'type'> {
3
+ /** What is hidden, for the toggle's name ("Show API key"). */
4
+ revealLabel?: string;
5
+ }
6
+ /**
7
+ * Password-style input with a show/hide toggle, in monospace so keys and
8
+ * tokens read cleanly. The toggle is hidden while the field is disabled.
9
+ */
10
+ declare function SecretInput({ className, revealLabel, disabled, ...props }: SecretInputProps): React.JSX.Element;
11
+ export { SecretInput };
@@ -0,0 +1,40 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Input } from "./input.js";
3
+ import { IconButton } from "./icon-button.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import Eye from "@burtson-labs/icons/react/eye";
7
+ import EyeOff from "@burtson-labs/icons/react/eye-off";
8
+ //#region src/components/secret-input.tsx
9
+ /**
10
+ * Password-style input with a show/hide toggle, in monospace so keys and
11
+ * tokens read cleanly. The toggle is hidden while the field is disabled.
12
+ */
13
+ function SecretInput({ className, revealLabel = "value", disabled, ...props }) {
14
+ const [revealed, setRevealed] = React.useState(false);
15
+ return /* @__PURE__ */ jsxs("div", {
16
+ "data-slot": "secret-input",
17
+ className: "relative",
18
+ children: [/* @__PURE__ */ jsx(Input, {
19
+ type: revealed && !disabled ? "text" : "password",
20
+ autoComplete: "off",
21
+ spellCheck: false,
22
+ disabled,
23
+ className: cn("pr-10 font-mono", className),
24
+ ...props
25
+ }), !disabled && /* @__PURE__ */ jsx(IconButton, {
26
+ type: "button",
27
+ variant: "ghost",
28
+ size: "icon-sm",
29
+ label: revealed ? `Hide ${revealLabel}` : `Show ${revealLabel}`,
30
+ "aria-pressed": revealed,
31
+ className: "absolute top-1/2 right-1 -translate-y-1/2",
32
+ onClick: () => setRevealed((r) => !r),
33
+ children: revealed ? /* @__PURE__ */ jsx(EyeOff, { "aria-hidden": true }) : /* @__PURE__ */ jsx(Eye, { "aria-hidden": true })
34
+ })]
35
+ });
36
+ }
37
+ //#endregion
38
+ export { SecretInput };
39
+
40
+ //# sourceMappingURL=secret-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-input.js","names":[],"sources":["../../src/components/secret-input.tsx"],"sourcesContent":["import Eye from '@burtson-labs/icons/react/eye';\nimport EyeOff from '@burtson-labs/icons/react/eye-off';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { IconButton } from './icon-button';\nimport { Input } from './input';\n\nexport interface SecretInputProps extends Omit<React.ComponentProps<'input'>, 'type'> {\n /** What is hidden, for the toggle's name (\"Show API key\"). */\n revealLabel?: string;\n}\n\n/**\n * Password-style input with a show/hide toggle, in monospace so keys and\n * tokens read cleanly. The toggle is hidden while the field is disabled.\n */\nfunction SecretInput({ className, revealLabel = 'value', disabled, ...props }: SecretInputProps) {\n const [revealed, setRevealed] = React.useState(false);\n return (\n <div data-slot=\"secret-input\" className=\"relative\">\n <Input\n type={revealed && !disabled ? 'text' : 'password'}\n autoComplete=\"off\"\n spellCheck={false}\n disabled={disabled}\n className={cn('pr-10 font-mono', className)}\n {...props}\n />\n {!disabled && (\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n label={revealed ? `Hide ${revealLabel}` : `Show ${revealLabel}`}\n aria-pressed={revealed}\n className=\"absolute top-1/2 right-1 -translate-y-1/2\"\n onClick={() => setRevealed((r) => !r)}\n >\n {revealed ? <EyeOff aria-hidden /> : <Eye aria-hidden />}\n </IconButton>\n )}\n </div>\n );\n}\n\nexport { SecretInput };\n"],"mappings":";;;;;;;;;;;;AAkBA,SAAS,YAAY,EAAE,WAAW,cAAc,SAAS,UAAU,GAAG,SAA2B;CAC/F,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS,KAAK;CACpD,OACE,qBAAC,OAAD;EAAK,aAAU;EAAe,WAAU;EAAxC,UAAA,CACE,oBAAC,OAAD;GACE,MAAM,YAAY,CAAC,WAAW,SAAS;GACvC,cAAa;GACb,YAAY;GACF;GACV,WAAW,GAAG,mBAAmB,SAAS;GAC1C,GAAI;EACL,CAAA,GACA,CAAC,YACA,oBAAC,YAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,OAAO,WAAW,QAAQ,gBAAgB,QAAQ;GAClD,gBAAc;GACd,WAAU;GACV,eAAe,aAAa,MAAM,CAAC,CAAC;GAEnC,UAAA,WAAW,oBAAC,QAAD,EAAQ,eAAA,KAAa,CAAA,IAAI,oBAAC,KAAD,EAAK,eAAA,KAAa,CAAA;EAC7C,CAAA,CAEX;;AAET"}
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ export interface SliderProps extends Omit<React.ComponentProps<'input'>, 'type' | 'value' | 'onChange'> {
3
+ value: number;
4
+ onValueChange: (value: number) => void;
5
+ min?: number;
6
+ max?: number;
7
+ step?: number;
8
+ }
9
+ /**
10
+ * A single-value range slider on the native input, so keyboard, touch and
11
+ * screen readers work without extra code. Pass `aria-valuetext` when the raw
12
+ * number isn't meaningful ("45% change").
13
+ */
14
+ declare function Slider({ className, value, onValueChange, min, max, step, style, ...props }: SliderProps): React.JSX.Element;
15
+ export { Slider };
@@ -0,0 +1,31 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/slider.tsx
5
+ /**
6
+ * A single-value range slider on the native input, so keyboard, touch and
7
+ * screen readers work without extra code. Pass `aria-valuetext` when the raw
8
+ * number isn't meaningful ("45% change").
9
+ */
10
+ function Slider({ className, value, onValueChange, min = 0, max = 100, step = 1, style, ...props }) {
11
+ const percent = max > min ? (value - min) / (max - min) * 100 : 0;
12
+ return /* @__PURE__ */ jsx("input", {
13
+ type: "range",
14
+ "data-slot": "slider",
15
+ min,
16
+ max,
17
+ step,
18
+ value,
19
+ onChange: (event) => onValueChange(Number(event.target.value)),
20
+ style: {
21
+ ...style,
22
+ ["--bl-slider-fill"]: `${percent}%`
23
+ },
24
+ className: cn("h-5 w-full min-w-0 cursor-pointer appearance-none bg-transparent outline-none disabled:cursor-not-allowed disabled:opacity-60", "[&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full", "[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-brand)_var(--bl-slider-fill),var(--color-muted)_var(--bl-slider-fill))]", "[&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-muted", "[&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-brand", "[&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-brand [&::-webkit-slider-thumb]:bg-background [&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-brand [&::-moz-range-thumb]:bg-background", "focus-visible:[&::-webkit-slider-thumb]:ring-[3px] focus-visible:[&::-webkit-slider-thumb]:ring-ring/30", "focus-visible:[&::-moz-range-thumb]:ring-[3px] focus-visible:[&::-moz-range-thumb]:ring-ring/30", className),
25
+ ...props
26
+ });
27
+ }
28
+ //#endregion
29
+ export { Slider };
30
+
31
+ //# sourceMappingURL=slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.js","names":[],"sources":["../../src/components/slider.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface SliderProps extends Omit<\n React.ComponentProps<'input'>,\n 'type' | 'value' | 'onChange'\n> {\n value: number;\n onValueChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * A single-value range slider on the native input, so keyboard, touch and\n * screen readers work without extra code. Pass `aria-valuetext` when the raw\n * number isn't meaningful (\"45% change\").\n */\nfunction Slider({\n className,\n value,\n onValueChange,\n min = 0,\n max = 100,\n step = 1,\n style,\n ...props\n}: SliderProps) {\n const percent = max > min ? ((value - min) / (max - min)) * 100 : 0;\n return (\n <input\n type=\"range\"\n data-slot=\"slider\"\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={(event) => onValueChange(Number(event.target.value))}\n style={{ ...style, ['--bl-slider-fill' as string]: `${percent}%` }}\n className={cn(\n 'h-5 w-full min-w-0 cursor-pointer appearance-none bg-transparent outline-none disabled:cursor-not-allowed disabled:opacity-60',\n // Track: brand up to the thumb, muted after it.\n '[&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full',\n '[&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-brand)_var(--bl-slider-fill),var(--color-muted)_var(--bl-slider-fill))]',\n '[&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-muted',\n '[&::-moz-range-progress]:h-1.5 [&::-moz-range-progress]:rounded-full [&::-moz-range-progress]:bg-brand',\n '[&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-brand [&::-webkit-slider-thumb]:bg-background [&::-webkit-slider-thumb]:shadow-sm',\n '[&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-brand [&::-moz-range-thumb]:bg-background',\n 'focus-visible:[&::-webkit-slider-thumb]:ring-[3px] focus-visible:[&::-webkit-slider-thumb]:ring-ring/30',\n 'focus-visible:[&::-moz-range-thumb]:ring-[3px] focus-visible:[&::-moz-range-thumb]:ring-ring/30',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Slider };\n"],"mappings":";;;;;;;;;AAoBA,SAAS,OAAO,EACd,WACA,OACA,eACA,MAAM,GACN,MAAM,KACN,OAAO,GACP,OACA,GAAG,SACW;CACd,MAAM,UAAU,MAAM,OAAQ,QAAQ,QAAQ,MAAM,OAAQ,MAAM;CAClE,OACE,oBAAC,SAAD;EACE,MAAK;EACL,aAAU;EACL;EACA;EACC;EACC;EACP,WAAW,UAAU,cAAc,OAAO,MAAM,OAAO,KAAK,CAAC;EAC7D,OAAO;GAAE,GAAG;IAAQ,qBAA+B,GAAG,QAAQ;EAAG;EACjE,WAAW,GACT,iIAEA,4FACA,uJACA,iGACA,0GACA,+SACA,yKACA,2GACA,mGACA,SACF;EACA,GAAI;CACL,CAAA;AAEL"}
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Imperative toasts: call `toast({ title, description, variant })` from
4
+ * anywhere (event handlers, data hooks) and one mounted `<Toaster />` renders
5
+ * them on the Toast primitives. Mount the Toaster once near the root.
6
+ */
7
+ export type ToastVariant = 'default' | 'success' | 'destructive';
8
+ export interface ToastOptions {
9
+ title: string;
10
+ description?: string;
11
+ variant?: ToastVariant;
12
+ /** Milliseconds before it closes (Radix pauses on hover and focus). */
13
+ duration?: number;
14
+ }
15
+ /** Show a brief notice. Returns a function that closes it early. */
16
+ declare function toast(options: ToastOptions | string): () => void;
17
+ declare function Toaster({ className }: {
18
+ className?: string;
19
+ }): React.JSX.Element;
20
+ export { toast, Toaster };
@@ -0,0 +1,61 @@
1
+ import { Toast, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from "./toast.js";
2
+ import * as React from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/toaster.tsx
5
+ var records = [];
6
+ var nextId = 1;
7
+ var listeners = /* @__PURE__ */ new Set();
8
+ var emit = () => listeners.forEach((listener) => listener());
9
+ function close(id) {
10
+ records = records.map((r) => r.id === id ? {
11
+ ...r,
12
+ open: false
13
+ } : r);
14
+ emit();
15
+ setTimeout(() => {
16
+ records = records.filter((r) => r.id !== id);
17
+ emit();
18
+ }, 400);
19
+ }
20
+ /** Show a brief notice. Returns a function that closes it early. */
21
+ function toast(options) {
22
+ const opts = typeof options === "string" ? { title: options } : options;
23
+ const id = nextId++;
24
+ records = [...records.slice(-3), {
25
+ ...opts,
26
+ id,
27
+ open: true
28
+ }];
29
+ emit();
30
+ return () => close(id);
31
+ }
32
+ var subscribe = (listener) => {
33
+ listeners.add(listener);
34
+ return () => {
35
+ listeners.delete(listener);
36
+ };
37
+ };
38
+ var snapshot = () => records;
39
+ function Toaster({ className }) {
40
+ const list = React.useSyncExternalStore(subscribe, snapshot, snapshot);
41
+ return /* @__PURE__ */ jsxs(ToastProvider, {
42
+ swipeDirection: "right",
43
+ children: [list.map((r) => /* @__PURE__ */ jsxs(Toast, {
44
+ open: r.open,
45
+ variant: r.variant,
46
+ duration: r.duration ?? (r.variant === "destructive" ? 8e3 : 4e3),
47
+ onOpenChange: (open) => {
48
+ if (!open) close(r.id);
49
+ },
50
+ children: [
51
+ /* @__PURE__ */ jsx(ToastTitle, { children: r.title }),
52
+ r.description && /* @__PURE__ */ jsx(ToastDescription, { children: r.description }),
53
+ /* @__PURE__ */ jsx(ToastClose, {})
54
+ ]
55
+ }, r.id)), /* @__PURE__ */ jsx(ToastViewport, { className })]
56
+ });
57
+ }
58
+ //#endregion
59
+ export { Toaster, toast };
60
+
61
+ //# sourceMappingURL=toaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toaster.js","names":[],"sources":["../../src/components/toaster.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n Toast,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from './toast';\n\n/**\n * Imperative toasts: call `toast({ title, description, variant })` from\n * anywhere (event handlers, data hooks) and one mounted `<Toaster />` renders\n * them on the Toast primitives. Mount the Toaster once near the root.\n */\nexport type ToastVariant = 'default' | 'success' | 'destructive';\n\nexport interface ToastOptions {\n title: string;\n description?: string;\n variant?: ToastVariant;\n /** Milliseconds before it closes (Radix pauses on hover and focus). */\n duration?: number;\n}\n\ninterface ToastRecord extends ToastOptions {\n id: number;\n open: boolean;\n}\n\nlet records: ToastRecord[] = [];\nlet nextId = 1;\nconst listeners = new Set<() => void>();\nconst emit = () => listeners.forEach((listener) => listener());\n\nfunction close(id: number) {\n records = records.map((r) => (r.id === id ? { ...r, open: false } : r));\n emit();\n // Leave time for the exit animation before dropping the record.\n setTimeout(() => {\n records = records.filter((r) => r.id !== id);\n emit();\n }, 400);\n}\n\n/** Show a brief notice. Returns a function that closes it early. */\nfunction toast(options: ToastOptions | string): () => void {\n const opts = typeof options === 'string' ? { title: options } : options;\n const id = nextId++;\n // Keep the stack short: the oldest go first.\n records = [...records.slice(-3), { ...opts, id, open: true }];\n emit();\n return () => close(id);\n}\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\nconst snapshot = () => records;\n\nfunction Toaster({ className }: { className?: string }) {\n const list = React.useSyncExternalStore(subscribe, snapshot, snapshot);\n return (\n <ToastProvider swipeDirection=\"right\">\n {list.map((r) => (\n <Toast\n key={r.id}\n open={r.open}\n variant={r.variant}\n duration={r.duration ?? (r.variant === 'destructive' ? 8000 : 4000)}\n onOpenChange={(open) => {\n if (!open) close(r.id);\n }}\n >\n <ToastTitle>{r.title}</ToastTitle>\n {r.description && <ToastDescription>{r.description}</ToastDescription>}\n <ToastClose />\n </Toast>\n ))}\n <ToastViewport className={className} />\n </ToastProvider>\n );\n}\n\nexport { toast, Toaster };\n"],"mappings":";;;;AA+BA,IAAI,UAAyB,CAAC;AAC9B,IAAI,SAAS;AACb,IAAM,4BAAY,IAAI,IAAgB;AACtC,IAAM,aAAa,UAAU,SAAS,aAAa,SAAS,CAAC;AAE7D,SAAS,MAAM,IAAY;CACzB,UAAU,QAAQ,KAAK,MAAO,EAAE,OAAO,KAAK;EAAE,GAAG;EAAG,MAAM;CAAM,IAAI,CAAE;CACtE,KAAK;CAEL,iBAAiB;EACf,UAAU,QAAQ,QAAQ,MAAM,EAAE,OAAO,EAAE;EAC3C,KAAK;CACP,GAAG,GAAG;AACR;;AAGA,SAAS,MAAM,SAA4C;CACzD,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,OAAO,QAAQ,IAAI;CAChE,MAAM,KAAK;CAEX,UAAU,CAAC,GAAG,QAAQ,MAAM,EAAE,GAAG;EAAE,GAAG;EAAM;EAAI,MAAM;CAAK,CAAC;CAC5D,KAAK;CACL,aAAa,MAAM,EAAE;AACvB;AAEA,IAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AACA,IAAM,iBAAiB;AAEvB,SAAS,QAAQ,EAAE,aAAqC;CACtD,MAAM,OAAO,MAAM,qBAAqB,WAAW,UAAU,QAAQ;CACrE,OACE,qBAAC,eAAD;EAAe,gBAAe;EAA9B,UAAA,CACG,KAAK,KAAK,MACT,qBAAC,OAAD;GAEE,MAAM,EAAE;GACR,SAAS,EAAE;GACX,UAAU,EAAE,aAAa,EAAE,YAAY,gBAAgB,MAAO;GAC9D,eAAe,SAAS;IACtB,IAAI,CAAC,MAAM,MAAM,EAAE,EAAE;GACvB;GAPF,UAAA;IASE,oBAAC,YAAD,EAAA,UAAa,EAAE,MAAkB,CAAA;IAChC,EAAE,eAAe,oBAAC,kBAAD,EAAA,UAAmB,EAAE,YAA8B,CAAA;IACrE,oBAAC,YAAD,CAAa,CAAA;GACR;EAXA,GAAA,EAAE,EAWF,CACR,GACD,oBAAC,eAAD,EAA0B,UAAY,CAAA,CACzB;;AAEnB"}
@@ -0,0 +1,32 @@
1
+ import * as React from 'react';
2
+ export type ToolCallStatus = 'pending' | 'running' | 'success' | 'error';
3
+ export interface ToolCallProps extends Omit<React.ComponentProps<'div'>, 'title'> {
4
+ /** The tool's name, e.g. `get_load`. */
5
+ name: string;
6
+ status: ToolCallStatus;
7
+ /** Arguments the agent passed; shown as formatted JSON. */
8
+ args?: unknown;
9
+ /** What the tool returned; shown as formatted JSON. */
10
+ result?: unknown;
11
+ /** Error message when the call failed. */
12
+ error?: string;
13
+ durationMs?: number;
14
+ defaultOpen?: boolean;
15
+ }
16
+ /** A tool call an agent made: name, live status, and collapsible arguments and result. */
17
+ declare function ToolCall({ name, status, args, result, error, durationMs, defaultOpen, className, ...props }: ToolCallProps): React.JSX.Element;
18
+ export interface ToolApprovalProps extends Omit<React.ComponentProps<'div'>, 'title'> {
19
+ name: string;
20
+ /** What will happen, in plain words, e.g. "Approve L-1042 and send it to Gravitate". */
21
+ description: React.ReactNode;
22
+ args?: unknown;
23
+ /** `pending` shows the buttons; the others record the decision. */
24
+ state?: 'pending' | 'approved' | 'denied';
25
+ onApprove?: () => void;
26
+ onDeny?: () => void;
27
+ approveLabel?: string;
28
+ denyLabel?: string;
29
+ }
30
+ /** A gate before an agent runs a tool with side effects: the person approves or denies it. */
31
+ declare function ToolApproval({ name, description, args, state, onApprove, onDeny, approveLabel, denyLabel, className, ...props }: ToolApprovalProps): React.JSX.Element;
32
+ export { ToolApproval, ToolCall };
@@ -0,0 +1,152 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { Button } from "./button.js";
3
+ import { StatusDot } from "./status.js";
4
+ import { Collapsible } from "radix-ui";
5
+ import "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import ChevronRight from "@burtson-labs/icons/react/chevron-right";
8
+ import Wrench from "@burtson-labs/icons/react/wrench";
9
+ //#region src/components/tool-call.tsx
10
+ var statusText = {
11
+ pending: "Queued",
12
+ running: "Running",
13
+ success: "Done",
14
+ error: "Failed"
15
+ };
16
+ var statusDot = {
17
+ pending: "neutral",
18
+ running: "brand",
19
+ success: "success",
20
+ error: "danger"
21
+ };
22
+ var json = (v) => typeof v === "string" ? v : JSON.stringify(v, null, 2);
23
+ /** A tool call an agent made: name, live status, and collapsible arguments and result. */
24
+ function ToolCall({ name, status, args, result, error, durationMs, defaultOpen = false, className, ...props }) {
25
+ const hasDetail = args !== void 0 || result !== void 0 || Boolean(error);
26
+ return /* @__PURE__ */ jsx(Collapsible.Root, {
27
+ defaultOpen,
28
+ disabled: !hasDetail,
29
+ children: /* @__PURE__ */ jsxs("div", {
30
+ "data-slot": "tool-call",
31
+ "data-status": status,
32
+ className: cn("animate-in overflow-hidden rounded-md border bg-surface text-[13px]", status === "error" && "border-destructive/30", className),
33
+ ...props,
34
+ children: [/* @__PURE__ */ jsxs(Collapsible.Trigger, {
35
+ className: "group/tool flex h-9 w-full items-center gap-2 px-3 text-left outline-none hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:cursor-default disabled:hover:bg-transparent",
36
+ children: [
37
+ /* @__PURE__ */ jsx(Wrench, {
38
+ className: "size-3.5 shrink-0 text-muted-foreground",
39
+ "aria-hidden": true
40
+ }),
41
+ /* @__PURE__ */ jsx("span", {
42
+ className: "min-w-0 flex-1 truncate font-mono text-[12.5px]",
43
+ children: name
44
+ }),
45
+ /* @__PURE__ */ jsxs("span", {
46
+ className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground",
47
+ children: [
48
+ /* @__PURE__ */ jsx(StatusDot, {
49
+ status: statusDot[status],
50
+ pulse: status === "running"
51
+ }),
52
+ statusText[status],
53
+ durationMs !== void 0 && status !== "running" && /* @__PURE__ */ jsxs("span", {
54
+ className: "tabular-nums",
55
+ children: [
56
+ "· ",
57
+ (durationMs / 1e3).toFixed(1),
58
+ "s"
59
+ ]
60
+ })
61
+ ]
62
+ }),
63
+ hasDetail && /* @__PURE__ */ jsx(ChevronRight, {
64
+ "aria-hidden": true,
65
+ className: "size-3.5 text-muted-foreground transition-transform group-data-[state=open]/tool:rotate-90"
66
+ })
67
+ ]
68
+ }), /* @__PURE__ */ jsx(Collapsible.Content, {
69
+ className: "overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
70
+ children: /* @__PURE__ */ jsxs("div", {
71
+ className: "grid gap-2 border-t p-3",
72
+ children: [args !== void 0 && /* @__PURE__ */ jsxs("section", {
73
+ className: "grid gap-1",
74
+ children: [/* @__PURE__ */ jsx("h4", {
75
+ className: "text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase",
76
+ children: "Arguments"
77
+ }), /* @__PURE__ */ jsx("pre", {
78
+ className: "overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5",
79
+ children: json(args)
80
+ })]
81
+ }), error ? /* @__PURE__ */ jsx("p", {
82
+ role: "alert",
83
+ className: "text-xs font-medium text-destructive",
84
+ children: error
85
+ }) : result !== void 0 && /* @__PURE__ */ jsxs("section", {
86
+ className: "grid gap-1",
87
+ children: [/* @__PURE__ */ jsx("h4", {
88
+ className: "text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase",
89
+ children: "Result"
90
+ }), /* @__PURE__ */ jsx("pre", {
91
+ className: "max-h-64 overflow-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5",
92
+ children: json(result)
93
+ })]
94
+ })]
95
+ })
96
+ })]
97
+ })
98
+ });
99
+ }
100
+ /** A gate before an agent runs a tool with side effects: the person approves or denies it. */
101
+ function ToolApproval({ name, description, args, state = "pending", onApprove, onDeny, approveLabel = "Approve", denyLabel = "Deny", className, ...props }) {
102
+ return /* @__PURE__ */ jsxs("div", {
103
+ "data-slot": "tool-approval",
104
+ "data-state": state,
105
+ className: cn("grid animate-in gap-3 rounded-md border p-3 text-[13px]", state === "pending" ? "border-warning/40 bg-warning/5" : "bg-surface", className),
106
+ ...props,
107
+ children: [
108
+ /* @__PURE__ */ jsxs("div", {
109
+ className: "flex items-center gap-2",
110
+ children: [
111
+ /* @__PURE__ */ jsx(Wrench, {
112
+ className: "size-3.5 text-muted-foreground",
113
+ "aria-hidden": true
114
+ }),
115
+ /* @__PURE__ */ jsx("span", {
116
+ className: "font-mono text-[12.5px]",
117
+ children: name
118
+ }),
119
+ /* @__PURE__ */ jsx("span", {
120
+ className: "ml-auto text-xs text-muted-foreground",
121
+ children: state === "pending" ? "Needs your approval" : state === "approved" ? "Approved" : "Denied"
122
+ })
123
+ ]
124
+ }),
125
+ /* @__PURE__ */ jsx("p", {
126
+ className: "text-sm",
127
+ children: description
128
+ }),
129
+ args !== void 0 && /* @__PURE__ */ jsx("pre", {
130
+ className: "overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5",
131
+ children: json(args)
132
+ }),
133
+ state === "pending" && /* @__PURE__ */ jsxs("div", {
134
+ className: "flex justify-end gap-2",
135
+ children: [/* @__PURE__ */ jsx(Button, {
136
+ size: "sm",
137
+ variant: "outline",
138
+ onClick: onDeny,
139
+ children: denyLabel
140
+ }), /* @__PURE__ */ jsx(Button, {
141
+ size: "sm",
142
+ onClick: onApprove,
143
+ children: approveLabel
144
+ })]
145
+ })
146
+ ]
147
+ });
148
+ }
149
+ //#endregion
150
+ export { ToolApproval, ToolCall };
151
+
152
+ //# sourceMappingURL=tool-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call.js","names":["CollapsiblePrimitive"],"sources":["../../src/components/tool-call.tsx"],"sourcesContent":["import ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport Wrench from '@burtson-labs/icons/react/wrench';\nimport { Collapsible as CollapsiblePrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { Button } from './button';\nimport { StatusDot } from './status';\n\nexport type ToolCallStatus = 'pending' | 'running' | 'success' | 'error';\n\nconst statusText: Record<ToolCallStatus, string> = {\n pending: 'Queued',\n running: 'Running',\n success: 'Done',\n error: 'Failed',\n};\nconst statusDot = {\n pending: 'neutral',\n running: 'brand',\n success: 'success',\n error: 'danger',\n} as const;\n\nconst json = (v: unknown) => (typeof v === 'string' ? v : JSON.stringify(v, null, 2));\n\nexport interface ToolCallProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n /** The tool's name, e.g. `get_load`. */\n name: string;\n status: ToolCallStatus;\n /** Arguments the agent passed; shown as formatted JSON. */\n args?: unknown;\n /** What the tool returned; shown as formatted JSON. */\n result?: unknown;\n /** Error message when the call failed. */\n error?: string;\n durationMs?: number;\n defaultOpen?: boolean;\n}\n\n/** A tool call an agent made: name, live status, and collapsible arguments and result. */\nfunction ToolCall({\n name,\n status,\n args,\n result,\n error,\n durationMs,\n defaultOpen = false,\n className,\n ...props\n}: ToolCallProps) {\n const hasDetail = args !== undefined || result !== undefined || Boolean(error);\n return (\n <CollapsiblePrimitive.Root defaultOpen={defaultOpen} disabled={!hasDetail}>\n <div\n data-slot=\"tool-call\"\n data-status={status}\n className={cn(\n 'animate-in overflow-hidden rounded-md border bg-surface text-[13px]',\n status === 'error' && 'border-destructive/30',\n className,\n )}\n {...props}\n >\n <CollapsiblePrimitive.Trigger className=\"group/tool flex h-9 w-full items-center gap-2 px-3 text-left outline-none hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/20 disabled:cursor-default disabled:hover:bg-transparent\">\n <Wrench className=\"size-3.5 shrink-0 text-muted-foreground\" aria-hidden />\n <span className=\"min-w-0 flex-1 truncate font-mono text-[12.5px]\">{name}</span>\n <span className=\"inline-flex items-center gap-1.5 text-xs text-muted-foreground\">\n <StatusDot status={statusDot[status]} pulse={status === 'running'} />\n {statusText[status]}\n {durationMs !== undefined && status !== 'running' && (\n <span className=\"tabular-nums\">· {(durationMs / 1000).toFixed(1)}s</span>\n )}\n </span>\n {hasDetail && (\n <ChevronRight\n aria-hidden\n className=\"size-3.5 text-muted-foreground transition-transform group-data-[state=open]/tool:rotate-90\"\n />\n )}\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content className=\"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down\">\n <div className=\"grid gap-2 border-t p-3\">\n {args !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Arguments\n </h4>\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n </section>\n )}\n {error ? (\n <p role=\"alert\" className=\"text-xs font-medium text-destructive\">\n {error}\n </p>\n ) : (\n result !== undefined && (\n <section className=\"grid gap-1\">\n <h4 className=\"text-[11px] font-semibold tracking-[0.06em] text-muted-foreground uppercase\">\n Result\n </h4>\n <pre className=\"max-h-64 overflow-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(result)}\n </pre>\n </section>\n )\n )}\n </div>\n </CollapsiblePrimitive.Content>\n </div>\n </CollapsiblePrimitive.Root>\n );\n}\n\nexport interface ToolApprovalProps extends Omit<React.ComponentProps<'div'>, 'title'> {\n name: string;\n /** What will happen, in plain words, e.g. \"Approve L-1042 and send it to Gravitate\". */\n description: React.ReactNode;\n args?: unknown;\n /** `pending` shows the buttons; the others record the decision. */\n state?: 'pending' | 'approved' | 'denied';\n onApprove?: () => void;\n onDeny?: () => void;\n approveLabel?: string;\n denyLabel?: string;\n}\n\n/** A gate before an agent runs a tool with side effects: the person approves or denies it. */\nfunction ToolApproval({\n name,\n description,\n args,\n state = 'pending',\n onApprove,\n onDeny,\n approveLabel = 'Approve',\n denyLabel = 'Deny',\n className,\n ...props\n}: ToolApprovalProps) {\n return (\n <div\n data-slot=\"tool-approval\"\n data-state={state}\n className={cn(\n 'grid animate-in gap-3 rounded-md border p-3 text-[13px]',\n state === 'pending' ? 'border-warning/40 bg-warning/5' : 'bg-surface',\n className,\n )}\n {...props}\n >\n <div className=\"flex items-center gap-2\">\n <Wrench className=\"size-3.5 text-muted-foreground\" aria-hidden />\n <span className=\"font-mono text-[12.5px]\">{name}</span>\n <span className=\"ml-auto text-xs text-muted-foreground\">\n {state === 'pending'\n ? 'Needs your approval'\n : state === 'approved'\n ? 'Approved'\n : 'Denied'}\n </span>\n </div>\n <p className=\"text-sm\">{description}</p>\n {args !== undefined && (\n <pre className=\"overflow-x-auto rounded-sm bg-muted/60 p-2 font-mono text-[12px] leading-5\">\n {json(args)}\n </pre>\n )}\n {state === 'pending' && (\n <div className=\"flex justify-end gap-2\">\n <Button size=\"sm\" variant=\"outline\" onClick={onDeny}>\n {denyLabel}\n </Button>\n <Button size=\"sm\" onClick={onApprove}>\n {approveLabel}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport { ToolApproval, ToolCall };\n"],"mappings":";;;;;;;;;AAYA,IAAM,aAA6C;CACjD,SAAS;CACT,SAAS;CACT,SAAS;CACT,OAAO;AACT;AACA,IAAM,YAAY;CAChB,SAAS;CACT,SAAS;CACT,SAAS;CACT,OAAO;AACT;AAEA,IAAM,QAAQ,MAAgB,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,GAAG,MAAM,CAAC;;AAiBnF,SAAS,SAAS,EAChB,MACA,QACA,MACA,QACA,OACA,YACA,cAAc,OACd,WACA,GAAG,SACa;CAChB,MAAM,YAAY,SAAS,KAAA,KAAa,WAAW,KAAA,KAAa,QAAQ,KAAK;CAC7E,OACE,oBAACA,YAAqB,MAAtB;EAAwC;EAAa,UAAU,CAAC;EAC9D,UAAA,qBAAC,OAAD;GACE,aAAU;GACV,eAAa;GACb,WAAW,GACT,uEACA,WAAW,WAAW,yBACtB,SACF;GACA,GAAI;GARN,UAAA,CAUE,qBAACA,YAAqB,SAAtB;IAA8B,WAAU;IAAxC,UAAA;KACE,oBAAC,QAAD;MAAQ,WAAU;MAA0C,eAAA;KAAa,CAAA;KACzE,oBAAC,QAAD;MAAM,WAAU;MAAmD,UAAA;KAAW,CAAA;KAC9E,qBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA;OACE,oBAAC,WAAD;QAAW,QAAQ,UAAU;QAAS,OAAO,WAAW;OAAY,CAAA;OACnE,WAAW;OACX,eAAe,KAAA,KAAa,WAAW,aACtC,qBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SAA+B;UAAI,aAAa,IAAA,CAAM,QAAQ,CAAC;SAAE;QAAO;;MAEtE;;KACL,aACC,oBAAC,cAAD;MACE,eAAA;MACA,WAAU;KACX,CAAA;IAEyB;GAC9B,CAAA,GAAA,oBAACA,YAAqB,SAAtB;IAA8B,WAAU;IACtC,UAAA,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACG,SAAS,KAAA,KACR,qBAAC,WAAD;MAAS,WAAU;MAAnB,UAAA,CACE,oBAAC,MAAD;OAAI,WAAU;OAA8E,UAAA;MAExF,CAAA,GACJ,oBAAC,OAAD;OAAK,WAAU;OACZ,UAAA,KAAK,IAAI;MACP,CAAA,CACE;KAEV,CAAA,GAAA,QACC,oBAAC,KAAD;MAAG,MAAK;MAAQ,WAAU;MACvB,UAAA;KACA,CAAA,IAEH,WAAW,KAAA,KACT,qBAAC,WAAD;MAAS,WAAU;MAAnB,UAAA,CACE,oBAAC,MAAD;OAAI,WAAU;OAA8E,UAAA;MAExF,CAAA,GACJ,oBAAC,OAAD;OAAK,WAAU;OACZ,UAAA,KAAK,MAAM;MACT,CAAA,CACE;KAGV,CAAA,CAAA;;GACuB,CAAA,CAC3B;;CACoB,CAAA;AAE/B;;AAgBA,SAAS,aAAa,EACpB,MACA,aACA,MACA,QAAQ,WACR,WACA,QACA,eAAe,WACf,YAAY,QACZ,WACA,GAAG,SACiB;CACpB,OACE,qBAAC,OAAD;EACE,aAAU;EACV,cAAY;EACZ,WAAW,GACT,2DACA,UAAU,YAAY,mCAAmC,cACzD,SACF;EACA,GAAI;EARN,UAAA;GAUE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,QAAD;MAAQ,WAAU;MAAiC,eAAA;KAAa,CAAA;KAChE,oBAAC,QAAD;MAAM,WAAU;MAA2B,UAAA;KAAW,CAAA;KACtD,oBAAC,QAAD;MAAM,WAAU;MACb,UAAA,UAAU,YACP,wBACA,UAAU,aACR,aACA;KACF,CAAA;IACH;;GACL,oBAAC,KAAD;IAAG,WAAU;IAAW,UAAA;GAAe,CAAA;GACtC,SAAS,KAAA,KACR,oBAAC,OAAD;IAAK,WAAU;IACZ,UAAA,KAAK,IAAI;GACP,CAAA;GAEN,UAAU,aACT,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAU,SAAS;KAC1C,UAAA;IACK,CAAA,GACR,oBAAC,QAAD;KAAQ,MAAK;KAAK,SAAS;KACxB,UAAA;IACK,CAAA,CACL;;EAEJ;;AAET"}
package/dist/index.d.ts CHANGED
@@ -13,6 +13,9 @@ export * from './components/checkbox';
13
13
  export * from './components/collapsible';
14
14
  export * from './components/combobox';
15
15
  export * from './components/command';
16
+ export * from './components/composer';
17
+ export * from './components/conversation';
18
+ export * from './components/copy-button';
16
19
  export * from './components/dialog';
17
20
  export * from './components/dropdown-menu';
18
21
  export * from './components/empty-state';
@@ -21,17 +24,22 @@ export * from './components/icon-button';
21
24
  export * from './components/input';
22
25
  export * from './components/kbd';
23
26
  export * from './components/label';
27
+ export * from './components/markdown';
28
+ export * from './components/message';
24
29
  export * from './components/navigation-menu';
25
30
  export * from './components/page-header';
26
31
  export * from './components/pagination';
27
32
  export * from './components/popover';
28
33
  export * from './components/progress';
29
34
  export * from './components/radio-group';
35
+ export * from './components/reasoning';
30
36
  export * from './components/scroll-area';
37
+ export * from './components/secret-input';
31
38
  export * from './components/select';
32
39
  export * from './components/separator';
33
40
  export * from './components/sheet';
34
41
  export * from './components/skeleton';
42
+ export * from './components/slider';
35
43
  export * from './components/spinner';
36
44
  export * from './components/stat-card';
37
45
  export * from './components/status';
@@ -41,5 +49,7 @@ export * from './components/table';
41
49
  export * from './components/tabs';
42
50
  export * from './components/textarea';
43
51
  export * from './components/toast';
52
+ export * from './components/toaster';
53
+ export * from './components/tool-call';
44
54
  export * from './components/toolbar';
45
55
  export * from './components/tooltip';
package/dist/index.js CHANGED
@@ -17,22 +17,32 @@ import { Input, fieldClasses } from "./components/input.js";
17
17
  import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, surfaceClasses } from "./components/popover.js";
18
18
  import { Spinner } from "./components/spinner.js";
19
19
  import { Combobox } from "./components/combobox.js";
20
+ import { Composer, Suggestions } from "./components/composer.js";
21
+ import { Conversation } from "./components/conversation.js";
22
+ import { IconButton } from "./components/icon-button.js";
23
+ import { Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, toastVariants } from "./components/toast.js";
24
+ import { Toaster, toast } from "./components/toaster.js";
25
+ import { CopyButton } from "./components/copy-button.js";
20
26
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./components/dropdown-menu.js";
21
27
  import { EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle } from "./components/empty-state.js";
22
28
  import { Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel } from "./components/field.js";
23
- import { IconButton } from "./components/icon-button.js";
24
29
  import { Kbd, KbdGroup } from "./components/kbd.js";
25
30
  import { Label } from "./components/label.js";
31
+ import { CodeBlock, Markdown, parseMarkdown } from "./components/markdown.js";
32
+ import { Message } from "./components/message.js";
26
33
  import { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, navigationMenuTriggerStyle } from "./components/navigation-menu.js";
27
34
  import { PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle } from "./components/page-header.js";
28
35
  import { Pagination, paginationRange } from "./components/pagination.js";
29
36
  import { Progress } from "./components/progress.js";
30
37
  import { RadioGroup, RadioGroupItem } from "./components/radio-group.js";
38
+ import { Reasoning, StreamingIndicator } from "./components/reasoning.js";
31
39
  import { ScrollArea, ScrollBar } from "./components/scroll-area.js";
40
+ import { SecretInput } from "./components/secret-input.js";
32
41
  import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from "./components/select.js";
33
42
  import { Separator } from "./components/separator.js";
34
43
  import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "./components/sheet.js";
35
44
  import { Skeleton } from "./components/skeleton.js";
45
+ import { Slider } from "./components/slider.js";
36
46
  import { StatCard } from "./components/stat-card.js";
37
47
  import { Status, StatusDot, statusDotVariants } from "./components/status.js";
38
48
  import { Steps } from "./components/steps.js";
@@ -40,7 +50,7 @@ import { Switch } from "./components/switch.js";
40
50
  import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./components/table.js";
41
51
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/tabs.js";
42
52
  import { Textarea } from "./components/textarea.js";
43
- import { Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, toastVariants } from "./components/toast.js";
53
+ import { ToolApproval, ToolCall } from "./components/tool-call.js";
44
54
  import { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer } from "./components/toolbar.js";
45
55
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/tooltip.js";
46
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Spinner, StatCard, Status, StatusDot, Steps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, dark, fieldClasses, fontMono, fontSans, light, motion, navigationMenuTriggerStyle, paginationRange, radius, shadow, statusDotVariants, surfaceClasses, toastVariants, tokens };
56
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, Conversation, CopyButton, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, Markdown, Message, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ScrollArea, ScrollBar, SecretInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, Spinner, StatCard, Status, StatusDot, Steps, StreamingIndicator, Suggestions, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, ToolApproval, ToolCall, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, dark, fieldClasses, fontMono, fontSans, light, motion, navigationMenuTriggerStyle, paginationRange, parseMarkdown, radius, shadow, statusDotVariants, surfaceClasses, toast, toastVariants, tokens };