@nexub/react 4.7.0 → 4.8.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.7.0",
2
+ "version": "4.8.0",
3
3
  "standard": "WCAG 2.2 Level AA",
4
4
  "method": {
5
5
  "automated": "axe-core rules tagged wcag2a, wcag2aa, wcag21a, wcag21aa and wcag22aa, run on every Storybook story in light and dark on every pull request; a new violation fails the build.",
@@ -69,6 +69,17 @@
69
69
  "keyboard": [],
70
70
  "screenReader": []
71
71
  },
72
+ {
73
+ "slug": "approval-card",
74
+ "name": "Approval Card",
75
+ "package": "@nexub/react",
76
+ "automated": "pass",
77
+ "exceptions": [],
78
+ "keyboard": [],
79
+ "screenReader": [
80
+ "The outcome is announced in a polite live region and replaces the buttons."
81
+ ]
82
+ },
72
83
  {
73
84
  "slug": "aurora",
74
85
  "name": "Aurora",
@@ -329,6 +340,17 @@
329
340
  "keyboard": [],
330
341
  "screenReader": []
331
342
  },
343
+ {
344
+ "slug": "diff-view",
345
+ "name": "Diff View",
346
+ "package": "@nexub/react",
347
+ "automated": "pass",
348
+ "exceptions": [],
349
+ "keyboard": [],
350
+ "screenReader": [
351
+ "Added and removed lines are spelled out for screen readers; colour is not the only cue."
352
+ ]
353
+ },
332
354
  {
333
355
  "slug": "donut-chart",
334
356
  "name": "Donut Chart",
@@ -719,6 +741,17 @@
719
741
  "keyboard": [],
720
742
  "screenReader": []
721
743
  },
744
+ {
745
+ "slug": "plan-tracker",
746
+ "name": "Plan Tracker",
747
+ "package": "@nexub/react",
748
+ "automated": "pass",
749
+ "exceptions": [],
750
+ "keyboard": [],
751
+ "screenReader": [
752
+ "Each step reads its status in text; the active step has `aria-current=\"step\"`."
753
+ ]
754
+ },
722
755
  {
723
756
  "slug": "popover",
724
757
  "name": "Popover",
@@ -1027,6 +1060,17 @@
1027
1060
  "keyboard": [],
1028
1061
  "screenReader": []
1029
1062
  },
