@useatlas/react 0.0.1 → 0.0.3

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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -2
  3. package/dist/{chunk-5SEVKHS5.cjs → chunk-35SCTKSW.js} +100 -7
  4. package/dist/chunk-35SCTKSW.js.map +1 -0
  5. package/dist/{chunk-UIRB6L36.cjs → chunk-DZFSZSQB.cjs} +46 -54
  6. package/dist/chunk-DZFSZSQB.cjs.map +1 -0
  7. package/dist/{chunk-2WFDP7G5.js → chunk-FMSGREKS.js} +46 -54
  8. package/dist/chunk-FMSGREKS.js.map +1 -0
  9. package/dist/{chunk-44HBZYKP.js → chunk-IDXGFWFS.cjs} +109 -3
  10. package/dist/chunk-IDXGFWFS.cjs.map +1 -0
  11. package/dist/global.d.ts +36 -0
  12. package/dist/hooks.cjs +10 -10
  13. package/dist/hooks.cjs.map +1 -1
  14. package/dist/hooks.d.cts +2 -2
  15. package/dist/hooks.d.ts +2 -2
  16. package/dist/hooks.js +3 -3
  17. package/dist/hooks.js.map +1 -1
  18. package/dist/index.cjs +385 -265
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +224 -4
  21. package/dist/index.d.ts +224 -4
  22. package/dist/index.js +328 -208
  23. package/dist/index.js.map +1 -1
  24. package/dist/lib/widget-types.d.ts +232 -0
  25. package/dist/{result-chart-YLCKBNV4.cjs → result-chart-ANZOT6FL.cjs} +24 -34
  26. package/dist/result-chart-ANZOT6FL.cjs.map +1 -0
  27. package/dist/{result-chart-NFAJ4IQ5.js → result-chart-C3EJTN5G.js} +22 -32
  28. package/dist/result-chart-C3EJTN5G.js.map +1 -0
  29. package/dist/widget.css +2 -2
  30. package/dist/widget.js +215 -246
  31. package/package.json +27 -17
  32. package/src/components/__tests__/data-table.test.tsx +125 -0
  33. package/src/components/actions/action-approval-card.tsx +26 -19
  34. package/src/components/actions/action-status-badge.tsx +3 -3
  35. package/src/components/atlas-chat.tsx +97 -37
  36. package/src/components/chart/result-chart.tsx +13 -37
  37. package/src/components/chat/api-key-bar.tsx +4 -4
  38. package/src/components/chat/data-table.tsx +42 -3
  39. package/src/components/chat/error-banner.tsx +108 -5
  40. package/src/components/chat/follow-up-chips.tsx +1 -1
  41. package/src/components/chat/managed-auth-card.tsx +6 -6
  42. package/src/components/conversations/conversation-item.tsx +19 -14
  43. package/src/components/conversations/conversation-list.tsx +3 -3
  44. package/src/components/conversations/conversation-sidebar.tsx +15 -4
  45. package/src/components/conversations/delete-confirmation.tsx +2 -2
  46. package/src/components/error-boundary.tsx +66 -0
  47. package/src/components/schema-explorer/schema-explorer.tsx +4 -0
  48. package/src/env.d.ts +9 -7
  49. package/src/global.d.ts +36 -0
  50. package/src/hooks/__tests__/use-atlas-conversations.test.tsx +4 -6
  51. package/src/hooks/use-atlas-chat.ts +1 -1
  52. package/src/hooks/use-atlas-conversations.ts +2 -2
  53. package/src/hooks/use-conversations.ts +60 -68
  54. package/src/index.ts +8 -0
  55. package/src/lib/action-types.ts +2 -2
  56. package/src/lib/helpers.ts +16 -16
  57. package/src/lib/types.ts +3 -2
  58. package/src/lib/widget-types.ts +232 -0
  59. package/src/test-setup.ts +2 -2
  60. package/dist/chunk-2WFDP7G5.js.map +0 -1
  61. package/dist/chunk-44HBZYKP.js.map +0 -1
  62. package/dist/chunk-5SEVKHS5.cjs.map +0 -1
  63. package/dist/chunk-UIRB6L36.cjs.map +0 -1
  64. package/dist/result-chart-NFAJ4IQ5.js.map +0 -1
  65. package/dist/result-chart-YLCKBNV4.cjs.map +0 -1
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "@useatlas/react",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Embeddable Atlas chat UI for React applications",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/AtlasDevHQ/atlas",
9
+ "directory": "packages/react"
10
+ },
6
11
  "type": "module",
