@flanksource/clicky-ui 0.3.47 → 0.3.49

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 (255) hide show
  1. package/README.md +49 -0
  2. package/dist/comments/CommentSidePanel.cjs +10 -4
  3. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  4. package/dist/comments/CommentSidePanel.d.ts +2 -0
  5. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  6. package/dist/comments/CommentSidePanel.js +10 -4
  7. package/dist/comments/CommentSidePanel.js.map +1 -1
  8. package/dist/comments/CommentThread.cjs +2 -0
  9. package/dist/comments/CommentThread.cjs.map +1 -1
  10. package/dist/comments/CommentThread.d.ts +2 -1
  11. package/dist/comments/CommentThread.d.ts.map +1 -1
  12. package/dist/comments/CommentThread.js +2 -0
  13. package/dist/comments/CommentThread.js.map +1 -1
  14. package/dist/comments/CommentThreadList.cjs +3 -0
  15. package/dist/comments/CommentThreadList.cjs.map +1 -1
  16. package/dist/comments/CommentThreadList.d.ts +3 -1
  17. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  18. package/dist/comments/CommentThreadList.js +3 -0
  19. package/dist/comments/CommentThreadList.js.map +1 -1
  20. package/dist/data/CodeLine.cjs +4 -2
  21. package/dist/data/CodeLine.cjs.map +1 -1
  22. package/dist/data/CodeLine.d.ts.map +1 -1
  23. package/dist/data/CodeLine.js +4 -2
  24. package/dist/data/CodeLine.js.map +1 -1
  25. package/dist/data/DataTable.cjs +18 -8
  26. package/dist/data/DataTable.cjs.map +1 -1
  27. package/dist/data/DataTable.d.ts +4 -0
  28. package/dist/data/DataTable.d.ts.map +1 -1
  29. package/dist/data/DataTable.js +18 -8
  30. package/dist/data/DataTable.js.map +1 -1
  31. package/dist/data/SymbolBadge.cjs +61 -0
  32. package/dist/data/SymbolBadge.cjs.map +1 -0
  33. package/dist/data/SymbolBadge.d.ts +21 -0
  34. package/dist/data/SymbolBadge.d.ts.map +1 -0
  35. package/dist/data/SymbolBadge.js +61 -0
  36. package/dist/data/SymbolBadge.js.map +1 -0
  37. package/dist/data/TaskManager.cjs +183 -159
  38. package/dist/data/TaskManager.cjs.map +1 -1
  39. package/dist/data/TaskManager.d.ts +3 -1
  40. package/dist/data/TaskManager.d.ts.map +1 -1
  41. package/dist/data/TaskManager.js +185 -161
  42. package/dist/data/TaskManager.js.map +1 -1
  43. package/dist/data/TaskManagerButton.cjs +1 -0
  44. package/dist/data/TaskManagerButton.cjs.map +1 -1
  45. package/dist/data/TaskManagerButton.js +1 -0
  46. package/dist/data/TaskManagerButton.js.map +1 -1
  47. package/dist/data/TaskProgress.cjs +13 -7
  48. package/dist/data/TaskProgress.cjs.map +1 -1
  49. package/dist/data/TaskProgress.d.ts +3 -1
  50. package/dist/data/TaskProgress.d.ts.map +1 -1
  51. package/dist/data/TaskProgress.js +13 -7
  52. package/dist/data/TaskProgress.js.map +1 -1
  53. package/dist/data/test-runner/TestDetailPanel.cjs +26 -12
  54. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  55. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  56. package/dist/data/test-runner/TestDetailPanel.js +27 -13
  57. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  58. package/dist/data/test-runner/TestRunner.cjs +6 -0
  59. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  60. package/dist/data/test-runner/TestRunner.d.ts +3 -1
  61. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  62. package/dist/data/test-runner/TestRunner.js +6 -0
  63. package/dist/data/test-runner/TestRunner.js.map +1 -1
  64. package/dist/data/test-runner/TestTreeNode.cjs +2 -1
  65. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  66. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  67. package/dist/data/test-runner/TestTreeNode.js +2 -1
  68. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  69. package/dist/data/test-runner/adapter.cjs +4 -0
  70. package/dist/data/test-runner/adapter.cjs.map +1 -1
  71. package/dist/data/test-runner/adapter.d.ts +9 -0
  72. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  73. package/dist/data/test-runner/adapter.js +4 -0
  74. package/dist/data/test-runner/adapter.js.map +1 -1
  75. package/dist/data/test-runner/context.cjs.map +1 -1
  76. package/dist/data/test-runner/context.d.ts +2 -0
  77. package/dist/data/test-runner/context.d.ts.map +1 -1
  78. package/dist/data/test-runner/context.js.map +1 -1
  79. package/dist/data/test-runner/index.d.ts +2 -2
  80. package/dist/data/test-runner/index.d.ts.map +1 -1
  81. package/dist/data/test-runner/marks.cjs +42 -1
  82. package/dist/data/test-runner/marks.cjs.map +1 -1
  83. package/dist/data/test-runner/marks.d.ts +10 -0
  84. package/dist/data/test-runner/marks.d.ts.map +1 -1
  85. package/dist/data/test-runner/marks.js +42 -1
  86. package/dist/data/test-runner/marks.js.map +1 -1
  87. package/dist/data/traces/ProcessTraceTree.cjs +93 -0
  88. package/dist/data/traces/ProcessTraceTree.cjs.map +1 -0
  89. package/dist/data/traces/ProcessTraceTree.d.ts +24 -0
  90. package/dist/data/traces/ProcessTraceTree.d.ts.map +1 -0
  91. package/dist/data/traces/ProcessTraceTree.js +93 -0
  92. package/dist/data/traces/ProcessTraceTree.js.map +1 -0
  93. package/dist/data/traces/Sparkline.cjs +23 -0
  94. package/dist/data/traces/Sparkline.cjs.map +1 -0
  95. package/dist/data/traces/Sparkline.d.ts +13 -0
  96. package/dist/data/traces/Sparkline.d.ts.map +1 -0
  97. package/dist/data/traces/Sparkline.js +23 -0
  98. package/dist/data/traces/Sparkline.js.map +1 -0
  99. package/dist/data/traces/SqlTraceTable.cjs +104 -0
  100. package/dist/data/traces/SqlTraceTable.cjs.map +1 -0
  101. package/dist/data/traces/SqlTraceTable.d.ts +19 -0
  102. package/dist/data/traces/SqlTraceTable.d.ts.map +1 -0
  103. package/dist/data/traces/SqlTraceTable.js +104 -0
  104. package/dist/data/traces/SqlTraceTable.js.map +1 -0
  105. package/dist/data/traces/TerminalCastPlayer.cjs +162 -0
  106. package/dist/data/traces/TerminalCastPlayer.cjs.map +1 -0
  107. package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
  108. package/dist/data/traces/TerminalCastPlayer.d.ts.map +1 -0
  109. package/dist/data/traces/TerminalCastPlayer.js +162 -0
  110. package/dist/data/traces/TerminalCastPlayer.js.map +1 -0
  111. package/dist/data/traces/TraceHarView.cjs +15 -0
  112. package/dist/data/traces/TraceHarView.cjs.map +1 -0
  113. package/dist/data/traces/TraceHarView.d.ts +13 -0
  114. package/dist/data/traces/TraceHarView.d.ts.map +1 -0
  115. package/dist/data/traces/TraceHarView.js +15 -0
  116. package/dist/data/traces/TraceHarView.js.map +1 -0
  117. package/dist/data/traces/TraceView.cjs +54 -0
  118. package/dist/data/traces/TraceView.cjs.map +1 -0
  119. package/dist/data/traces/TraceView.d.ts +18 -0
  120. package/dist/data/traces/TraceView.d.ts.map +1 -0
  121. package/dist/data/traces/TraceView.js +54 -0
  122. package/dist/data/traces/TraceView.js.map +1 -0
  123. package/dist/data/traces/cast.cjs +81 -0
  124. package/dist/data/traces/cast.cjs.map +1 -0
  125. package/dist/data/traces/cast.d.ts +9 -0
  126. package/dist/data/traces/cast.d.ts.map +1 -0
  127. package/dist/data/traces/cast.js +81 -0
  128. package/dist/data/traces/cast.js.map +1 -0
  129. package/dist/data/traces/fixtures.d.ts +8 -0
  130. package/dist/data/traces/fixtures.d.ts.map +1 -0
  131. package/dist/data/traces/har-adapter.cjs +83 -0
  132. package/dist/data/traces/har-adapter.cjs.map +1 -0
  133. package/dist/data/traces/har-adapter.d.ts +13 -0
  134. package/dist/data/traces/har-adapter.d.ts.map +1 -0
  135. package/dist/data/traces/har-adapter.js +83 -0
  136. package/dist/data/traces/har-adapter.js.map +1 -0
  137. package/dist/data/traces/index.d.ts +12 -0
  138. package/dist/data/traces/index.d.ts.map +1 -0
  139. package/dist/data/traces/process-tree.cjs +53 -0
  140. package/dist/data/traces/process-tree.cjs.map +1 -0
  141. package/dist/data/traces/process-tree.d.ts +21 -0
  142. package/dist/data/traces/process-tree.d.ts.map +1 -0
  143. package/dist/data/traces/process-tree.js +53 -0
  144. package/dist/data/traces/process-tree.js.map +1 -0
  145. package/dist/data/traces/sql-trace.cjs +39 -0
  146. package/dist/data/traces/sql-trace.cjs.map +1 -0
  147. package/dist/data/traces/sql-trace.d.ts +31 -0
  148. package/dist/data/traces/sql-trace.d.ts.map +1 -0
  149. package/dist/data/traces/sql-trace.js +39 -0
  150. package/dist/data/traces/sql-trace.js.map +1 -0
  151. package/dist/data/traces/terminal-screen.cjs +270 -0
  152. package/dist/data/traces/terminal-screen.cjs.map +1 -0
  153. package/dist/data/traces/terminal-screen.d.ts +45 -0
  154. package/dist/data/traces/terminal-screen.d.ts.map +1 -0
  155. package/dist/data/traces/terminal-screen.js +270 -0
  156. package/dist/data/traces/terminal-screen.js.map +1 -0
  157. package/dist/data/traces/terminal-timeline.cjs +48 -0
  158. package/dist/data/traces/terminal-timeline.cjs.map +1 -0
  159. package/dist/data/traces/terminal-timeline.d.ts +26 -0
  160. package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
  161. package/dist/data/traces/terminal-timeline.js +48 -0
  162. package/dist/data/traces/terminal-timeline.js.map +1 -0
  163. package/dist/data/traces/types.d.ts +139 -0
  164. package/dist/data/traces/types.d.ts.map +1 -0
  165. package/dist/data/verification/VerificationResults.cjs +4 -0
  166. package/dist/data/verification/VerificationResults.cjs.map +1 -1
  167. package/dist/data/verification/VerificationResults.d.ts +3 -1
  168. package/dist/data/verification/VerificationResults.d.ts.map +1 -1
  169. package/dist/data/verification/VerificationResults.js +4 -0
  170. package/dist/data/verification/VerificationResults.js.map +1 -1
  171. package/dist/data/verification/adapterViews.cjs +12 -3
  172. package/dist/data/verification/adapterViews.cjs.map +1 -1
  173. package/dist/data/verification/adapterViews.d.ts +4 -1
  174. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  175. package/dist/data/verification/adapterViews.js +12 -3
  176. package/dist/data/verification/adapterViews.js.map +1 -1
  177. package/dist/data/verification/adapters.cjs +53 -10
  178. package/dist/data/verification/adapters.cjs.map +1 -1
  179. package/dist/data/verification/adapters.d.ts +7 -1
  180. package/dist/data/verification/adapters.d.ts.map +1 -1
  181. package/dist/data/verification/adapters.js +53 -10
  182. package/dist/data/verification/adapters.js.map +1 -1
  183. package/dist/data/verification/index.d.ts +4 -2
  184. package/dist/data/verification/index.d.ts.map +1 -1
  185. package/dist/data/verification/stepKind.cjs +217 -0
  186. package/dist/data/verification/stepKind.cjs.map +1 -0
  187. package/dist/data/verification/stepKind.d.ts +87 -0
  188. package/dist/data/verification/stepKind.d.ts.map +1 -0
  189. package/dist/data/verification/stepKind.js +217 -0
  190. package/dist/data/verification/stepKind.js.map +1 -0
  191. package/dist/data/verification/stepKindViews.cjs +111 -0
  192. package/dist/data/verification/stepKindViews.cjs.map +1 -0
  193. package/dist/data/verification/stepKindViews.d.ts +18 -0
  194. package/dist/data/verification/stepKindViews.d.ts.map +1 -0
  195. package/dist/data/verification/stepKindViews.js +111 -0
  196. package/dist/data/verification/stepKindViews.js.map +1 -0
  197. package/dist/data/verification/verifyReportTests.cjs +1 -0
  198. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  199. package/dist/data/verification/verifyReportTests.d.ts +2 -1
  200. package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
  201. package/dist/data/verification/verifyReportTests.js +1 -0
  202. package/dist/data/verification/verifyReportTests.js.map +1 -1
  203. package/dist/data/version-info.cjs +3 -3
  204. package/dist/data/version-info.cjs.map +1 -1
  205. package/dist/data/version-info.js +3 -3
  206. package/dist/data/version-info.js.map +1 -1
  207. package/dist/data.cjs +36 -0
  208. package/dist/data.cjs.map +1 -1
  209. package/dist/data.d.ts +2 -0
  210. package/dist/data.d.ts.map +1 -1
  211. package/dist/data.js +38 -2
  212. package/dist/data.js.map +1 -1
  213. package/dist/index.cjs +38 -0
  214. package/dist/index.cjs.map +1 -1
  215. package/dist/index.js +40 -2
  216. package/dist/index.js.map +1 -1
  217. package/dist/rpc/FilterForm.cjs +9 -0
  218. package/dist/rpc/FilterForm.cjs.map +1 -1
  219. package/dist/rpc/FilterForm.d.ts +5 -1
  220. package/dist/rpc/FilterForm.d.ts.map +1 -1
  221. package/dist/rpc/FilterForm.js +9 -0
  222. package/dist/rpc/FilterForm.js.map +1 -1
  223. package/dist/rpc/OperationArgsForm.cjs +153 -0
  224. package/dist/rpc/OperationArgsForm.cjs.map +1 -0
  225. package/dist/rpc/OperationArgsForm.d.ts +16 -0
  226. package/dist/rpc/OperationArgsForm.d.ts.map +1 -0
  227. package/dist/rpc/OperationArgsForm.js +153 -0
  228. package/dist/rpc/OperationArgsForm.js.map +1 -0
  229. package/dist/rpc/OperationScheduleDialog.cjs +61 -17
  230. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  231. package/dist/rpc/OperationScheduleDialog.d.ts +3 -0
  232. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  233. package/dist/rpc/OperationScheduleDialog.js +62 -18
  234. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  235. package/dist/rpc/OperationSchedules.cjs +6 -1
  236. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  237. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  238. package/dist/rpc/OperationSchedules.js +6 -1
  239. package/dist/rpc/OperationSchedules.js.map +1 -1
  240. package/dist/rpc/operation-schedule-model.cjs +0 -7
  241. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  242. package/dist/rpc/operation-schedule-model.d.ts +0 -2
  243. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  244. package/dist/rpc/operation-schedule-model.js +0 -7
  245. package/dist/rpc/operation-schedule-model.js.map +1 -1
  246. package/dist/rpc/operation-schedule-types.d.ts +6 -1
  247. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  248. package/dist/rpc.cjs +2 -0
  249. package/dist/rpc.cjs.map +1 -1
  250. package/dist/rpc.d.ts +1 -0
  251. package/dist/rpc.d.ts.map +1 -1
  252. package/dist/rpc.js +2 -0
  253. package/dist/rpc.js.map +1 -1
  254. package/dist/styles.css +1 -1
  255. package/package.json +1 -1
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const utils = require("../lib/utils.cjs");
6
+ const badgeVariants = require("./badge-variants.cjs");
7
+ const CodeLine = require("./CodeLine.cjs");
8
+ const Icon = require("./Icon.cjs");
9
+ const COLORS = /* @__PURE__ */ new Map([
10
+ ["neutral", "text-foreground"],
11
+ ["primary", "text-primary"],
12
+ ["blue", "text-blue-700 [[data-theme=dark]_&]:text-blue-300"],
13
+ ["cyan", "text-cyan-700 [[data-theme=dark]_&]:text-cyan-300"],
14
+ ["indigo", "text-indigo-700 [[data-theme=dark]_&]:text-indigo-300"],
15
+ ["sky", "text-sky-700 [[data-theme=dark]_&]:text-sky-300"],
16
+ ["slate", "text-slate-700 [[data-theme=dark]_&]:text-slate-300"],
17
+ ["violet", "text-violet-700 [[data-theme=dark]_&]:text-violet-300"]
18
+ ]);
19
+ function SymbolBadge({
20
+ style = "badge",
21
+ color = "indigo",
22
+ icon,
23
+ iconClassName,
24
+ language,
25
+ children,
26
+ className,
27
+ title,
28
+ ...props
29
+ }) {
30
+ if (typeof children === "string" ? !children.trim() || /[\r\n]/.test(children) : !react.isValidElement(children)) {
31
+ throw new Error("SymbolBadge requires a nonempty, single-line symbol; use CodeBlock for multiline source.");
32
+ }
33
+ const colorClass = COLORS.get(color);
34
+ return /* @__PURE__ */ jsxRuntime.jsxs(
35
+ "span",
36
+ {
37
+ ...props,
38
+ "data-symbol-style": style,
39
+ title: title ?? (typeof children === "string" ? children : void 0),
40
+ className: utils.cn(
41
+ badgeVariants.badgeVariants({ variant: "outline", size: "md" }),
42
+ "max-w-full items-baseline gap-1.5 rounded-md align-baseline text-[12px] leading-4",
43
+ style === "badge" && "border-transparent",
44
+ style === "badge-outline" && "border-current",
45
+ style === "inline" && "rounded-none border-0 p-0",
46
+ colorClass,
47
+ className
48
+ ),
49
+ style: {
50
+ ...colorClass === void 0 ? { color } : {},
51
+ ...style === "badge" ? { backgroundColor: `color-mix(in srgb, ${colorClass === void 0 ? color : "currentColor"} 16%, transparent)` } : {}
52
+ },
53
+ children: [
54
+ icon !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "data-symbol-icon": true, "aria-hidden": true, className: "relative w-[1.25em] shrink-0 before:invisible before:content-['.']", children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon, width: "1.25em", className: utils.cn("absolute top-1/2 -translate-y-1/2", iconClassName) }) }),
55
+ typeof children === "string" ? /* @__PURE__ */ jsxRuntime.jsx(CodeLine.CodeLine, { code: children, ...language !== void 0 ? { language } : {}, className: "min-w-0 truncate" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 whitespace-normal", children })
56
+ ]
57
+ }
58
+ );
59
+ }
60
+ exports.SymbolBadge = SymbolBadge;
61
+ //# sourceMappingURL=SymbolBadge.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SymbolBadge.cjs","sources":["../../src/data/SymbolBadge.tsx"],"sourcesContent":["import { isValidElement, type HTMLAttributes, type ReactElement } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { badgeVariants } from \"./badge-variants\";\nimport { CodeLine } from \"./CodeLine\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\n\nconst COLORS = new Map([\n [\"neutral\", \"text-foreground\"],\n [\"primary\", \"text-primary\"],\n [\"blue\", \"text-blue-700 [[data-theme=dark]_&]:text-blue-300\"],\n [\"cyan\", \"text-cyan-700 [[data-theme=dark]_&]:text-cyan-300\"],\n [\"indigo\", \"text-indigo-700 [[data-theme=dark]_&]:text-indigo-300\"],\n [\"sky\", \"text-sky-700 [[data-theme=dark]_&]:text-sky-300\"],\n [\"slate\", \"text-slate-700 [[data-theme=dark]_&]:text-slate-300\"],\n [\"violet\", \"text-violet-700 [[data-theme=dark]_&]:text-violet-300\"],\n]);\n\nexport type SymbolBadgeStyle = \"badge\" | \"badge-outline\" | \"inline\";\n\nexport type SymbolBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, \"style\" | \"color\" | \"children\"> & {\n /** Filled badge, colored outline, or an unframed inline symbol. */\n style?: SymbolBadgeStyle;\n /** Named palette hue or CSS color, including CSS custom properties. */\n color?: string;\n /** Imported icon component placed before the symbol. */\n icon?: StaticIconComponent;\n /** Additional glyph classes, including adjustments for fixed-color SVGs. */\n iconClassName?: string;\n} & (\n | { /** Literal, nonempty, single-line symbol or expression. */ children: string; language?: string }\n | { /** Content already formatted by the caller, such as MathML. */ children: ReactElement; language?: never }\n);\n\nexport function SymbolBadge({\n style = \"badge\",\n color = \"indigo\",\n icon,\n iconClassName,\n language,\n children,\n className,\n title,\n ...props\n}: SymbolBadgeProps) {\n if (typeof children === \"string\" ? !children.trim() || /[\\r\\n]/.test(children) : !isValidElement(children)) {\n throw new Error(\"SymbolBadge requires a nonempty, single-line symbol; use CodeBlock for multiline source.\");\n }\n const colorClass = COLORS.get(color);\n return (\n <span\n {...props}\n data-symbol-style={style}\n title={title ?? (typeof children === \"string\" ? children : undefined)}\n className={cn(\n badgeVariants({ variant: \"outline\", size: \"md\" }),\n \"max-w-full items-baseline gap-1.5 rounded-md align-baseline text-[12px] leading-4\",\n style === \"badge\" && \"border-transparent\",\n style === \"badge-outline\" && \"border-current\",\n style === \"inline\" && \"rounded-none border-0 p-0\",\n colorClass,\n className,\n )}\n style={{\n ...(colorClass === undefined ? { color } : {}),\n ...(style === \"badge\" ? { backgroundColor: `color-mix(in srgb, ${colorClass === undefined ? color : \"currentColor\"} 16%, transparent)` } : {}),\n }}\n >\n {icon !== undefined && <span data-symbol-icon aria-hidden className=\"relative w-[1.25em] shrink-0 before:invisible before:content-['.']\">\n <Icon icon={icon} width=\"1.25em\" className={cn(\"absolute top-1/2 -translate-y-1/2\", iconClassName)} />\n </span>}\n {typeof children === \"string\"\n ? <CodeLine code={children} {...(language !== undefined ? { language } : {})} className=\"min-w-0 truncate\" />\n : <span className=\"min-w-0 whitespace-normal\">{children}</span>}\n </span>\n );\n}\n"],"names":["isValidElement","jsxs","cn","badgeVariants","jsx","Icon","CodeLine"],"mappings":";;;;;;;;AAMA,MAAM,6BAAa,IAAI;AAAA,EACrB,CAAC,WAAW,iBAAiB;AAAA,EAC7B,CAAC,WAAW,cAAc;AAAA,EAC1B,CAAC,QAAQ,mDAAmD;AAAA,EAC5D,CAAC,QAAQ,mDAAmD;AAAA,EAC5D,CAAC,UAAU,uDAAuD;AAAA,EAClE,CAAC,OAAO,iDAAiD;AAAA,EACzD,CAAC,SAAS,qDAAqD;AAAA,EAC/D,CAAC,UAAU,uDAAuD;AACpE,CAAC;AAkBM,SAAS,YAAY;AAAA,EAC1B,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,MAAI,OAAO,aAAa,WAAW,CAAC,SAAS,KAAA,KAAU,SAAS,KAAK,QAAQ,IAAI,CAACA,MAAAA,eAAe,QAAQ,GAAG;AAC1G,UAAM,IAAI,MAAM,0FAA0F;AAAA,EAC5G;AACA,QAAM,aAAa,OAAO,IAAI,KAAK;AACnC,SACEC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,qBAAmB;AAAA,MACnB,OAAO,UAAU,OAAO,aAAa,WAAW,WAAW;AAAA,MAC3D,WAAWC,MAAAA;AAAAA,QACTC,cAAAA,cAAc,EAAE,SAAS,WAAW,MAAM,MAAM;AAAA,QAChD;AAAA,QACA,UAAU,WAAW;AAAA,QACrB,UAAU,mBAAmB;AAAA,QAC7B,UAAU,YAAY;AAAA,QACtB;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,GAAI,eAAe,SAAY,EAAE,MAAA,IAAU,CAAA;AAAA,QAC3C,GAAI,UAAU,UAAU,EAAE,iBAAiB,sBAAsB,eAAe,SAAY,QAAQ,cAAc,qBAAA,IAAyB,CAAA;AAAA,MAAC;AAAA,MAG7I,UAAA;AAAA,QAAA,SAAS,UAAaC,+BAAC,QAAA,EAAK,oBAAgB,MAAC,eAAW,MAAC,WAAU,sEAClE,yCAACC,WAAA,EAAK,MAAY,OAAM,UAAS,WAAWH,MAAAA,GAAG,qCAAqC,aAAa,GAAG,EAAA,CACtG;AAAA,QACC,OAAO,aAAa,WACjBE,2BAAAA,IAACE,SAAAA,YAAS,MAAM,UAAW,GAAI,aAAa,SAAY,EAAE,aAAa,CAAA,GAAK,WAAU,oBAAmB,IACzGF,+BAAC,QAAA,EAAK,WAAU,6BAA6B,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGhE;;"}
@@ -0,0 +1,21 @@
1
+ import { HTMLAttributes, ReactElement } from 'react';
2
+ import { StaticIconComponent } from './Icon.js';
3
+ export type SymbolBadgeStyle = "badge" | "badge-outline" | "inline";
4
+ export type SymbolBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, "style" | "color" | "children"> & {
5
+ /** Filled badge, colored outline, or an unframed inline symbol. */
6
+ style?: SymbolBadgeStyle;
7
+ /** Named palette hue or CSS color, including CSS custom properties. */
8
+ color?: string;
9
+ /** Imported icon component placed before the symbol. */
10
+ icon?: StaticIconComponent;
11
+ /** Additional glyph classes, including adjustments for fixed-color SVGs. */
12
+ iconClassName?: string;
13
+ } & ({
14
+ children: string;
15
+ language?: string;
16
+ } | {
17
+ children: ReactElement;
18
+ language?: never;
19
+ });
20
+ export declare function SymbolBadge({ style, color, icon, iconClassName, language, children, className, title, ...props }: SymbolBadgeProps): import("react").JSX.Element;
21
+ //# sourceMappingURL=SymbolBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SymbolBadge.d.ts","sourceRoot":"","sources":["../../src/data/SymbolBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAI/E,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAaxD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,eAAe,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG;IACrG,mEAAmE;IACnE,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,CACA;IAA8D,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACnG;IAAkE,QAAQ,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,CAC/G,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,KAAe,EACf,KAAgB,EAChB,IAAI,EACJ,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,gBAAgB,+BAgClB"}
@@ -0,0 +1,61 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { isValidElement } from "react";
3
+ import { cn } from "../lib/utils.js";
4
+ import { badgeVariants } from "./badge-variants.js";
5
+ import { CodeLine } from "./CodeLine.js";
6
+ import { Icon } from "./Icon.js";
7
+ const COLORS = /* @__PURE__ */ new Map([
8
+ ["neutral", "text-foreground"],
9
+ ["primary", "text-primary"],
10
+ ["blue", "text-blue-700 [[data-theme=dark]_&]:text-blue-300"],
11
+ ["cyan", "text-cyan-700 [[data-theme=dark]_&]:text-cyan-300"],
12
+ ["indigo", "text-indigo-700 [[data-theme=dark]_&]:text-indigo-300"],
13
+ ["sky", "text-sky-700 [[data-theme=dark]_&]:text-sky-300"],
14
+ ["slate", "text-slate-700 [[data-theme=dark]_&]:text-slate-300"],
15
+ ["violet", "text-violet-700 [[data-theme=dark]_&]:text-violet-300"]
16
+ ]);
17
+ function SymbolBadge({
18
+ style = "badge",
19
+ color = "indigo",
20
+ icon,
21
+ iconClassName,
22
+ language,
23
+ children,
24
+ className,
25
+ title,
26
+ ...props
27
+ }) {
28
+ if (typeof children === "string" ? !children.trim() || /[\r\n]/.test(children) : !isValidElement(children)) {
29
+ throw new Error("SymbolBadge requires a nonempty, single-line symbol; use CodeBlock for multiline source.");
30
+ }
31
+ const colorClass = COLORS.get(color);
32
+ return /* @__PURE__ */ jsxs(
33
+ "span",
34
+ {
35
+ ...props,
36
+ "data-symbol-style": style,
37
+ title: title ?? (typeof children === "string" ? children : void 0),
38
+ className: cn(
39
+ badgeVariants({ variant: "outline", size: "md" }),
40
+ "max-w-full items-baseline gap-1.5 rounded-md align-baseline text-[12px] leading-4",
41
+ style === "badge" && "border-transparent",
42
+ style === "badge-outline" && "border-current",
43
+ style === "inline" && "rounded-none border-0 p-0",
44
+ colorClass,
45
+ className
46
+ ),
47
+ style: {
48
+ ...colorClass === void 0 ? { color } : {},
49
+ ...style === "badge" ? { backgroundColor: `color-mix(in srgb, ${colorClass === void 0 ? color : "currentColor"} 16%, transparent)` } : {}
50
+ },
51
+ children: [
52
+ icon !== void 0 && /* @__PURE__ */ jsx("span", { "data-symbol-icon": true, "aria-hidden": true, className: "relative w-[1.25em] shrink-0 before:invisible before:content-['.']", children: /* @__PURE__ */ jsx(Icon, { icon, width: "1.25em", className: cn("absolute top-1/2 -translate-y-1/2", iconClassName) }) }),
53
+ typeof children === "string" ? /* @__PURE__ */ jsx(CodeLine, { code: children, ...language !== void 0 ? { language } : {}, className: "min-w-0 truncate" }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 whitespace-normal", children })
54
+ ]
55
+ }
56
+ );
57
+ }
58
+ export {
59
+ SymbolBadge
60
+ };
61
+ //# sourceMappingURL=SymbolBadge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SymbolBadge.js","sources":["../../src/data/SymbolBadge.tsx"],"sourcesContent":["import { isValidElement, type HTMLAttributes, type ReactElement } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { badgeVariants } from \"./badge-variants\";\nimport { CodeLine } from \"./CodeLine\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\n\nconst COLORS = new Map([\n [\"neutral\", \"text-foreground\"],\n [\"primary\", \"text-primary\"],\n [\"blue\", \"text-blue-700 [[data-theme=dark]_&]:text-blue-300\"],\n [\"cyan\", \"text-cyan-700 [[data-theme=dark]_&]:text-cyan-300\"],\n [\"indigo\", \"text-indigo-700 [[data-theme=dark]_&]:text-indigo-300\"],\n [\"sky\", \"text-sky-700 [[data-theme=dark]_&]:text-sky-300\"],\n [\"slate\", \"text-slate-700 [[data-theme=dark]_&]:text-slate-300\"],\n [\"violet\", \"text-violet-700 [[data-theme=dark]_&]:text-violet-300\"],\n]);\n\nexport type SymbolBadgeStyle = \"badge\" | \"badge-outline\" | \"inline\";\n\nexport type SymbolBadgeProps = Omit<HTMLAttributes<HTMLSpanElement>, \"style\" | \"color\" | \"children\"> & {\n /** Filled badge, colored outline, or an unframed inline symbol. */\n style?: SymbolBadgeStyle;\n /** Named palette hue or CSS color, including CSS custom properties. */\n color?: string;\n /** Imported icon component placed before the symbol. */\n icon?: StaticIconComponent;\n /** Additional glyph classes, including adjustments for fixed-color SVGs. */\n iconClassName?: string;\n} & (\n | { /** Literal, nonempty, single-line symbol or expression. */ children: string; language?: string }\n | { /** Content already formatted by the caller, such as MathML. */ children: ReactElement; language?: never }\n);\n\nexport function SymbolBadge({\n style = \"badge\",\n color = \"indigo\",\n icon,\n iconClassName,\n language,\n children,\n className,\n title,\n ...props\n}: SymbolBadgeProps) {\n if (typeof children === \"string\" ? !children.trim() || /[\\r\\n]/.test(children) : !isValidElement(children)) {\n throw new Error(\"SymbolBadge requires a nonempty, single-line symbol; use CodeBlock for multiline source.\");\n }\n const colorClass = COLORS.get(color);\n return (\n <span\n {...props}\n data-symbol-style={style}\n title={title ?? (typeof children === \"string\" ? children : undefined)}\n className={cn(\n badgeVariants({ variant: \"outline\", size: \"md\" }),\n \"max-w-full items-baseline gap-1.5 rounded-md align-baseline text-[12px] leading-4\",\n style === \"badge\" && \"border-transparent\",\n style === \"badge-outline\" && \"border-current\",\n style === \"inline\" && \"rounded-none border-0 p-0\",\n colorClass,\n className,\n )}\n style={{\n ...(colorClass === undefined ? { color } : {}),\n ...(style === \"badge\" ? { backgroundColor: `color-mix(in srgb, ${colorClass === undefined ? color : \"currentColor\"} 16%, transparent)` } : {}),\n }}\n >\n {icon !== undefined && <span data-symbol-icon aria-hidden className=\"relative w-[1.25em] shrink-0 before:invisible before:content-['.']\">\n <Icon icon={icon} width=\"1.25em\" className={cn(\"absolute top-1/2 -translate-y-1/2\", iconClassName)} />\n </span>}\n {typeof children === \"string\"\n ? <CodeLine code={children} {...(language !== undefined ? { language } : {})} className=\"min-w-0 truncate\" />\n : <span className=\"min-w-0 whitespace-normal\">{children}</span>}\n </span>\n );\n}\n"],"names":[],"mappings":";;;;;;AAMA,MAAM,6BAAa,IAAI;AAAA,EACrB,CAAC,WAAW,iBAAiB;AAAA,EAC7B,CAAC,WAAW,cAAc;AAAA,EAC1B,CAAC,QAAQ,mDAAmD;AAAA,EAC5D,CAAC,QAAQ,mDAAmD;AAAA,EAC5D,CAAC,UAAU,uDAAuD;AAAA,EAClE,CAAC,OAAO,iDAAiD;AAAA,EACzD,CAAC,SAAS,qDAAqD;AAAA,EAC/D,CAAC,UAAU,uDAAuD;AACpE,CAAC;AAkBM,SAAS,YAAY;AAAA,EAC1B,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,MAAI,OAAO,aAAa,WAAW,CAAC,SAAS,KAAA,KAAU,SAAS,KAAK,QAAQ,IAAI,CAAC,eAAe,QAAQ,GAAG;AAC1G,UAAM,IAAI,MAAM,0FAA0F;AAAA,EAC5G;AACA,QAAM,aAAa,OAAO,IAAI,KAAK;AACnC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ,qBAAmB;AAAA,MACnB,OAAO,UAAU,OAAO,aAAa,WAAW,WAAW;AAAA,MAC3D,WAAW;AAAA,QACT,cAAc,EAAE,SAAS,WAAW,MAAM,MAAM;AAAA,QAChD;AAAA,QACA,UAAU,WAAW;AAAA,QACrB,UAAU,mBAAmB;AAAA,QAC7B,UAAU,YAAY;AAAA,QACtB;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,GAAI,eAAe,SAAY,EAAE,MAAA,IAAU,CAAA;AAAA,QAC3C,GAAI,UAAU,UAAU,EAAE,iBAAiB,sBAAsB,eAAe,SAAY,QAAQ,cAAc,qBAAA,IAAyB,CAAA;AAAA,MAAC;AAAA,MAG7I,UAAA;AAAA,QAAA,SAAS,UAAa,oBAAC,QAAA,EAAK,oBAAgB,MAAC,eAAW,MAAC,WAAU,sEAClE,8BAAC,MAAA,EAAK,MAAY,OAAM,UAAS,WAAW,GAAG,qCAAqC,aAAa,GAAG,EAAA,CACtG;AAAA,QACC,OAAO,aAAa,WACjB,oBAAC,YAAS,MAAM,UAAW,GAAI,aAAa,SAAY,EAAE,aAAa,CAAA,GAAK,WAAU,oBAAmB,IACzG,oBAAC,QAAA,EAAK,WAAU,6BAA6B,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGhE;"}
@@ -4,20 +4,83 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
5
  const reactQuery = require("@tanstack/react-query");
6
6
  const utils = require("../lib/utils.cjs");
7
+ const format = require("../lib/format.cjs");
8
+ const useResourceClock = require("../hooks/use-resource-clock.cjs");
7
9
  const useTaskRun = require("../hooks/use-task-run.cjs");
8
10
  const Icon = require("./Icon.cjs");
11
+ const DataTable = require("./DataTable.cjs");
12
+ const tagUtils = require("./cells/tag-utils.cjs");
9
13
  const ProgressBar = require("./ProgressBar.cjs");
10
- const Timestamp = require("./cells/Timestamp.cjs");
11
14
  const TaskProgress = require("./TaskProgress.cjs");
12
15
  const taskWorkProgress = require("./task-work-progress.cjs");
13
16
  const taskQueryKeys = require("./task-query-keys.cjs");
14
17
  const taskStatus = require("./task-status.cjs");
18
+ const progressColumn = {
19
+ key: "progress",
20
+ label: "Progress",
21
+ minWidth: 180,
22
+ accessor: (row) => taskWorkProgress.taskWorkProgress(row.run).done,
23
+ render: (_, row) => {
24
+ const progress = taskWorkProgress.taskWorkProgress(row.run);
25
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-36 space-y-1", children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs tabular-nums text-muted-foreground", children: progress.label }),
27
+ progress.total > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar.ProgressBar, { segments: taskStatus.taskSegments(progress.counts), total: progress.total, height: "h-1.5" })
28
+ ] });
29
+ }
30
+ };
31
+ const startedColumn = { key: "startedAt", label: "Started", kind: "timestamp", sortable: true };
32
+ const durationColumn = {
33
+ key: "duration",
34
+ label: "Duration",
35
+ sortable: true,
36
+ accessor: (row) => row.startedAt ? Date.parse(row.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString()) - Date.parse(row.startedAt) : null,
37
+ render: (_, row) => /* @__PURE__ */ jsxRuntime.jsx(RunDuration, { startedAt: row.startedAt, finishedAt: row.finishedAt })
38
+ };
39
+ const runColumns = [
40
+ { key: "name", label: "Run", sortable: true, grow: true, minWidth: 220 },
41
+ {
42
+ key: "status",
43
+ label: "Status",
44
+ sortable: true,
45
+ render: (_, row) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: utils.cn("inline-flex items-center gap-1.5 capitalize", taskStatus.taskStatusColor(row.status)), children: [
46
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: taskStatus.taskStatusIcon(row.status), ...row.status === "running" ? { className: "animate-spin" } : {} }),
47
+ row.status
48
+ ] })
49
+ },
50
+ durationColumn,
51
+ progressColumn,
52
+ { key: "labels", label: "Labels", kind: "tags", tags: { maxVisible: 2 }, minWidth: 160 },
53
+ startedColumn,
54
+ { key: "finishedAt", label: "Finished", kind: "timestamp", sortable: true }
55
+ ];
56
+ const compactRunColumns = [
57
+ {
58
+ key: "name",
59
+ label: "Run",
60
+ sortable: true,
61
+ grow: true,
62
+ minWidth: 220,
63
+ render: (_, row) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: row.name }),
65
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
66
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: applicationLabel(row.kind) }),
67
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: utils.cn("inline-flex items-center gap-1 capitalize", taskStatus.taskStatusColor(row.status)), children: [
68
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: taskStatus.taskStatusIcon(row.status) }),
69
+ row.status
70
+ ] })
71
+ ] })
72
+ ] })
73
+ },
74
+ progressColumn,
75
+ startedColumn
76
+ ];
15
77
  function TaskManager({
16
78
  basePath,
17
79
  kind,
18
80
  labels,
19
81
  pollMs,
20
82
  className,
83
+ compact,
21
84
  selectedId,
22
85
  onSelectRun,
23
86
  extraTabs,
@@ -25,13 +88,21 @@ function TaskManager({
25
88
  }) {
26
89
  const [kindFilter, setKindFilter] = react.useState(kind ?? "");
27
90
  const [statusFilter, setStatusFilter] = react.useState("");
91
+ const [labelFilter, setLabelFilter] = react.useState("");
92
+ const [filterOptions, setFilterOptions] = react.useState({ kinds: [], labels: [] });
93
+ const [localSelectedId, setLocalSelectedId] = react.useState(null);
28
94
  const queryClient = reactQuery.useQueryClient();
29
95
  const apiBase = basePath ?? "/api/v1";
30
96
  const activeKind = kind ?? (kindFilter || void 0);
97
+ const activeLabels = react.useMemo(() => {
98
+ if (!labelFilter) return labels;
99
+ const selected = tagUtils.splitTagToken(labelFilter);
100
+ return { ...labels, [selected.key]: selected.value };
101
+ }, [labels, labelFilter]);
31
102
  const { runs, runsKey, status } = useTaskRun.useTaskRuns({
32
103
  basePath: apiBase,
33
104
  kind: activeKind,
34
- labels,
105
+ labels: activeLabels,
35
106
  status: statusFilter || void 0,
36
107
  pollMs
37
108
  });
@@ -40,79 +111,88 @@ function TaskManager({
40
111
  basePath: apiBase,
41
112
  kind: activeKind,
42
113
  status: statusFilter || void 0,
43
- labels
114
+ labels: activeLabels
44
115
  }),
45
- [activeKind, apiBase, labels, statusFilter]
116
+ [activeKind, apiBase, activeLabels, statusFilter]
46
117
  );
47
118
  react.useEffect(() => {
48
119
  if (!runsKey || reactQuery.hashKey(runsKey) !== reactQuery.hashKey(runsQueryKey)) return;
49
120
  queryClient.setQueryData(runsQueryKey, runs);
50
121
  }, [queryClient, runs, runsKey, runsQueryKey]);
51
- const kinds = react.useMemo(() => {
52
- const set = /* @__PURE__ */ new Set();
53
- for (const r of runs) if (r.kind) set.add(r.kind);
54
- return [...set].sort();
122
+ react.useEffect(() => {
123
+ setFilterOptions((previous) => {
124
+ const kinds = [.../* @__PURE__ */ new Set([...previous.kinds, ...runs.flatMap((run) => run.kind ? [run.kind] : [])])].sort();
125
+ const labels2 = [.../* @__PURE__ */ new Set([...previous.labels, ...runs.flatMap((run) => Object.entries(run.labels ?? {}).map(([key, value]) => `${key}=${value}`))])].sort();
126
+ if (kinds.length === previous.kinds.length && labels2.length === previous.labels.length) return previous;
127
+ return { kinds, labels: labels2 };
128
+ });
55
129
  }, [runs]);
56
- const applications = react.useMemo(() => groupRunsByApplication(runs), [runs]);
57
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("space-y-3", className), children: [
58
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
59
- !kind && /* @__PURE__ */ jsxRuntime.jsxs(
60
- "select",
61
- {
62
- className: "rounded-md border bg-background px-2 py-1 text-xs",
63
- value: kindFilter,
64
- onChange: (e) => setKindFilter(e.target.value),
65
- children: [
66
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "All kinds" }),
67
- kinds.map((k) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: k, children: k }, k))
68
- ]
69
- }
70
- ),
71
- /* @__PURE__ */ jsxRuntime.jsxs(
72
- "select",
73
- {
74
- className: "rounded-md border bg-background px-2 py-1 text-xs",
75
- value: statusFilter,
76
- onChange: (e) => setStatusFilter(e.target.value),
77
- children: [
78
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Any status" }),
79
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "running", children: "Running" }),
80
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
81
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "success", children: "Success" }),
82
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "failed", children: "Failed" }),
83
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "warning", children: "Warning" }),
84
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" })
85
- ]
86
- }
87
- ),
88
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: status })
89
- ] }),
90
- runs.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed p-6 text-center text-sm text-muted-foreground", children: "No background tasks." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: applications.map((application) => /* @__PURE__ */ jsxRuntime.jsxs("section", { children: [
91
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-1 px-1 text-xs font-semibold text-muted-foreground", children: applicationLabel(application.kind) }),
92
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-lg border bg-card", children: application.runs.map((run) => /* @__PURE__ */ jsxRuntime.jsx(
93
- RunRow,
130
+ const filters = [
131
+ ...!kind ? [{ key: "kind", kind: "enum", label: "Kind", placeholder: "All kinds", value: kindFilter, options: filterOptions.kinds.map((value) => ({ value, label: applicationLabel(value) })), onChange: setKindFilter }] : [],
132
+ { key: "status", kind: "enum", label: "Status", placeholder: "Any status", value: statusFilter, options: [
133
+ { value: "running", label: "Running" },
134
+ { value: "pending", label: "Pending" },
135
+ { value: "success", label: "Success" },
136
+ { value: "failed", label: "Failed" },
137
+ { value: "warning", label: "Warning" },
138
+ { value: "canceled", label: "Canceled" }
139
+ ], onChange: setStatusFilter },
140
+ {
141
+ key: "labels",
142
+ kind: "enum",
143
+ label: "Labels",
144
+ placeholder: "Any label",
145
+ value: labelFilter,
146
+ options: filterOptions.labels.filter((token) => !(tagUtils.splitTagToken(token).key in (labels ?? {}))).map((value) => ({ value })),
147
+ onChange: setLabelFilter
148
+ }
149
+ ];
150
+ const rows = react.useMemo(() => runs.map((run) => ({
151
+ id: run.id,
152
+ name: run.name,
153
+ kind: run.kind || "other",
154
+ status: run.status,
155
+ ...run.startedAt ? { startedAt: run.startedAt } : {},
156
+ ...run.finishedAt ? { finishedAt: run.finishedAt } : {},
157
+ ...run.labels ? { labels: run.labels } : {},
158
+ run
159
+ })), [runs]);
160
+ const openId = onSelectRun ? selectedId : localSelectedId;
161
+ return /* @__PURE__ */ jsxRuntime.jsx(
162
+ DataTable.DataTable,
163
+ {
164
+ ...className ? { className } : {},
165
+ data: rows,
166
+ columns: compact ? compactRunColumns : runColumns,
167
+ emptyMessage: "No background tasks.",
168
+ externalFilters: filters,
169
+ filterBarProps: { trailing: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: status }) },
170
+ getRowId: (row) => row.id,
171
+ defaultSort: { key: "startedAt", dir: "desc" },
172
+ expandedRowIds: openId ? [openId] : [],
173
+ onExpandedRowIdsChange: (ids) => {
174
+ const next = ids.find((id) => id !== openId) ?? null;
175
+ if (onSelectRun) onSelectRun(next);
176
+ else setLocalSelectedId(next);
177
+ },
178
+ renderExpandedRow: (row) => /* @__PURE__ */ jsxRuntime.jsx(
179
+ ExpandedRun,
94
180
  {
95
- run,
181
+ run: row.run,
96
182
  basePath,
97
183
  pollMs,
98
- selectedId,
99
- onSelectRun,
100
184
  runsQueryKey,
101
185
  extraTabs,
102
186
  headerExtra
103
- },
104
- run.id
105
- )) })
106
- ] }, application.kind)) })
107
- ] });
187
+ }
188
+ )
189
+ }
190
+ );
108
191
  }