1063
+ {
1064
+ "slug": "tool-call",
1065
+ "name": "Tool Call",
1066
+ "package": "@nexub/react",
1067
+ "automated": "pass",
1068
+ "exceptions": [],
1069
+ "keyboard": [],
1070
+ "screenReader": [
1071
+ "A native `<details>` disclosure: opens with Enter or Space."
1072
+ ]
1073
+ },
1030
1074
  {
1031
1075
  "slug": "tooltip",
1032
1076
  "name": "Tooltip",
@@ -0,0 +1,31 @@
1
+ import * as React from 'react';
2
+ export type PlanStepStatus = 'done' | 'active' | 'pending' | 'failed';
3
+ export interface PlanStep {
4
+ title: string;
5
+ status: PlanStepStatus;
6
+ detail?: React.ReactNode;
7
+ }
8
+ export interface PlanTrackerProps extends React.HTMLAttributes<HTMLOListElement> {
9
+ steps: PlanStep[];
10
+ }
11
+ /** An agent's plan: ordered steps with their status, announced in text. */
12
+ export declare function PlanTracker({ steps, className, ...props }: PlanTrackerProps): React.JSX.Element;
13
+ export interface ToolCallProps extends Omit<React.DetailsHTMLAttributes<HTMLDetailsElement>, 'title'> {
14
+ /** Tool name, e.g. "search_invoices". */
15
+ name: string;
16
+ status: 'running' | 'done' | 'failed';
17
+ /** Arguments, shown as JSON. */
18
+ input?: unknown;
19
+ /** Result, shown as given (string) or as JSON. */
20
+ output?: unknown;
21
+ }
22
+ /** One tool call: name and status, expandable to its input and output. */
23
+ export declare function ToolCall({ name, status, input, output, className, ...props }: ToolCallProps): React.JSX.Element;
24
+ export interface DiffViewProps extends React.HTMLAttributes<HTMLDivElement> {
25
+ /** A unified diff (lines starting with "+", "-" or " "); "@@" lines become headers. */
26
+ diff: string;
27
+ /** File name shown above the diff. */
28
+ file?: string;
29
+ }
30
+ /** A unified diff, with added and removed lines spelled out for screen readers. */
31
+ export declare function DiffView({ diff, file, className, ...props }: DiffViewProps): React.JSX.Element;
@@ -0,0 +1,78 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ const STATUS_TEXT = { done: "Done", active: "In progress", pending: "Not started", failed: "Failed" };
5
+ function StepIcon({ status }) {
6
+ const ring = "flex size-5 shrink-0 items-center justify-center rounded-full";
7
+ if (status === "done")
8
+ return /* @__PURE__ */ jsx("span", { className: cn(ring, "bg-[var(--color-primary)] text-[var(--color-on-primary)]"), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "size-3", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) });
9
+ if (status === "failed")
10
+ return /* @__PURE__ */ jsx("span", { className: cn(ring, "bg-[var(--color-error)] text-label-sm font-bold text-[var(--color-on-error)]"), children: "!" });
11
+ if (status === "active")
12
+ return /* @__PURE__ */ jsx("span", { className: cn(ring, "border-2 border-[var(--color-primary)]"), children: /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-[var(--color-primary)] motion-safe:animate-pulse" }) });
13
+ return /* @__PURE__ */ jsx("span", { className: cn(ring, "border-2 border-[var(--color-outline-variant)]") });
14
+ }
15
+ function PlanTracker({ steps, className, ...props }) {
16
+ return /* @__PURE__ */ jsx("ol", { className: cn("m-0 flex list-none flex-col gap-3 p-0", className), ...props, children: steps.map((s, i) => /* @__PURE__ */ jsxs("li", { "aria-current": s.status === "active" ? "step" : void 0, className: "flex gap-3", children: [
17
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(StepIcon, { status: s.status }) }),
18
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
19
+ /* @__PURE__ */ jsxs("span", { className: cn("text-body-md", s.status === "pending" ? "text-[var(--color-on-surface-variant)]" : "text-[var(--color-on-surface)]"), children: [
20
+ s.title,
21
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `, ${STATUS_TEXT[s.status]}` })
22
+ ] }),
23
+ s.detail && /* @__PURE__ */ jsx("span", { className: "text-body-sm text-[var(--color-on-surface-variant)]", children: s.detail })
24
+ ] })
25
+ ] }, i)) });
26
+ }
27
+ const json = (v) => typeof v === "string" ? v : JSON.stringify(v, null, 2);
28
+ function ToolCall({ name, status, input, output, className, ...props }) {
29
+ return /* @__PURE__ */ jsxs("details", { className: cn("group rounded-shape-container border border-[var(--color-outline-variant)] bg-[var(--color-surface-container-low)]", className), ...props, children: [
30
+ /* @__PURE__ */ jsxs("summary", { className: "nx-state-layer flex cursor-pointer list-none items-center gap-2 rounded-shape-container px-3 py-2 text-label-lg", children: [
31
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "transition-transform group-open:rotate-90", children: "\u203A" }),
32
+ /* @__PURE__ */ jsx("code", { className: "font-mono text-label-md", children: name }),
33
+ /* @__PURE__ */ jsx("span", { className: cn("ms-auto rounded-full px-2 text-label-sm", status === "failed" ? "bg-[var(--color-error-container)] text-[var(--color-on-error-container)]" : status === "done" ? "bg-[var(--color-success-container)] text-[var(--color-on-success-container)]" : "bg-[var(--color-surface-container-high)] text-[var(--color-on-surface-variant)]"), children: status === "running" ? "Running" : status === "done" ? "Done" : "Failed" })
34
+ ] }),
35
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-t border-[var(--color-outline-variant)] p-3", children: [
36
+ input !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
37
+ /* @__PURE__ */ jsx("p", { className: "m-0 mb-1 text-label-sm text-[var(--color-on-surface-variant)]", children: "Input" }),
38
+ /* @__PURE__ */ jsx("pre", { className: "m-0 overflow-auto rounded-shape-field bg-[var(--color-surface)] p-2 text-body-sm", children: /* @__PURE__ */ jsx("code", { children: json(input) }) })
39
+ ] }),
40
+ output !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
41
+ /* @__PURE__ */ jsx("p", { className: "m-0 mb-1 text-label-sm text-[var(--color-on-surface-variant)]", children: "Output" }),
42
+ /* @__PURE__ */ jsx("pre", { className: "m-0 overflow-auto rounded-shape-field bg-[var(--color-surface)] p-2 text-body-sm", children: /* @__PURE__ */ jsx("code", { children: json(output) }) })
43
+ ] })
44
+ ] })
45
+ ] });
46
+ }
47
+ function DiffView({ diff, file, className, ...props }) {
48
+ const lines = diff.replace(/\n$/, "").split("\n");
49
+ return /* @__PURE__ */ jsxs("div", { className: cn("overflow-hidden rounded-shape-container border border-[var(--color-outline-variant)]", className), ...props, children: [
50
+ file && /* @__PURE__ */ jsx("div", { className: "border-b border-[var(--color-outline-variant)] bg-[var(--color-surface-container-low)] px-3 py-1.5 font-mono text-label-md", children: file }),
51
+ /* @__PURE__ */ jsx("pre", { className: "m-0 overflow-auto bg-[var(--color-surface)] py-1 text-body-sm", children: lines.map((line, i) => {
52
+ const kind = line.startsWith("@@") ? "hunk" : line.startsWith("+") ? "add" : line.startsWith("-") ? "del" : "ctx";
53
+ return /* @__PURE__ */ jsxs(
54
+ "div",
55
+ {
56
+ className: cn(
57
+ "flex px-3 font-mono",
58
+ kind === "add" && "bg-[color-mix(in_oklab,var(--color-success)_14%,transparent)]",
59
+ kind === "del" && "bg-[color-mix(in_oklab,var(--color-error)_12%,transparent)]",
60
+ kind === "hunk" && "text-[var(--color-on-surface-variant)]"
61
+ ),
62
+ children: [
63
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "w-4 shrink-0 select-none", children: kind === "add" ? "+" : kind === "del" ? "\u2212" : "" }),
64
+ kind === "add" && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Added: " }),
65
+ kind === "del" && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Removed: " }),
66
+ /* @__PURE__ */ jsx("span", { className: "whitespace-pre", children: kind === "hunk" ? line : line.slice(1) })
67
+ ]
68
+ },
69
+ i
70
+ );
71
+ }) })
72
+ ] });
73
+ }
74
+ export {
75
+ DiffView,
76
+ PlanTracker,
77
+ ToolCall
78
+ };
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ export interface ApprovalCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
3
+ /** What the agent wants to do, e.g. "Send 3 invoices to Acme". */
4
+ title: string;
5
+ /** Details: who, how much, what changes. */
6
+ children?: React.ReactNode;
7
+ onApprove?: () => void;
8
+ onDeny?: () => void;
9
+ approveLabel?: string;
10
+ denyLabel?: string;
11
+ }
12
+ export declare function ApprovalCard({ title, children, onApprove, onDeny, approveLabel, denyLabel, className, ...props }: ApprovalCardProps): React.JSX.Element;
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.js";
5
+ import { Button } from "../Button/Button.js";
6
+ function ApprovalCard({ title, children, onApprove, onDeny, approveLabel = "Approve", denyLabel = "Deny", className, ...props }) {
7
+ const [choice, setChoice] = React.useState(null);
8
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3 rounded-shape-container border border-[var(--color-outline-variant)] bg-[var(--color-surface-elevated)] p-4", className), ...props, children: [
9
+ /* @__PURE__ */ jsx("p", { className: "m-0 text-title-sm text-[var(--color-on-surface)]", children: title }),
10
+ children && /* @__PURE__ */ jsx("div", { className: "text-body-sm text-[var(--color-on-surface-variant)]", children }),
11
+ /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "text-label-md text-[var(--color-on-surface-variant)]", children: choice === "approved" ? "Approved" : choice === "denied" ? "Denied" : "" }),
12
+ !choice && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
13
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => {
14
+ setChoice("approved");
15
+ onApprove?.();
16
+ }, children: approveLabel }),
17
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outlined", onClick: () => {
18
+ setChoice("denied");
19
+ onDeny?.();
20
+ }, children: denyLabel })
21
+ ] })
22
+ ] });
23
+ }
24
+ export {
25
+ ApprovalCard
26
+ };
@@ -0,0 +1,4 @@
1
+ export { PlanTracker, ToolCall, DiffView } from './AgentKit.js';
2
+ export type { PlanTrackerProps, PlanStep, PlanStepStatus, ToolCallProps, DiffViewProps } from './AgentKit.js';
3
+ export { ApprovalCard } from './ApprovalCard.js';
4
+ export type { ApprovalCardProps } from './ApprovalCard.js';
@@ -0,0 +1,8 @@
1
+ import { PlanTracker, ToolCall, DiffView } from "./AgentKit.js";
2
+ import { ApprovalCard } from "./ApprovalCard.js";
3
+ export {
4
+ ApprovalCard,
5
+ DiffView,
6
+ PlanTracker,
7
+ ToolCall
8
+ };
package/dist/index.d.ts CHANGED
@@ -37,6 +37,8 @@ export type { NumberInputProps } from './components/NumberInput/index.js';
37
37
  export { MoneyInput } from './components/MoneyInput/index.js';