7
12
  "main": "./src/index.ts",
8
13
  "module": "./src/index.ts",
@@ -10,6 +15,7 @@
10
15
  "exports": {
11
16
  ".": "./src/index.ts",
12
17
  "./hooks": "./src/hooks/index.ts",
18
+ "./widget": "./src/global.d.ts",
13
19
  "./styles.css": "./src/styles.css"
14
20
  },
15
21
  "publishConfig": {
@@ -37,6 +43,9 @@
37
43
  "default": "./dist/hooks.cjs"
38
44
  }
39
45
  },
46
+ "./widget": {
47
+ "types": "./dist/global.d.ts"
48
+ },
40
49
  "./styles.css": "./dist/styles.css"
41
50
  }
42
51
  },
@@ -48,8 +57,9 @@
48
57
  "*.css"
49
58
  ],
50
59
  "scripts": {
51
- "build": "tsup && cp src/styles.css dist/styles.css && bun x @tailwindcss/cli -i src/widget.css -o dist/widget.css --minify",
60
+ "build": "tsup && cp src/styles.css dist/styles.css && cp src/global.d.ts dist/global.d.ts && mkdir -p dist/lib && cp src/lib/widget-types.ts dist/lib/widget-types.d.ts && bun x @tailwindcss/cli -i src/widget.css -o dist/widget.css --minify",
52
61
  "dev": "tsup --watch",
62
+ "test": "bun scripts/test-isolated.ts",
53
63
  "type": "tsc --noEmit"
54
64
  },
55
65
  "peerDependencies": {
@@ -61,7 +71,7 @@
61
71
  "react-syntax-highlighter": ">=15.0.0",
62
72
  "recharts": ">=2.0.0",
63
73
  "tailwindcss": ">=4.0.0",
64
- "xlsx": ">=0.18.0"
74
+ "exceljs": ">=4.0.0"
65
75
  },