109
- function groupRunsByApplication(runs) {
110
- const grouped = /* @__PURE__ */ new Map();
111
- for (const run of runs) {
112
- const application = run.kind || "other";
113
- grouped.set(application, [...grouped.get(application) ?? [], run]);
114
- }
115
- return [...grouped].map(([kind, applicationRuns]) => ({ kind, runs: applicationRuns }));
192
+ function RunDuration({ startedAt, finishedAt }) {
193
+ const now = useResourceClock.useResourceClock(!!startedAt && !finishedAt);
194
+ if (!startedAt) return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "—" });
195
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: format.formatDuration(Math.max(0, (finishedAt ? Date.parse(finishedAt) : now) - Date.parse(startedAt))) });
116
196
  }
117
197
  function applicationLabel(kind) {
118
198
  const names = {
@@ -124,98 +204,15 @@ function applicationLabel(kind) {
124
204
  };
125
205
  return names[kind] ?? kind;
126
206
  }
127
- function RunRow({
128
- run,
129
- basePath,
130
- pollMs,
131
- selectedId,
132
- onSelectRun,
133
- runsQueryKey,
134
- extraTabs,
135
- headerExtra
136
- }) {
137
- const [localOpen, setLocalOpen] = react.useState(false);
138
- const controlled = onSelectRun !== void 0;
139
- const open = controlled ? selectedId === run.id : localOpen;
140
- const toggle = () => {
141
- if (controlled) onSelectRun(open ? null : run.id);
142
- else setLocalOpen((v) => !v);
143
- };
144
- const isTerminal = run.status !== "running" && run.status !== "pending";
145
- const progress = taskWorkProgress.taskWorkProgress(run);
146
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b last:border-0", children: [
147
- /* @__PURE__ */ jsxRuntime.jsxs(
148
- "button",
149
- {
150
- type: "button",
151
- className: "flex w-full items-center justify-between gap-4 px-4 py-3 text-left hover:bg-muted/50",
152
- onClick: toggle,
153
- children: [
154
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
155
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
156
- /* @__PURE__ */ jsxRuntime.jsx(
157
- Icon.Icon,
158
- {
159
- icon: taskStatus.taskStatusIcon(run.status),
160
- className: utils.cn(taskStatus.taskStatusColor(run.status), run.status === "running" && "animate-spin")
161
- }
162
- ),
163
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: run.name }),
164
- run.kind && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-muted px-1.5 py-0 text-[10px] text-muted-foreground", children: run.kind }),
165
- isTerminal && /* @__PURE__ */ jsxRuntime.jsx(
166
- "span",
167
- {
168
- className: utils.cn(
169
- "rounded-full px-2 py-0.5 text-xs",
170
- taskStatus.taskStatusColor(run.status),
171
- taskStatus.taskStatusBg(run.status)
172
- ),
173
- children: run.status
174
- }
175
- )
176
- ] }),
177
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-0.5 text-xs text-muted-foreground", children: [
178
- run.startedAt && /* @__PURE__ */ jsxRuntime.jsx(Timestamp.Timestamp, { value: run.startedAt, format: "relative" }),
179
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: progress.label }),
180
- Object.entries(run.labels ?? {}).map(([k, v]) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
181
- k,
182
- "=",
183
- v
184
- ] }, k))
185
- ] })
186
- ] }),
187
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-40 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
188
- ProgressBar.ProgressBar,
189
- {
190
- segments: taskStatus.taskSegments(progress.counts),
191
- total: progress.total || 1,
192
- height: "h-1.5"
193
- }
194
- ) })
195
- ]
196
- }
197
- ),
198
- open && /* @__PURE__ */ jsxRuntime.jsx(
199
- ExpandedRun,
200
- {
201
- runId: run.id,
202
- basePath,
203
- pollMs,
204
- runsQueryKey,
205
- extraTabs,
206
- headerExtra
207
- }
208
- )
209
- ] });
210
- }
211
207
  function ExpandedRun({
212
- runId,
208
+ run,
213
209
  basePath,
214
210
  pollMs,
215
211
  runsQueryKey,
216
212
  extraTabs,
217
213
  headerExtra
218
214
  }) {
215
+ const runId = run.id;
219
216
  const { snapshots, status } = useTaskRun.useTaskRun({ id: runId, basePath, pollMs });
220
217
  const apiBase = basePath ?? "/api/v1";
221
218
  const queryClient = reactQuery.useQueryClient();
@@ -264,19 +261,46 @@ function ExpandedRun({
264
261
  action,
265
262
  target: task
266
263
  });
267
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t bg-muted/30 px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(
268
- TaskProgress.TaskProgress,
269
- {
270
- snapshots,
271
- connectionStatus: status,
272
- compact: true,
273
- onControl: control,
274
- onTaskControl: controlTask,
275
- metricsBaseUrl: `${apiBase}/tasks/metrics/`,
276
- ...extraTabs ? { extraTabs } : {},
277
- ...headerExtra ? { headerExtra } : {}
278
- }
279
- ) });
264
+ const progress = taskWorkProgress.taskWorkProgress(run);
265
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 bg-muted/20 px-4 py-4", children: [
266
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-5 gap-y-1 text-xs text-muted-foreground", children: [
267
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
268
+ progress.completed,
269
+ " completed"
270
+ ] }),
271
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
272
+ progress.running,
273
+ " running"
274
+ ] }),
275
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
276
+ progress.failed,
277
+ " failed"
278
+ ] }),
279
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
280
+ progress.counts.pending + progress.unstarted,
281
+ " waiting"
282
+ ] }),
283
+ Object.entries(run.labels ?? {}).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
284
+ key,
285
+ "=",
286
+ value
287
+ ] }, key))
288
+ ] }),
289
+ /* @__PURE__ */ jsxRuntime.jsx(
290
+ TaskProgress.TaskProgress,
291
+ {
292
+ snapshots,
293
+ compact: true,
294
+ connectionStatus: status,
295
+ initialShowAllTasks: true,
296
+ onControl: control,
297
+ onTaskControl: controlTask,
298
+ metricsBaseUrl: `${apiBase}/tasks/metrics/`,
299
+ ...extraTabs ? { extraTabs } : {},
300
+ ...headerExtra ? { headerExtra } : {}
301
+ }
302
+ )
303
+ ] });
280
304
  }
281
305
  async function postTaskControl({ url, action, target }) {
282
306
  const context = `Failed to ${action} ${target.type} "${target.name}"`;