38
38
  export type { MoneyInputProps } from './components/MoneyInput/index.js';
39
39
  export { Amount } from './components/Amount/index.js';
40
+ export { PlanTracker, ToolCall, DiffView, ApprovalCard } from './components/AgentKit/index.js';
41
+ export type { PlanTrackerProps, PlanStep, PlanStepStatus, ToolCallProps, DiffViewProps, ApprovalCardProps } from './components/AgentKit/index.js';
40
42
  export { SharedElement, transitionName } from './components/SharedElement/index.js';
41
43
  export type { SharedElementProps } from './components/SharedElement/index.js';
42
44
  export { ScrollProgress } from './components/ScrollProgress/index.js';
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ import { Textarea, textareaVariants } from "./components/Textarea/index.js";
22
22
  import { NumberInput } from "./components/NumberInput/index.js";
23
23
  import { MoneyInput } from "./components/MoneyInput/index.js";
24
24
  import { Amount } from "./components/Amount/index.js";
25
+ import { PlanTracker, ToolCall, DiffView, ApprovalCard } from "./components/AgentKit/index.js";
25
26
  import { SharedElement, transitionName } from "./components/SharedElement/index.js";
26
27
  import { ScrollProgress } from "./components/ScrollProgress/index.js";
27
28
  import { FloatingInput } from "./components/FloatingInput/index.js";
@@ -125,6 +126,7 @@ export {
125
126
  AlertDialog,
126
127
  Amount,
127
128
  AppShell,
129
+ ApprovalCard,
128
130
  AspectRatio,
129
131
  Aurora,
130
132
  Autocomplete,
@@ -159,6 +161,7 @@ export {
159
161
  DatePicker,
160
162
  DateRangePicker,
161
163
  Dialog,
164
+ DiffView,
162
165
  DonutChart,
163
166
  Drawer,
164
167
  DropdownMenu,
@@ -206,6 +209,7 @@ export {
206
209
  PageHeader,
207
210
  Pagination,
208
211
  PasswordInput,
212
+ PlanTracker,
209
213
  Popover,
210
214
  Progress,
211
215
  PromptInput,
@@ -249,6 +253,7 @@ export {
249
253
  Toaster,
250
254
  Toggle,
251
255
  ToggleGroup,
256
+ ToolCall,
252
257
  Toolbar,
253
258
  Tooltip,
254
259
  Provider as TooltipProvider,