66
76
  "peerDependenciesMeta": {
67
77
  "lucide-react": {
@@ -76,13 +86,13 @@
76
86
  "tailwindcss": {
77
87
  "optional": true
78
88
  },
79
- "xlsx": {
89
+ "exceljs": {
80
90
  "optional": true
81
91
  }
82
92
  },
83
93
  "dependencies": {
84
- "@useatlas/types": "workspace:*",
85
- "@radix-ui/react-slot": "^1.2.3",
94
+ "@useatlas/types": "^0.0.2",
95
+ "@radix-ui/react-slot": "^1.2.4",
86
96
  "class-variance-authority": "^0.7.1",
87
97
  "clsx": "^2.1.1",
88
98
  "radix-ui": "^1.4.3",
@@ -91,23 +101,23 @@
91
101
  "tailwind-merge": "^3.5.0"
92
102
  },
93
103
  "devDependencies": {
94
- "@ai-sdk/react": "^3.0.99",
95
- "@tailwindcss/cli": "^4.2.1",
104
+ "@ai-sdk/react": "^3.0.143",
105
+ "@tailwindcss/cli": "^4.2.2",
96
106
  "@testing-library/dom": "^10.4.1",
97
107
  "@testing-library/react": "^16.3.2",
98
108
  "@types/react": "^19.2.14",
99
109
  "@types/react-dom": "^19.2.3",
100
110
  "@types/react-syntax-highlighter": "^15.5.13",
101
- "ai": "^6.0.97",
102
- "happy-dom": "16.6.0",
103
- "lucide-react": "^0.577.0",
111
+ "ai": "^6.0.141",
112
+ "exceljs": "^4.4.0",
113
+ "happy-dom": "20.8.9",
114
+ "lucide-react": "^1.7.0",
104
115
  "react": "^19.2.4",
105
116
  "react-dom": "^19.2.4",
106
- "react-syntax-highlighter": "^16.1.0",
107
- "recharts": "^3.7.0",
108
- "tailwindcss": "^4.2.1",
109
- "tsup": "^8.5.0",
110
- "typescript": "^5.9.3",
111
- "xlsx": "^0.18.5"
117
+ "react-syntax-highlighter": "^16.1.1",
118
+ "recharts": "^3.8.1",
119
+ "tailwindcss": "^4.2.2",
120
+ "tsup": "^8.5.1",
121
+ "typescript": "^6.0.2"
112
122
  }
113
123
  }
@@ -0,0 +1,125 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { render, fireEvent } from "@testing-library/react";
3
+ import { DataTable } from "../chat/data-table";
4
+
5
+ describe("DataTable", () => {
6
+ const columns = ["name", "revenue", "city"];
7
+ const rows = [
8
+ { name: "Acme", revenue: 500000, city: "NYC" },
9
+ { name: "Beta", revenue: 300000, city: "LA" },
10
+ { name: "Gamma", revenue: 200000, city: "SF" },
11
+ ];
12
+
13
+ test("renders column headers", () => {
14
+ const { container } = render(<DataTable columns={columns} rows={rows} />);
15
+ const ths = container.querySelectorAll("th");
16
+ const headers = Array.from(ths).map((th) => th.textContent?.trim());
17
+ expect(headers).toEqual(["name", "revenue", "city"]);
18
+ });
19
+
20
+ test("renders correct number of data rows", () => {
21
+ const { container } = render(<DataTable columns={columns} rows={rows} />);
22
+ const trs = container.querySelectorAll("tbody tr");
23
+ expect(trs.length).toBe(3);
24
+ });
25
+
26
+ test("renders cell values", () => {
27
+ const { container } = render(<DataTable columns={columns} rows={rows} />);
28
+ expect(container.textContent).toContain("Acme");
29
+ expect(container.textContent).toContain("NYC");
30
+ });
31
+
32
+ test("formats numeric values with locale separators", () => {
33
+ const { container } = render(
34
+ <DataTable columns={["val"]} rows={[{ val: 1234567 }]} />,
35
+ );
36
+ const text = container.textContent!;
37
+ // formatCell uses toLocaleString() — verify formatted output contains separators
38
+ // (exact format varies by locale, but should match X,XXX,XXX or X.XXX.XXX pattern)
39
+ expect(text).toMatch(/1[,.\s]234[,.\s]567/);
40
+ });
41
+
42
+ test("renders em-dash for null values", () => {
43
+ const { container } = render(
44
+ <DataTable columns={["val"]} rows={[{ val: null }]} />,
45
+ );
46
+ expect(container.textContent).toContain("\u2014");
47
+ });
48
+
49
+ test("truncates to maxRows and shows overflow message", () => {
50
+ const manyRows = Array.from({ length: 25 }, (_, i) => ({ name: `Item ${i}` }));
51
+ const { container } = render(
52
+ <DataTable columns={["name"]} rows={manyRows} maxRows={10} />,
53
+ );
54
+ const trs = container.querySelectorAll("tbody tr");
55
+ expect(trs.length).toBe(10);
56
+ expect(container.textContent).toContain("Showing 10 of 25 rows");
57
+ });
58
+
59
+ test("no overflow message when rows fit", () => {
60
+ const { container } = render(<DataTable columns={columns} rows={rows} maxRows={10} />);
61
+ expect(container.textContent).not.toContain("Showing");
62
+ });
63
+
64
+ test("sort ascending on column click", () => {
65
+ const { container } = render(<DataTable columns={columns} rows={rows} />);
66
+ const ths = container.querySelectorAll("th");
67
+ const nameHeader = ths[0];
68
+
69
+ // Click to sort ascending by name
70
+ fireEvent.click(nameHeader);
71
+
72
+ const firstCell = container.querySelector("tbody tr td");
73
+ expect(firstCell!.textContent).toBe("Acme");
74
+ });
75
+
76
+ test("sort descending on second click", () => {
77
+ const { container } = render(<DataTable columns={columns} rows={rows} />);
78
+ const ths = container.querySelectorAll("th");
79
+ const nameHeader = ths[0];
80
+
81
+ fireEvent.click(nameHeader); // asc
82
+ fireEvent.click(nameHeader); // desc
83
+
84
+ const cells = container.querySelectorAll("tbody tr td:first-child");
85
+ expect(cells[0].textContent).toBe("Gamma");
86
+ });
87
+
88
+ test("third click resets sort to original order", () => {
89
+ // Use data where original order differs from both asc and desc
90
+ const unsortedRows = [
91
+ { name: "Beta", revenue: 300000, city: "LA" },
92
+ { name: "Acme", revenue: 500000, city: "NYC" },
93
+ { name: "Gamma", revenue: 200000, city: "SF" },
94
+ ];
95
+ const { container } = render(<DataTable columns={columns} rows={unsortedRows} />);
96
+ const ths = container.querySelectorAll("th");
97
+ const nameHeader = ths[0];
98
+
99
+ fireEvent.click(nameHeader); // asc: Acme, Beta, Gamma
100
+ fireEvent.click(nameHeader); // desc: Gamma, Beta, Acme
101
+ fireEvent.click(nameHeader); // reset: Beta, Acme, Gamma (original)
102
+
103
+ const firstCell = container.querySelector("tbody tr td");
104
+ expect(firstCell!.textContent).toBe("Beta");
105
+ });
106
+
107
+ test("renders with array rows (unknown[][])", () => {
108
+ const arrayRows = [
109
+ ["Alice", 100],
110
+ ["Bob", 200],
111
+ ];
112
+ const { container } = render(
113
+ <DataTable columns={["name", "score"]} rows={arrayRows} />,
114
+ );
115
+ expect(container.textContent).toContain("Alice");
116
+ expect(container.textContent).toContain("Bob");
117
+ });
118
+
119
+ test("renders empty state message when rows are empty", () => {
120
+ const { container } = render(<DataTable columns={["id"]} rows={[]} />);
121
+ expect(container.querySelector("table")).toBeNull();
122
+ expect(container.textContent).toContain("Query returned no results");
123
+ expect(container.textContent).toContain("Try adjusting your query filters or criteria");
124
+ });
125
+ });
@@ -5,8 +5,8 @@ import { getToolArgs, getToolResult, isToolComplete } from "../../lib/helpers";
5
5
  import {
6
6
  isActionToolResult,
7
7
  RESOLVED_STATUSES,
8
- type ActionStatus,
9
- type ResolvedStatus,
8
+ type ActionDisplayStatus,
9
+ type ResolvedDisplayStatus,
10
10
  type ActionApprovalResponse,
11
11
  type ActionToolResultShape,
12
12
  } from "../../lib/action-types";
@@ -35,14 +35,14 @@ function safeStringify(value: unknown): string {
35
35
  type CardState =
36
36
  | { phase: "idle" }
37
37
  | { phase: "submitting"; action: "approve" | "deny" }
38
- | { phase: "resolved"; status: ResolvedStatus; result?: unknown }
38
+ | { phase: "resolved"; status: ResolvedDisplayStatus; result?: unknown }
39
39
  | { phase: "error"; message: string };
40
40
 
41
41
  /* ------------------------------------------------------------------ */
42
42
  /* Border color by status */
43
43
  /* ------------------------------------------------------------------ */
44
44
 
45
- function borderColor(status: ActionStatus): string {
45
+ function borderColor(status: ActionDisplayStatus): string {
46
46
  switch (status) {
47
47
  case "pending_approval":
48
48
  return "border-yellow-300 dark:border-yellow-900/50";
@@ -53,7 +53,8 @@ function borderColor(status: ActionStatus): string {
53
53
  case "denied":
54
54
  case "failed":
55
55
  return "border-red-300 dark:border-red-900/50";
56
- default:
56
+ case "rolled_back":
57
+ case "timed_out":
57
58
  return "border-zinc-200 dark:border-zinc-700";
58
59
  }
59
60
  }
@@ -87,12 +88,16 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
87
88
  const toolResult: ActionToolResultShape = rawResult;
88
89
 
89
90
  // Effective status: local optimistic update wins over server result
90
- const effectiveStatus: ActionStatus =
91
+ const effectiveStatus: ActionDisplayStatus =
91
92
  cardState.phase === "resolved" ? cardState.status : toolResult.status;
92
93
 
93
94
  const isPending = effectiveStatus === "pending_approval" && cardState.phase !== "submitting";
94
95
  const isSubmitting = cardState.phase === "submitting";
95
- const resolvedResult = cardState.phase === "resolved" ? cardState.result : toolResult.result;
96
+ const resolvedResult = cardState.phase === "resolved"
97
+ ? cardState.result
98
+ : toolResult.status === "approved" || toolResult.status === "executed" || toolResult.status === "auto_approved"
99
+ ? toolResult.result
100
+ : undefined;
96
101
 
97
102
  /* ---------------------------------------------------------------- */
98
103
  /* API helpers */
@@ -127,8 +132,10 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
127
132
  } catch {
128
133
  throw new Error("Action was already resolved, but the response could not be read. Refresh the page.");
129
134
  }
130
- const status = typeof data.status === "string" ? data.status as ResolvedStatus : "failed" as ResolvedStatus;
131
- const label = status.replace(/_/g, " ");
135
+ if (typeof data.status !== "string" || !RESOLVED_STATUSES.has(data.status as ActionDisplayStatus)) {
136
+ throw new Error("Action was already resolved with an unrecognized status. Refresh the page.");
137
+ }
138
+ const label = data.status.replace(/_/g, " ");
132
139
  throw new Error(`This action was already ${label} by another user or policy.`);
133
140
  }
134
141
 
@@ -143,10 +150,10 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
143
150
  } catch {
144
151
  throw new Error("Action succeeded, but the response could not be read. Refresh the page.");
145
152
  }
146
- if (typeof data.status !== "string") {
147
- throw new Error("Action succeeded, but the server returned an invalid status. Refresh the page.");
153
+ if (typeof data.status !== "string" || !RESOLVED_STATUSES.has(data.status as ActionDisplayStatus)) {
154
+ throw new Error("Action succeeded, but the server returned an unrecognized status. Refresh the page.");
148
155
  }
149
- setCardState({ phase: "resolved", status: data.status as ResolvedStatus, result: data.result });
156
+ setCardState({ phase: "resolved", status: data.status as ResolvedDisplayStatus, result: data.result });
150
157
  }
151
158
 
152
159
  async function handleApprove() {
@@ -215,13 +222,13 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
215
222
  : safeStringify(resolvedResult)}
216
223
  </div>
217
224
  )}
218
- {toolResult.error && (
225
+ {toolResult.status === "failed" && (
219
226
  <div className="mb-2 rounded bg-red-50 p-2 text-xs text-red-700 dark:bg-red-900/20 dark:text-red-400">
220
227
  <span className="font-medium">Error: </span>
221
228
  {toolResult.error}
222
229
  </div>
223
230
  )}
224
- {toolResult.reason && RESOLVED_STATUSES.has(effectiveStatus) && (
231
+ {toolResult.status === "denied" && RESOLVED_STATUSES.has(effectiveStatus) && (
225
232
  <div className="mb-2 text-xs text-zinc-500 dark:text-zinc-400">
226
233
  <span className="font-medium">Reason: </span>
227
234
  {toolResult.reason}
@@ -241,7 +248,7 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
241
248
  <button
242
249
  onClick={handleApprove}
243
250
  disabled={isSubmitting}
244
- className="inline-flex items-center gap-1.5 rounded bg-blue-600 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-blue-500 disabled:opacity-40"
251
+ className="inline-flex items-center gap-1.5 rounded bg-blue-600 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-blue-500 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-blue-500/50 disabled:opacity-40"
245
252
  >
246
253
  {isSubmitting && cardState.action === "approve" && (
247
254
  <span className="inline-block h-3 w-3 animate-spin rounded-full border-2 border-white/30 border-t-white" />
@@ -253,7 +260,7 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
253
260
  <button
254
261
  onClick={() => setShowDenyInput(true)}
255
262
  disabled={isSubmitting}
256
- className="rounded border border-zinc-300 px-3 py-1.5 text-xs font-medium text-zinc-600 transition-colors hover:border-zinc-400 hover:text-zinc-800 disabled:opacity-40 dark:border-zinc-600 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200"
263
+ className="rounded border border-zinc-300 px-3 py-1.5 text-xs font-medium text-zinc-600 transition-colors hover:border-zinc-400 hover:text-zinc-800 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:opacity-40 dark:border-zinc-600 dark:text-zinc-400 dark:hover:border-zinc-500 dark:hover:text-zinc-200"
257
264
  >
258
265
  Deny
259
266
  </button>
@@ -263,13 +270,13 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
263
270
  value={denyReason}
264
271
  onChange={(e) => setDenyReason(e.target.value)}
265
272
  placeholder="Reason (optional)"
266
- className="flex-1 rounded border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-900 placeholder-zinc-400 outline-none focus:border-red-400 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-100 dark:placeholder-zinc-600"
273
+ className="flex-1 rounded border border-zinc-200 bg-white px-2 py-1 text-xs text-zinc-900 placeholder-zinc-400 outline-none focus-visible:border-red-400 focus-visible:ring-[3px] focus-visible:ring-red-400/30 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-100 dark:placeholder-zinc-600"
267
274
  disabled={isSubmitting}
268
275
  />
269
276
  <button
270
277
  onClick={handleDeny}
271
278
  disabled={isSubmitting}
272
- className="inline-flex items-center gap-1.5 rounded bg-red-600 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-red-500 disabled:opacity-40"
279
+ className="inline-flex items-center gap-1.5 rounded bg-red-600 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-red-500 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-red-500/50 disabled:opacity-40"
273
280
  >
274
281
  {isSubmitting && cardState.action === "deny" && (
275
282
  <span className="inline-block h-3 w-3 animate-spin rounded-full border-2 border-white/30 border-t-white" />
@@ -282,7 +289,7 @@ export function ActionApprovalCard({ part }: { part: unknown }) {
282
289
  setDenyReason("");
283
290
  }}
284
291
  disabled={isSubmitting}
285
- className="text-xs text-zinc-400 hover:text-zinc-600 disabled:opacity-40 dark:hover:text-zinc-300"
292
+ className="rounded text-xs text-zinc-400 hover:text-zinc-600 focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:opacity-40 dark:hover:text-zinc-300"
286
293
  >
287
294
  Cancel
288
295
  </button>
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
- import type { ActionStatus } from "../../lib/action-types";
3
+ import type { ActionDisplayStatus } from "../../lib/action-types";
4
4
 
5
- const STATUS_CONFIG: Record<ActionStatus, { label: string; classes: string }> = {
5
+ const STATUS_CONFIG: Record<ActionDisplayStatus, { label: string; classes: string }> = {
6
6
  pending_approval: {
7
7
  label: "Pending Approval",
8
8
  classes: "bg-yellow-100 text-yellow-700 dark:bg-yellow-600/20 dark:text-yellow-400",
@@ -37,7 +37,7 @@ const STATUS_CONFIG: Record<ActionStatus, { label: string; classes: string }> =
37
37
  },
38
38
  };
39
39
 
40
- export function ActionStatusBadge({ status }: { status: ActionStatus }) {
40
+ export function ActionStatusBadge({ status }: { status: ActionDisplayStatus }) {
41
41
  const config = STATUS_CONFIG[status] ?? {
42
42
  label: status.replace(/_/g, " "),
43
43
  classes: "bg-zinc-100 text-zinc-700 dark:bg-zinc-600/20 dark:text-zinc-400",